Per-Distribution cgroup Isolation in WSL 2: What the Setting Does and Does Not Guarantee
Inspect WSL 2 per-distribution cgroup isolation, its cgroup v2 prerequisite, verification steps, and the limits of treating it as resource control.
WSL 2 runs Linux distributions on a shared utility virtual machine. That shared kernel and VM do not mean every distribution must be exposed to one undifferentiated cgroup view. Current WSL configuration documentation lists isolateDistroCgroup under the global [wsl2] settings, says it enables per-distribution cgroup isolation, and lists cgroup v2 as a requirement. The distinction is useful, but it is easy to overread: isolation is not the same as assigning a CPU or memory budget, nor does the setting turn distributions into security tenants comparable to separately managed virtual machines.
Treat the option as a boundary in the cgroup organization presented to distributions. Then inspect the effective Linux view and configure resource limits only where the relevant controller, hierarchy, and delegation model support them. The evidence is what the running guest exposes, not merely the text in .wslconfig.
The hierarchy and the WSL option are different layers
Linux cgroups organize processes into a hierarchy. Controllers account for or constrain resource classes such as CPU, memory, I/O, and process count. On cgroup v2, controllers are exposed through a unified hierarchy, and controller availability and delegation depend on how parent and child cgroups are configured. The kernel’s cgroup v2 documentation describes this model and its controller rules; it does not promise that every consumer receives every controller or can write every control file.
WSL’s isolateDistroCgroup option is a WSL VM configuration choice. It is not a numeric quota and does not itself set values such as cpu.max, memory.max, or pids.max. If a team needs a defined budget, it must separately configure and verify a supported limit at the level that owns the workload. The setting also should not be confused with the [wsl.conf] cgroups option, which selects the cgroup hierarchy version for a distribution. Microsoft’s current reference explicitly requires cgroup v2 for per-distro isolation.
Because .wslconfig applies to the shared WSL 2 VM, its location and scope matter. The file belongs in the Windows user’s profile, and changes may not be visible until the WSL VM has stopped and started again. The setting is global to WSL 2 rather than a per-distro switch. Do not assume a WSL 1 distribution has the same VM or cgroup behavior.
Establish the effective runtime state first
Record the Windows and WSL versions before comparing machines. WSL features and configuration keys have changed over time, and the current Microsoft reference is the authority for the setting’s documented scope. From PowerShell, capture:
wsl.exe --version
wsl.exe --status
wsl.exe --list --verbose
Get-Content "$env:USERPROFILE\.wslconfig" -ErrorAction SilentlyContinue
The last command may show a missing file or a file with unrelated settings; do not overwrite it to add one key. Merge the setting into the existing [wsl2] section, keeping only one section header. For example:
[wsl2]
isolateDistroCgroup=true
If an existing file already contains [wsl2], add the key to that section rather than creating a duplicate. After editing, stop the VM intentionally from Windows so the shared change can be loaded. wsl.exe --shutdown stops all running WSL 2 distributions, so save work and coordinate services first. Start the target distributions again and verify their Linux-visible hierarchy.
wsl.exe --shutdown
wsl.exe --distribution Ubuntu --exec sh -lc 'findmnt -t cgroup2; cat /proc/self/cgroup'
wsl.exe --distribution Debian --exec sh -lc 'findmnt -t cgroup2; cat /proc/self/cgroup'
These commands establish whether a cgroup2 filesystem is mounted and show the current process’s cgroup membership. They do not, by themselves, prove that a controller is active, that the distribution separation has the expected implementation detail, or that a service is constrained. Record the output from at least two distributions and compare it with the WSL version and exact configuration used. Avoid assuming a hard-coded /sys/fs/cgroup path proves isolation: mount namespaces and distribution setup can affect what a process sees.
Inspect controllers and ownership without changing them
Read the controller files before creating limits. This example is deliberately observational:
printf '%s\n' 'mounts:'
findmnt -t cgroup,cgroup2
printf '%s\n' 'current membership:'
cat /proc/self/cgroup
printf '%s\n' 'available root controllers:'
if test -r /sys/fs/cgroup/cgroup.controllers; then
cat /sys/fs/cgroup/cgroup.controllers
else
echo 'No cgroup v2 root controller list at this path'
fi
On a cgroup v2 mount, cgroup.controllers reports controllers available to that cgroup, not a promise that a particular service already has a limit. The Linux kernel documentation explains that a controller generally has to be enabled by a parent through cgroup.subtree_control before it is available to children. Delegation is constrained by the hierarchy rules. Do not blindly write to root cgroup control files from a shell, and do not enable controllers on a production host without understanding the manager that owns the tree.
If systemd is PID 1 in a distribution, use systemd unit or slice properties for managed workloads rather than hand-editing transient cgroup paths. If systemd is not running, use the distribution’s supported service manager or a deliberate cgroup manager. WSL cgroup isolation and a service manager’s delegation are separate questions. A workload may still be unrestricted even when distribution views are isolated.
What isolation is useful for
The option is relevant when the operator needs to distinguish resource accounting and cgroup organization for multiple WSL distributions that coexist in the shared VM. Examples include diagnosing whether a container manager is reporting the expected cgroup hierarchy, keeping per-distribution process accounting easier to interpret, and avoiding tooling that assumes every distribution’s process belongs to one visible cgroup tree. Those are verification goals, not performance guarantees.
It is also important to separate a cgroup hierarchy from a cgroup namespace. A namespace changes the view of paths and ancestors exposed to a process; cgroups account for and may limit tasks. The WSL configuration reference uses the phrase “per-distribution cgroup isolation,” but operators should not infer an undocumented namespace layout or assume that /proc/self/cgroup must contain a particular prefix. The reliable contract is the documented purpose and the observed runtime behavior on the exact WSL release being tested.
Container tooling may create nested cgroups below the distribution’s visible hierarchy. If a container reports that a controller is unavailable, collect the host distro’s controller list, the container’s cgroup namespace and mount view, and the runtime’s delegation configuration. A per-distribution WSL setting cannot grant a container manager permissions that its parent cgroup does not delegate. Likewise, a successful container startup does not prove memory or CPU controllers are enforcing the values declared in the container spec. Query the runtime’s effective state and the kernel’s controller counters.
Do not translate “per-distribution cgroup isolation” into a claim that one distribution cannot affect another. They still share a WSL VM and host resources. Unless explicit controller limits are applied and measured, a CPU-heavy process in one distribution can contend with another for host and VM execution. Memory pressure, disk throughput, GPU execution, and Windows scheduling are also not solved by this one setting. Nor is it an authorization boundary that makes untrusted code safe to run.
A controlled acceptance test
Use a disposable workload and collect baseline and post-change evidence. First record wsl.exe --version, Windows build, distro versions, .wslconfig, wsl.conf, findmnt, /proc/self/cgroup, and controller files from each participating distribution. Confirm cgroup v2 is the effective hierarchy where the feature is expected to apply. Then launch the same small process in two distributions and compare their Linux-visible membership and relevant manager-created cgroups. Do not assume their cgroup path strings must match a specific example from another release.
If the objective includes a resource ceiling, state the intended limit numerically and configure it using the supported manager for that workload. Run a repeatable CPU or memory test in each distribution while observing the relevant controller statistics and the Windows host. A passing isolation test means the intended separation is visible and workloads can be accounted for as designed; a passing quota test additionally requires the controller’s limit and usage counters to demonstrate enforcement. One does not imply the other.
Keep the test process itself simple and avoid changing the global root hierarchy during the observation. A stable load such as a bounded CPU loop can answer a CPU accounting question, while a memory allocation test should have a strict ceiling and run in a disposable distro. Record the workload command, duration, exit status, and counters before and after. Do not use a stress test as a substitute for reading the cgroup files: an application may exit due to its own limit, a Linux OOM event, a WSL memory ceiling, or host pressure, and those mechanisms are not interchangeable.
When results do not change after editing, check for duplicate .wslconfig sections, malformed syntax, editing a different Windows profile, WSL 1 versus WSL 2, and whether the shared VM fully stopped. Also inspect whether a distribution’s /etc/wsl.conf selects cgroup v1. Keep the test output with the WSL package version because a configuration reference can evolve independently of an installed runtime.
Operational decision
Enable per-distribution cgroup isolation only when there is an explicit need and the installed WSL build documents and exhibits the behavior. Keep the WSL VM configuration centrally managed where possible, but put workload limits in the service or container manager that owns them. Re-test after WSL updates, changes to .wslconfig, switching cgroup versions, or changing service managers. The safe conclusion is narrow: cgroup v2 is required by the current WSL reference, the setting enables per-distribution cgroup isolation, and resource ceilings still require their own supported configuration and measurement.
Related:
- WSL 2 and cgroup v2: Resource Control Inside the Linux VM
- Rootless Podman in WSL: cgroup v2, Storage, and systemd
Sources: