πŸ“šBook Signing at KubeCon EU 2026Meet us at Booking.com HQ (Mon 18:30-21:00) & vCluster booth #521 (Tue 24 Mar, 12:30-1:30pm) β€” free book giveaway!RSVP Booking.com Event
Security advanced ⏱ 20 minutes K8s 1.28+

Kata Containers RuntimeClass Kubernetes

Deploy Kata Containers with Kubernetes RuntimeClass for hardware-isolated pods. VM-based sandboxing, microVM configuration, and multi-runtime clusters.

By Luca Berton β€’ β€’ πŸ“– 5 min read

πŸ’‘ Quick Answer: Kata Containers runs pods inside lightweight VMs (microVMs) for hardware-level isolation. Install kata-containers on nodes, configure containerd with a kata runtime handler, create a RuntimeClass named kata, then set runtimeClassName: kata on pods. Each pod gets its own kernel β€” stronger isolation than gVisor, at the cost of ~100ms startup overhead and ~128MB memory per pod.

The Problem

Standard container isolation (namespaces + cgroups) shares the host kernel:

  • Kernel exploits affect all containers on the node
  • Multi-tenant clusters need stronger isolation
  • Compliance requirements (PCI-DSS, FedRAMP) may require VM-level isolation
  • Untrusted workloads (CI/CD runners, user-submitted code) risk host compromise

The Solution

Install Kata Containers

# Option 1: kata-deploy DaemonSet (recommended for Kubernetes)
kubectl apply -f https://raw.githubusercontent.com/kata-containers/kata-containers/main/tools/packaging/kata-deploy/kata-rbac/base/kata-rbac.yaml
kubectl apply -f https://raw.githubusercontent.com/kata-containers/kata-containers/main/tools/packaging/kata-deploy/kata-deploy/base/kata-deploy.yaml

# Wait for installation on all nodes
kubectl -n kube-system wait --for=condition=Ready pod -l name=kata-deploy --timeout=300s

# Option 2: Package manager (per-node)
# Ubuntu/Debian
sudo apt install kata-containers

# RHEL/CentOS
sudo dnf install kata-containers

Configure containerd Runtime

# /etc/containerd/config.toml
# kata-deploy adds this automatically, but for manual setup:

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata]
  runtime_type = "io.containerd.kata.v2"
  privileged_without_host_devices = true
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata.options]
    ConfigPath = "/opt/kata/share/defaults/kata-containers/configuration.toml"

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-qemu]
  runtime_type = "io.containerd.kata.v2"
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-qemu.options]
    ConfigPath = "/opt/kata/share/defaults/kata-containers/configuration-qemu.toml"

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-clh]
  runtime_type = "io.containerd.kata.v2"
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-clh.options]
    ConfigPath = "/opt/kata/share/defaults/kata-containers/configuration-clh.toml"

Create RuntimeClass

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: kata
handler: kata           # Matches containerd runtime name
overhead:
  podFixed:
    memory: "160Mi"     # VM overhead per pod
    cpu: "250m"
scheduling:
  nodeSelector:
    katacontainers.io/kata-runtime: "true"

---
# Cloud-Hypervisor variant (faster startup)
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: kata-clh
handler: kata-clh
overhead:
  podFixed:
    memory: "130Mi"
    cpu: "200m"
scheduling:
  nodeSelector:
    katacontainers.io/kata-runtime: "true"

Use in Pods

apiVersion: v1
kind: Pod
metadata:
  name: isolated-workload
spec:
  runtimeClassName: kata      # ← This runs the pod in a microVM
  containers:
  - name: app
    image: nginx:1.27
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 500m
        memory: 256Mi

---
# CI/CD runner with untrusted code
apiVersion: batch/v1
kind: Job
metadata:
  name: ci-build
