Repository navigation
runsc: apply pod containers' swap limits to the sandbox cgroup - #16798
milantracy wants to merge 1 commit into
Conversation
|
Tested on the reproducer from #15756, on arm64, against the same tree without this change. Build: the diff at 8c867f3 applied to the
Under A note on the build, for anyone who tries it the same way: on the |
78e9527 to
bb8c5bd
Compare
bb8c5bd to
c2c3f32
Compare
|
Re-tested at c2c3f32 on the reproducer from #15756, the same way as in my earlier comment: the diff applied to the Node: kind v0.33.0,
12992512 is the sum of the kubelet's budgets for the two containers (8661801 + 4330900 bytes), rounded down to a page. With the systemd driver, the After a container goes away: with the loop in |
In a pod, all processes of the pod run in the cgroup of the sandbox. runsc configures that cgroup from the sandbox spec: the spec of the infrastructure (pause) container in a CRI pod, which has no swap limit. Kubernetes sets the swap limit on each application container instead (memory.swap.max=0 under the default NoSwap behavior on cgroup v2). runsc applied these limits only to the per-container compat cgroups, which have no processes. On a node with swap, a gVisor pod thus swapped without limit after it reached the memory limit of the pod cgroup, where a runc pod is OOM-killed. The swap support for pre-created cgroups (b393e6f) reads the pause container spec, so it does not apply here. Set memory.swap.max of the sandbox cgroup to the sum of the swap limits of the application containers, but not more than the swap limit of the sandbox spec, when a container starts, changes its resources, or is destroyed. If a container does not limit swap, only the sandbox spec limits it. This applies to CRI pods and to sandboxes without a root container. With the systemd driver, set the MemorySwapMax unit property. Hosts without swap accounting are skipped. Rootless permission errors are tolerated, as for the other cgroup settings, and a failure while a container is deleted is only logged. COMPATIBILITY:NEW-APP-CONFIG: Kubernetes nodes with swap and the default NoSwap swap behavior (also LimitedSwap), as reported in google#15756 on kind with both the systemd and cgroupfs drivers. gVisor pods ignored the swap limits. Assisted-by: Claude Opus 5.5 Signed-off-by: Jing Chen <milantracy@gmail.com>
c2c3f32 to
34442fd
Compare
…fix tested again Both on 11 November 2026: docker/sbx-releases#818 (issuecomment-6806741643) and google/gvisor#16798 (issuecomment-6801968334).
In a pod, all processes of the pod run in the cgroup of the sandbox. runsc configures that cgroup from the sandbox spec: the spec of the infrastructure (pause) container in a CRI pod, which has no swap limit. Kubernetes sets the swap limit on each application container instead (memory.swap.max=0 under the default NoSwap behavior on cgroup v2). runsc applied these limits only to the per-container compat cgroups, which have no processes. On a node with swap, a gVisor pod thus swapped without limit after it reached the memory limit of the pod cgroup, where a runc pod is OOM-killed. The swap support for pre-created cgroups (b393e6f) reads the pause container spec, so it does not apply here.
Set memory.swap.max of the sandbox cgroup to the sum of the swap limits of the application containers, but not more than the swap limit of the sandbox spec, when a container starts, changes its resources, or is destroyed. If a container does not limit swap, only the sandbox spec limits it. This applies to CRI pods and to sandboxes without a root container. With the systemd driver, set the MemorySwapMax unit property. Hosts without swap accounting are skipped. Rootless permission errors are tolerated, as for the other cgroup settings, and a failure while a container is deleted is only logged.
COMPATIBILITY:NEW-APP-CONFIG: Kubernetes nodes with swap and the default NoSwap swap behavior (also LimitedSwap), as reported in #15756 on kind with both the systemd and cgroupfs drivers. gVisor pods ignored the swap limits.
Fix #15756
Assisted-by: Claude Opus 5.5