CKSKubernetes 1.35

Lessons

Sandboxed runtimes: gVisor, Kata, RuntimeClass

updated 2026-10-22 by seed

Why a sandbox

A container shares the host kernel. A kernel bug is a container escape. A
sandboxed runtime puts a real boundary in between:

  • gVisor (runsc) — a user-space kernel that implements the syscall surface; the container talks to runsc, not to the host kernel.
  • Kata Containers — a lightweight VM per Pod; the container runs on its own guest kernel.
  • Firecracker / microVM — same idea, minimal VMM.

Cost: syscall-heavy workloads are slower. The exam only cares that you can wire
one up.

The two objects

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata: {name: gvisor}
handler: runsc              # must match the runtime name in containerd
---
apiVersion: v1
kind: Pod
metadata: {name: sandboxed, namespace: prod}
spec:
  runtimeClassName: gvisor
  containers:
  - name: app
    image: registry.example.com/app:1.4.2

The handler is the containerd runtime key, not the binary path. A mismatch
gives RuntimeClass "gvisor" is not registered.

Installing gVisor on a node (what the task can ask you to do)

curl -fsSL https://gvisor.dev/archive.key | sudo gpg --dearmor -o /usr/share/keyrings/gvisor-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/gvisor-archive-keyring.gpg] https://storage.googleapis.com/gvisor/releases release main" | sudo tee /etc/apt/sources.list.d/gvisor.list
sudo apt-get update && sudo apt-get install -y runsc

Then register it with containerd — /etc/containerd/config.toml:

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc]
  runtime_type = "io.containerd.runsc.v1"
sudo systemctl restart containerd

Prove the sandbox is real

kubectl get pod sandboxed -n prod -o jsonpath='{.spec.runtimeClassName}'
kubectl get pod sandboxed -n prod -o jsonpath='{.status.containerStatuses[0].containerID}'
# on the node:
sudo crictl inspect <id> | grep -i runtimeType
sudo dmesg | grep -i gvisor      # gVisor prints its own banner

Inside a gVisor Pod, uname -r reports a gVisor kernel version, and
/proc/version mentions it. That is the cheap check.

Traps

  • A RuntimeClass that no node supports leaves the Pod Pending with no nodes available to schedule pods — the scheduler filters on the handler.
  • runtimeClassName is immutable on an existing Pod: recreate it.
  • Kata needs hardware virtualisation; gVisor does not. If grep -c vmx /proc/cpuinfo is 0, Kata is not a viable answer in that cluster.
  • The sandbox does not replace a securityContext: still drop capabilities and run non-root inside it.