Skip to main content

Run in the secure (Kata) runtime

Inspect 1.36

The secure runtime class runs each pod in its own lightweight virtual machine, with its own kernel. If a process escapes the container it stays inside that VM, unable to reach the host or a neighbouring pod, even through a kernel-level bug. That is a harder boundary than a , which remaps UIDs but leaves every pod sharing the one host kernel. Use it when you run untrusted code, mix trust levels in one cluster, or cannot afford a kernel escape.

Where it runs#

The secure runtime is Kata Containers, and Kata boots a real kernel, so it needs bare-metal nodes with hardware virtualization (KVM). Hetzner Cloud VMs do not expose nested virtualization, so secure pods will not schedule on them. No bare-metal workers yet? first.

You wire up no node selector; the runtime class carries its own, so the scheduler steers secure pods onto capable nodes. When none is free the pod sits Pending; it never quietly drops back to the shared-kernel runtime.

Set the runtime class#

One line. Add runtimeClassName: secure to the pod spec; nothing else about the workload changes.

secure-deployment.yamlyaml
		apiVersion: apps/v1
kind: Deployment
metadata:
  name: secure-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: secure-app
  template:
    metadata:
      labels:
        app: secure-app
    spec:
      runtimeClassName: secure
      containers:
        - name: app
          image: nginx:stable
          resources:
            requests: # size for the container; the VM overhead is added on top
              cpu: "250m"
              memory: "128Mi"
	

Verify the VM boundary#

Compare the kernel the pod sees with the node's:

		$ kubectl exec <pod> -- uname -r
$ kubectl get node <node> -o jsonpath='{.status.nodeInfo.kernelVersion}'
	

The two versions differ: each secure pod runs its own guest kernel inside the VM. A standard-runtime pod reports the node's kernel, because it shares it.

What a drain does to a secure pod#

A secure pod is still a pod: cordon or drain its node and it evicts and reschedules like any workload. The cost lands only on the way back up: the guest kernel boots again before the container starts, eating into the pool's drain budget. The default nodeDrainTimeoutSeconds is 180s; raise it per pool if secure pods routinely need longer to hand off.

Limits to budget for#

  • Per-pod VM overhead. The VM layer costs roughly 250m CPU and 160Mi memory on top of the container's request.
  • hostNetwork and privileged are out. A pod that sets either cannot use the secure runtime.