📰 AI NewsDigital MarketingIntermediate✨ AI-assisted

Kubernetes Swap Packs Up to 3x More Sandboxes per Node

WittyTech Daily··4 min read
#kubernetes#swap#cgroup-v2#sandboxes

Headless-browser agents spend most of their lives waiting for the next prompt, and Kubernetes node swap now lets that idle memory move to disk. On October 5 the Kubernetes blog published benchmarks for it, including a node that went from 80 to 240 concurrent sandboxes, a 3x gain. Those are the authors' numbers from one Google Cloud setup, so treat them as a target to test, not a promise.

What the Kubernetes node swap post reports

The Kubernetes blog post by Ocean Xie and Yuan Wang says node swap reached general availability in v1.34. It targets a familiar waste: agent sandboxes need a lot of memory to start and run untrusted code, then sit idle while still holding it. That caps how many pods fit on a node.

Swap was discouraged for two reasons, per the post. Under cgroup v1, memory and swap shared one combined limit, and paging to slow spinning disks hurt. Swap support now relies on cgroup v2, which tracks swap separately, and fast NVMe Local SSDs largely remove the disk penalty.

The authors' results, all with Local SSD swap:

| Workload | Without swap | With swap | |---|---|---| | Python sandbox, gVisor | 80 sessions | 240 sessions | | Headless Chrome, gVisor | 80 pods | 160 pods | | Headless Chrome, Kata Containers | 40 pods | 50 pods | | Headless Chrome, plain runc (c4-standard-32, 120 GB) | 512 pods | 768 pods | | Linux kernel build | 600 MB limit | 300 MB limit |

The 3x headline is the Python test. The browser gains run from 1.25x to 2x, and Kata stopped at 50 pods because CPU saturated.

On latency, the authors say that at peak density the per-pod slowdown comes mainly from pods competing for CPU, not from swap I/O. They suggest running below peak if you have a latency target. The kernel build is the warning: at a 300 MB limit it finished in 374s versus 433s at 600 MB, but at 200 MB the working set spilled into swap and runtime rose over 40%. Swap is insurance for bursts, not a replacement for active RAM.

Why it matters for ad-check and QA browser agents

The post doesn't test ad verification, but headless Chrome sandboxes have the same shape: a memory burst while a page loads, then a long wait. If your marketing team runs agents that open landing pages, check ad creatives or run QA flows, much of your node memory is probably idle. The post calls memory often the first hard limit a cluster hits, so more sandboxes per node means fewer nodes.

There is a deadline attached. A second post on October 6 says that from v1.35 failCgroupV1 defaults to true, so the kubelet won't start on a cgroup v1 node, and the v1 fallback is scheduled for removal in v1.38. The swap prerequisite is also your upgrade homework.

Try Kubernetes node swap on one node pool

Confirm the node runs cgroup v2

stat -fc %T /sys/fs/cgroup/

The output cgroup2fs means cgroup v2 is enabled. Anything else, fix that first.

Enable LimitedSwap in the kubelet

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

failSwapOn: false lets the kubelet start on a node with swap. The default NoSwap keeps pods off it, and LimitedSwap lets them use it. Provision swap first, then restart the kubelet so it detects it. The swap docs encourage encrypted swap on a dedicated disk, not a partition on the root filesystem.

Leave room between request and limit

apiVersion: v1
kind: Pod
metadata:
  name: ad-check-browser
spec:
  tolerations:
    - key: gke-swap
      operator: Equal
      value: enabled
      effect: NoSchedule
  containers:
    - name: chrome
      image: <your-headless-chrome-image>
      resources:
        requests:
          cpu: 250m
          memory: 512Mi
        limits:
          memory: 1Gi

Only Burstable pods get swap, meaning the memory limit is above the request. A container's share is its memory request divided by node memory, times the swap available to pods. Request equal to limit means no swap. The toleration matches the taint in the next step.

On GKE, use the managed setting

linuxConfig:
  swapConfig:
    enabled: true

Save that as system-config.yaml, then create a tainted pool:

gcloud container node-pools create <nodepool-name> \
  --cluster=<cluster-name> \
  --location=<location> \
  --node-version=<1.34.1-gke.1341000-or-later> \
  --system-config-from-file=system-config.yaml \
  --machine-type=<machine-type-with-local-ssd>

The GKE docs require 1.34.1-gke.1341000 or later and a machine type that supports Local SSD (the default e2-medium doesn't). First- and second-generation series also need --ephemeral-storage-local-ssd. Swap is encrypted by default. Taint the pool, for example gke-swap=enabled:NoSchedule, as the docs suggest.

Measure before you pack

kubectl top nodes --show-swap
kubectl top pod --show-swap

Start below the post's peak counts and raise density until page-load time breaks your target.

Gotchas before you pack nodes tighter

  • The scheduler doesn't account for swap, so taint swap nodes or non-swap workloads will land there.
  • Guaranteed, BestEffort and high-priority pods get no swap.
  • Throttled cloud disks are much worse than SSD or NVMe, and the post's numbers used Local SSD.
  • A memory-hungry pod can force its neighbours into swap.
  • The docs recommend running control plane nodes without swap.

For anyone running browser agents in production, swap turns idle memory into capacity, provided you verify cgroup v2, limit it to Burstable pods and measure latency on your own hardware.

← More in Digital Marketing