FR
live

Kubernetes triples pod density by enabling swap on NVMe SSDs

On October 5, 2026, an official Kubernetes blog post documents node swap, generally available since v1.34, with measured gains of up to 3× density on local SSD. Enable it for best-effort workloads and AI agents, but never to mask a memory leak.

An NVMe SSD caddy pulled halfway out of a server rack, its amber activity LED lit in the dark.

October 5, 2026. A Kubernetes blog post by Ocean Xie and Yuan Wang documents node swap, generally available since v1.34. 240 isolated pods on a single node, versus 80 without swap. 3×. That is the density gain measured on Python sandboxes. Why it matters: after years in which the kubelet refused to start with swap enabled, the platform is now officially embracing a mechanism that changes the economics of memory-oversubscribed nodes.

Why swap was forbidden

For nearly a decade, swap was off-limits in Kubernetes. The kubelet would simply refuse to start on a node where swap was mounted — failSwapOn: true was the default, and enabling swap meant explicitly overriding it. Two technical reasons justified the dogma.

The first is memory accounting. Under cgroup v1, the controller treated memory and swap as a single merged limit: there was no way to set an independent bound for disk swap. A container could therefore push a large share of its anonymous memory onto disk, making its real usage unpredictable and hard to isolate from a neighbour. The second brake was latency: paging to a slow spinning disk punished applications heavily, and the density benefit was wiped out by degraded response times.

The result: operators preferred to kill a pod cleanly with OOM rather than let it spill onto a slow, poorly accounted disk. A rational choice in the cgroup v1 plus spinning-disk world.

What changed

Both locks came off at once. cgroup v2 brings separate swap accounting: memory and disk swap are tracked independently, so you can set a distinct swap limit and know exactly what a container has paged out. And local NVMe SSDs dropped paging latency to a point where it no longer dominates the cost: page out the dormant memory, keep the active set in RAM.

The October 5 post formalizes the result. Node swap support has been GA since v1.34, and it rests on that pairing: cgroup v2 for accounting, NVMe for speed. On GKE, the mechanism is exposed natively through the Node Memory Swap feature configured on local SSD profiles.

The benchmark numbers

The post measures three workload families, quantifying the trade-off precisely.

WorkloadBaseline capacity (no swap)Local SSD swap capacityDensity improvement
Linux CI/CD kernel build600 MB RAM limit300 MB RAM limit−50% RAM footprint
Headless Chrome (Kata)40 pods50 pods+25%
Headless Chrome (gVisor)80 pods160 pods+100%
Python sandbox (gVisor)80 pods240 pods+200%

The kernel build case is the most instructive about what swap actually is. Compiling Linux 6.1.1 demands a big memory spike at link time, but leaves many compiled objects inactive in RAM the rest of the time — exactly the profile of a CI/CD pipeline. Without swap, a 600 MB limit was needed to avoid OOM. Routing swap to a local SSD cuts the limit to 300 MB, and the build finishes in 374 s versus 433 s without swap. But dropping to 200 MB forces the active working set into swap: execution time jumps by more than 40%. The lesson in one sentence — swap is insurance against spikes, not a substitute for RAM.

The agentic workloads tell the same story at greater scale. On a c4-standard-32 node (32 vCPU, 120 GB RAM), unsandboxed runc containers capped out at 512 pods; local SSD swap pushes the limit to 768. With strict security runtimes the effect is even clearer, because isolation has a memory cost: gVisor went from 80 to 160 pods, and Kata Containers from 40 to 50 microVMs. Isolated Python sandboxes — sessions analyzing 5 million rows of the MovieLens 20M dataset, with a resident footprint of about 375 MiB per execution — jumped from 80 to 240 concurrent sessions, a 3× improvement.

The telling detail: at these peak densities, the extra latency comes mainly from CPU contention between pods, not from swap I/O. An operator tuning for a specific latency target will run below the peak and see a proportionally smaller cost.

How to enable it

Enabling comes down to the kubelet configuration, dropping the historical lock and bounding the swap behaviour:

yaml
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
failSwapOn: false
memorySwap:
  swapBehavior: LimitedSwap

Two settings complete the mechanism. On the disk side, point swap at a fast local SSD — on GKE, enable Node Memory Swap on a local SSD profile. On the workload side, configure your workloads with Burstable QoS: set the container’s memory limit above its request. The node then automatically rations fast swap space based on idle application memory while keeping active processes responsive.

What it does not fix

Node swap is not a silver bullet, and the post says so plainly. First, it does not repair a memory leak: an application that allocates without releasing will saturate swap exactly as it would have saturated RAM, with the same eventual crash — just later and slower. Second, latency-critical workloads should stay in Guaranteed QoS: giving them a limit equal to their request excludes them from the mechanism and preserves response time. Finally, the gain assumes a fast local disk; routing swap to a slow network volume will reintroduce exactly the penalty NVMe removed.

Verdict

If you operate clusters hosting AI agents, sandboxes or CI/CD pipelines with long idle phases, enable node swap on local SSD today: the GKE numbers show up to 3× density, often with no measurable latency cost, on the same infrastructure. If your workloads are latency-critical, keep them in Guaranteed QoS and leave swap to Burstable pods — the mechanism is built to absorb spikes, not to carry your databases. If you are unsure about the principle, hold on to the post’s distinction: swap is insurance against memory spikes, never a replacement for RAM — and anyone who uses it to hide a leak will pay the bill later.

References

The cyber brief, every Tuesday

The flaws that matter and the patches to apply, in a ten-minute read.

No spam. One-click unsubscribe.
read next

On the same topic

GitHub makes open source license compliance a merge-blocking ruleset, generally available

On October 16, 2026, GitHub made open source license compliance generally available: a ruleset requires compliant results before merge and blocks any pull request that adds a dependency under an unacceptable license. For enterprises that already govern their dependencies, this is the shift from after-the-fact audit to a policy enforced in CI.

GitHub Actions freezes third-party actions to reviewed commits

On 14 October 2026, GitHub opened workflow lockfiles to public preview: every action and reusable workflow is pinned to a specific commit, so the code you reviewed is the code that runs. Turn on locking for your critical repositories before a moved tag slips malicious code into your CI.

← Back to the feed

Type at least two characters.

↑ ↓ navigate ↵ open esc dismiss