k3s-io/k3s · critical
pids cgroup controller not found
Error message
pids cgroup controller not found
What it means
Before building kubelet args, cgroups.CheckCgs() scans /sys/fs/cgroup for available controllers; the 'pids' controller is mandatory (kubelet requires it for pod limits), so its absence is fatal. The 'cpu' controller absence is only a warning (CPU quotas disabled), contrasted inline.
Source
Thrown at pkg/daemons/agent/agent_linux.go:131
// If the embedded CCM is disabled, don't assume that dual-stack node IPs are safe.
// When using an external CCM, the user wants dual-stack node IPs, they will need to set the node-ip kubelet arg directly.
// This should be fine since most cloud providers have their own way of finding node IPs that doesn't depend on the kubelet
// setting them.
if cfg.DisableCCM {
dualStack, err := utilsnet.IsDualStackIPs(cfg.NodeIPs)
if err == nil && !dualStack {
argsMap["node-ip"] = cfg.NodeIP
}
} else {
argsMap["cloud-provider"] = "external"
if nodeIPs := util.JoinIPs(cfg.NodeIPs); nodeIPs != "" {
argsMap["node-ip"] = util.JoinIPs(cfg.NodeIPs)
}
}
kubeletRoot, runtimeRoot, controllers := cgroups.CheckCgroups()
if !controllers["pids"] {
return nil, nil, errors.New("pids cgroup controller not found")
}
if !controllers["cpu"] {
logrus.Warn("Disabling CPU quotas due to missing cpu controller or cpu.cfs_period_us")
defaultConfig.CPUCFSQuota = utilsptr.To(false)
}
if kubeletRoot != "" {
defaultConfig.KubeletCgroups = kubeletRoot
}
if runtimeRoot != "" {
argsMap["runtime-cgroups"] = runtimeRoot
}
argsMap["node-labels"] = strings.Join(cfg.NodeLabels, ",")
if ImageCredProvAvailable(cfg) {
logrus.Infof("Kubelet image credential provider bin dir and configuration file found.")
argsMap["image-credential-provider-bin-dir"] = cfg.ImageCredProvBinDir
argsMap["image-credential-provider-config"] = cfg.ImageCredProvConfigView on GitHub (pinned to 6ba341e396)
Solutions
- On the host verify: grep pids /sys/fs/cgroup/cgroup.controllers (v2) or existence of /sys/fs/cgroup/pids (v1).
- Run k3s directly on the host or in a properly privileged container (host cgroup namespace: --cgroupns=host, full /sys mount).
- Enable the pids controller in systemd slices (ensure no cgroup hierarchy excludes pids) and prefer cgroup v2 unified mode.
- For WSL2/old kernels, upgrade to a kernel with pids controller support.
Example fix
# before: pids hidden inside container docker run ... k3s server # after: expose host cgroups docker run --privileged --cgroupns=host -v /sys/fs/cgroup:/sys/fs/cgroup ... k3s server
Defensive patterns
Strategy: validation
Validate before calling
// Same probe CheckCgroups performs, as a pre-flight:
data, _ := os.ReadFile("/sys/fs/cgroup/cgroup.controllers") // cgroup v2
if !strings.Contains(string(data), "- pids") && !strings.Contains(string(data), "pids") {
if _, err := os.Stat("/sys/fs/cgroup/pids"); err != nil { // cgroup v1 fallback
return errors.New("pids controller unavailable: kubelet cannot run; fix host cgroups")
}
} Try / catch
if _, _, err := agent.KubeletArgs(cfg); err != nil {
if strings.Contains(err.Error(), "pids cgroup controller not found") {
// host-level fix: privileged container / cgroupns=host / enable pids; not retryable in-place
}
} Prevention
- Run k3s directly on hosts or in privileged containers with the host cgroup namespace.
- Include a pids-controller check in node bootstrap/pre-flight for clusters on VMs.
- Standardize on cgroup v2 unified mode; it makes pids delegation and detection deterministic.
When it happens
Trigger: Host has cgroup v1 without the pids controller; k3s runs inside a container whose /sys/fs/cgroup view hides pids; kernel booted with cgroup_no_pids or a minimal controller set; some WSL2/older-LTS kernels.
Common situations: Running k3s in Docker without --cgroupns=host / privileged; minimal VMs or NAS kernels lacking pids; cgroup v1 hybrid systems predating pids support.
Related errors
- delegated cgroup v2 controllers are required for rootless
- unhandled cgroup mode
- nix-store not found in PATH: install nix (https://nixos.org/
- value required for kubelet-arg --%s
- failed to find memory cgroup, you may need to add "cgroup_me
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/b048482c2659a068.
Report an issue: GitHub.