spec:
  template:
    spec:
      runtimeClassName: kata
      containers:
      - name: builder
        image: docker.io/library/golang:1.22
        command: ["go", "test", "./..."]
        securityContext:
          runAsNonRoot: true
          runAsUser: 1000
      restartPolicy: Never

Kata vs gVisor vs runc

Featurerunc (default)gVisor (runsc)Kata Containers
IsolationNamespaces + cgroupsUser-space kernelHardware VM
KernelShared host kernelGo-based guest kernelLinux guest kernel
Startup~100ms~200ms~500ms (QEMU), ~200ms (CLH)
Memory overheadNone~50MB~128-160MB
Syscall compat100%~80% (limited)~99% (full kernel)
GPU supportβœ…βŒβœ… (VFIO passthrough)
Nested containersβœ…βŒβœ…
Best forGeneral workloadsUntrusted simple appsFull isolation + compat

Hypervisor Options

# Check available hypervisors
ls /opt/kata/share/defaults/kata-containers/configuration-*.toml

# QEMU β€” most compatible, slower startup
kata-runtime kata-env | grep -A5 Hypervisor
# Hypervisor: QEMU

# Cloud-Hypervisor (CLH) β€” faster, recommended for production
# Edit kata configuration:
sudo sed -i 's/default_hypervisor = "qemu"/default_hypervisor = "cloud-hypervisor"/' \
  /opt/kata/share/defaults/kata-containers/configuration.toml

# Firecracker β€” AWS-style microVM, fastest but limited features

Verify Isolation

# Inside a Kata pod β€” separate kernel!
kubectl exec -it isolated-workload -- uname -r
# 6.1.0-kata  ← Guest kernel, NOT host kernel

# Compare with standard pod
kubectl exec -it normal-pod -- uname -r
# 6.5.0-host  ← Host kernel

# Check VM from host
ps aux | grep qemu
# qemu-system-x86_64 ... -name sandbox-abc123 ...

Common Issues

β€œkata runtime not found” or β€œhandler kata not registered”

kata-deploy DaemonSet hasn’t finished or containerd wasn’t restarted. Check: kubectl get pods -n kube-system -l name=kata-deploy.

Pod startup takes 5+ seconds

Use Cloud-Hypervisor (kata-clh) instead of QEMU β€” 2-3x faster startup. Or use Firecracker for even faster cold starts.

β€œnested virtualization required”

Kata needs hardware virtualization (VT-x/AMD-V). On cloud VMs, ensure nested virtualization is enabled. Bare metal always works.

GPU passthrough not working

Kata supports GPU via VFIO β€” requires IOMMU enabled and GPU assigned to VFIO driver. Not transparent like runc GPU access.

Best Practices

  • Use kata-clh in production β€” Cloud-Hypervisor is faster and more resource-efficient than QEMU
  • Set overhead on RuntimeClass β€” scheduler accounts for VM memory/CPU
  • Kata for multi-tenant isolation β€” run untrusted workloads in VMs
  • runc for trusted workloads β€” no need for VM overhead on trusted code
  • Combine with Pod Security Standards β€” defense in depth

Key Takeaways

  • Kata Containers runs each pod in a lightweight VM for hardware-level isolation
  • Create a RuntimeClass and set runtimeClassName: kata on pods
  • Cloud-Hypervisor is the recommended hypervisor (faster than QEMU)
  • ~128MB memory overhead per pod β€” use selectively for untrusted workloads
  • Full kernel inside VM means near-100% syscall compatibility unlike gVisor
#kata-containers #runtimeclass #security #sandboxing #microvm
Luca Berton
Written by Luca Berton

Principal Solutions Architect specializing in Kubernetes, AI/GPU infrastructure, and cloud-native platforms. Author of Kubernetes Recipes and creator of CopyPasteLearn courses.

Kubernetes Recipes book cover

Want More Kubernetes Recipes?

This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.

Luca Berton Ansible Pilot Ansible by Example Open Empower K8s Recipes Terraform Pilot CopyPasteLearn ProteinLens