Checking the node dependencies of a cgroup v2 migration
Kubernetes now defaults to refusing kubelet startup on cgroup v1 nodes. Migration needs an inventory of runtime configuration and software that interprets cgroup files directly.
The Kubernetes project has published updated cgroup v2 migration guidance. The immediate upgrade concern is kubelet startup. Since Kubernetes 1.35, failCgroupV1 defaults to true. A node still using cgroup v1 therefore needs the temporary explicit override or a completed migration before the newer kubelet starts under its default configuration.
I would treat this as a node-platform change with workload acceptance checks. My eight years with Kubernetes include Talos clusters with Cilium and GitOps, so I am interested in keeping the running node configuration consistent with its declared setup. This migration also reaches software inside containers and monitoring agents that inspect cgroup files. A control-plane version check cannot establish their compatibility.
The change has a documented history. Kubernetes 1.31 moved cgroup v1 into maintenance mode, with no new functionality planned for that implementation. That announcement distinguished maintenance from deprecation. The October guidance describes the subsequent default startup restriction and the temporary escape hatch. An old maintenance-mode assessment therefore needs updating before a current node upgrade.
Verify the hierarchy on each Linux node
Cgroup v2 provides a unified hierarchy for resource controls. The guidance gives a filesystem check that reports cgroup2fs when v2 is enabled:
stat -fc %T /sys/fs/cgroup/
This command belongs on the node being evaluated. I would record its result with the operating-system and runtime configuration for every Linux node group. A successful check on one worker does not establish the state of a different image or bootstrap configuration.
The guidance requires a compatible kernel and runtime, with the kubelet and runtime using matching cgroup drivers. It identifies Linux 5.8 as the minimum kernel version for Kubernetes cgroup v2 support. It lists containerd 1.4 or later and CRI-O 1.20 or later as supporting v2. Those version requirements are distinct from automatic driver discovery, which needs additional runtime support.
Automatic discovery uses the CRI RuntimeConfig RPC. The article gives containerd 2.0 or later and CRI-O 1.28 or later as examples implementing that capability. When discovery is available, kubelet uses the driver reported by the runtime. I would inspect the effective driver arrangement before assuming that a manually configured kubelet field determines the result.
Temporary startup compatibility needs an owner
The documented override is failCgroupV1: false in kubelet configuration. I would use it only with an explicit migration issue and a record of which nodes depend on it. A successful startup under the override demonstrates continued use of the fallback. It does not establish completion of the cgroup v2 migration.
Kubeadm-managed installations have an earlier check as well. The October guidance says system verification rejects cgroup v1 for kubelet 1.35 or later during initialization, joining, and upgrading. I would account for the management tool's preflight behavior in the upgrade rehearsal. Editing kubelet configuration alone may not describe every stage at which an old node setup becomes unacceptable.
Resource files have different meanings
The article explains that cgroup v1 CPU shares become cgroup v2 CPU weights through runtime conversion. It identifies improved conversion behavior in crun 1.23 and runc 1.3.2. A tool predicting an exact cpu.weight value may therefore need revision after a runtime upgrade. I would test such tools against the runtime actually selected for the node image.
CPU weight and CPU limit also express different controls. The guidance maps the request-related weight to cpu.weight and the limit to cpu.max. It maps the memory limit to memory.max. I would preserve those distinctions when updating monitoring or policy checks. Reading a weight cannot establish that a container has the intended CPU quota.
The source recommends tracing a limit through the Kubernetes specification, enacted status, runtime configuration, and kernel files. In-place resizing can leave desired and enacted resources temporarily different. I would investigate that transition before interpreting a mismatch as a failed cgroup migration. The inspection needs to identify the exact container and node concerned.
Runtime behavior needs workload checks
On v2 nodes, the guidance says kubelet defaults singleProcessOOMKill to false and configures container-level grouped OOM handling. That concerns the processes in one container, not the entire pod. A multi-process application should be tested with the intended setting and recovery expectations. I would avoid translating a container-level statement into a pod-wide guarantee.
The article also warns that migrating does not by itself fix kubelet's treatment of active_file memory as unreclaimable. I would keep that issue separate when evaluating memory-pressure behavior for I/O-intensive applications. A new hierarchy does not establish a correction to every existing eviction calculation.
For acceptance, I would include agents and application runtimes that read cgroup files directly, then compare their observations with the node's effective resource controls. The migration record should identify any temporary overrides still required and any tools awaiting changes. Completion means the declared v2 setup supports the actual workloads and observability checks on each node group.