This episode covers RuntimeClass in full: kata for QEMU, kata-clh for Cloud Hypervisor, kata-fc for Firecracker, and kata-qemu-coco-dev for confidential containers. You'll also run your first pod with spec.runtimeClassName and prove that the application process runs inside the microVM.

In episode 3 you installed Kata and prepared the kata RuntimeClass. Episode 4 is the most satisfying moment: running your first pod with microVM isolation. But before that, we need to understand RuntimeClass thoroughly — because in a production cluster, you'll face several RuntimeClasses at once, each for a different hypervisor backend.
You'll also see for yourself the most convincing proof that isolation really happens: the application process isn't visible on the host, but inside the microVM. After this episode, "the speed of containers, the security of VMs" is no longer a slogan, but something you prove with a ps command.
Kata provides several commonly used RuntimeClasses, each pointing to a different VMM backend:
kata: the QEMU backend — default, broadest compatibility.kata-clh: the Cloud Hypervisor backend — modern and fast for general workloads.kata-fc: the Firecracker backend — minimal, suited for lightweight sandboxes.kata-qemu-coco-dev: the QEMU backend with confidential containers support (TDX/SEV-SNP), used for workloads that need attestation.These names aren't magic — each is a RuntimeClass entry whose handler points to a containerd configuration. See what's already registered in your cluster:
kubectl get runtimeclass
kubectl get runtimeclass kata -o yamlkubectl get runtimeclass displays the list of RuntimeClasses known to the cluster. kubectl get runtimeclass kata -o yaml displays the details — including handler: kata, which must match the runtime name in containerd.
The runtime selection flow follows the chain built in episodes 2 and 3:
spec.runtimeClassName: kata.runtimes block in config.toml.containerd-shim-kata-v2, and the microVM is born.If the handler isn't found, Kubernetes rejects the pod with a failed to find runtime handler error. This is why the containerd configuration (episode 3) and the handler name must be consistent.
A pod with Kata looks like a normal pod, with one difference: spec.runtimeClassName. Create the file pod-kata.yaml:
apiVersion: v1
kind: Pod
metadata:
name: kata-demo
labels:
app: kata-demo
spec:
runtimeClassName: kata
containers:
- name: app
image: nginx:alpine
ports:
- containerPort: 80spec.runtimeClassName: kata is the only difference from a normal pod. Apply it and wait for the pod to become Running:
kubectl apply -f pod-kata.yaml
kubectl get pod kata-demo -wkubectl get pod kata-demo -w shows the pod status in real time. What's interesting: a Kata pod usually stays in ContainerCreating a bit longer for a moment — because the microVM is being booted — but overall it's still fast, consistent with the 150-300 ms boot claim.
One important architectural detail: the pod sandbox and the app container share one microVM. In Kata, a pod is one microVM, and the containers inside the pod are containers inside the guest. The sandbox (pause container) and the app container are born in the same guest, managed by the Kata agent.
To see this relationship, inspect the containers and sandbox from containerd's side:
crictl pods
crictl pscrictl pods displays pod sandboxes, and crictl ps displays running containers. Both should show the kata-demo pod in a normal state — from the CRI perspective, everything looks like a regular container runtime.
This is the most interesting moment of proof. Look for the application process on the host:
ps aux | grep nginx
pgrep -f nginxps aux | grep nginx on the host should not find any nginx process. What's on the host is only the VMM process — one process per microVM. Take a look:
ps aux | grep -E "(qemu|cloud-hypervisor|firecracker)"ps aux | grep -E "(qemu|cloud-hypervisor|firecracker)" shows one VMM process wrapping the entire microVM of the kata-demo pod. The nginx process isn't visible on the host because it's born inside the guest kernel.
To see processes inside the guest, we need to enter it. Kata provides kata-runtime exec for running commands inside the microVM. Get the sandbox ID from kata-runtime list:
kata-runtime list
sudo kata-runtime exec <sandbox-id> ps auxkata-runtime list shows the running sandboxes along with their IDs. kata-runtime exec <sandbox-id> ps aux runs ps inside the guest — this is where you'll see the nginx process, along with the Kata agent process and the guest system processes.
Tip
A quick way to prove isolation: run ps aux | grep nginx on the host (it should be empty), then kata-runtime exec <sandbox-id> ps aux to see nginx inside the guest. The host only sees one VMM process; the guest sees all the application processes.
Here are some of the most frequent problems when running your first Kata pod:
kubectl describe pod for the exact error message./dev/kvm makes the microVM unable to boot. The pod will get stuck in ContainerCreating and then CreateContainerError./etc/containerd/config.toml don't take effect until containerd is restarted.kubectl describe pod and kubectl logs remain your first diagnostic tools. Expand with kata-runtime commands and the logs in /var/log/kata-containers/ when you suspect a problem in the Kata layer — we'll cover this thoroughly in episode 12.
What you should take away:
kata, kata-clh, kata-fc, kata-qemu-coco-dev.spec.runtimeClassName is the only change a pod needs.kata-runtime list and kata-runtime exec prove isolation directly.In the next episode, episode 5, we'll cover runtime configuration — dissecting /etc/kata-containers/configuration.toml, hypervisor parameters, kernel, memory/CPU limits, and the virtio-blk vs virtio-scsi block device driver choice. This is the file that controls your microVM's behavior, and understanding it will let you master Kata tuning.
Phase 2 is going smoothly. Move on to the next episode!