kata-firecracker-devmapper (kfd), kata-qemu-longhorn (kql), k7d, and k7d-fc. A node can install any combination (k7 install --backend kfd,kql,k7d,k7d-fc) and each sandbox picks one (k7 create --backend …).
Deprecated aliases:
fd and ql (and the long names without the kata- prefix) are older names for kfd / kata-firecracker-devmapper and kql / kata-qemu-longhorn. They still resolve for backwards compatibility, but new configs should use the current names. k7-fc is accepted as an alias of k7d-fc.At a glance
Numbers are medians of 3 on one Hetzner AX41 node; ranges and methodology are in PERFORMANCE.md.
Privilege separation is the k7d daemon, not a fifth backend: a root node broker (no listening socket) plus a uid-
k7d VM broker for the whole node. Both k7d and k7d-fc sandboxes go through that pair. Tables: k7d vs k7d-fc and privilege separation.
Choosing a backend
Pickkata-firecracker-devmapper when:
- You run many short-lived sandboxes per node and want the smallest possible footprint.
- You don’t need to pause, resume, fork, or persist state between restarts.
- You’re on a single node and don’t need replication.
- Security is paramount: Firecracker has the smallest attack surface, and the jailer is active (verified by
tests/integration/test_firecracker.py::test_jailer_active).
kata-qemu-longhorn when:
- You need a real persistent disk that survives pod restarts (
/mnt/statemount inside the sandbox). - You want to
pause/resume/forksandboxes at the disk level, ork7 snapshot/k7 restorenamed snapshots. - You run multi-node and want data to survive node failure (Longhorn replicates).
- You need bigger root disks (sized with
--root-disk-size), or a Docker graph that survives pause / fork / restore.
k7d when:
- Fork latency matters: k7d warm-forks a running VM in ~5 ms with faithful memory, disk, process, and network state — versus ~45 s for a disk-only Longhorn fork.
- You want snapshot trees: fork many branches from a checkpoint, protect winners, prune losers, under RAM/disk budgets.
- Your workload is RL training or agent tree search over many resettable environments.
- You want a forkable Docker engine:
k7 create --docker --backend k7drunsdockerdinside the guest andk7 forkclones it, running inner containers included.
k7d-fc when:
- You want k7d’s fork / pause lifecycle and Firecracker’s jailer around every VM — a separate VMM process per sandbox with its own uid, chroot, pid namespace, cgroup, and Firecracker’s default seccomp. A guest-to-VMM escape lands in that jail instead of the k7d daemon.
- You run
--dockerfor mutually distrusting tenants. The guest side is identical tok7d, so this is a RuntimeClass switch, not a rewrite. - You can live without virtiofs / hostPath volumes (refused up front on
k7d-fc) and without k7d’s time warp.
Cluster fork is a k7d feature, not a k7 feature. Forking an entire live Kubernetes cluster (~100 ms for a 3-node cluster) is done by the k7d runtime directly, through its own daemon API — see Cluster mode. k7’s
fork command clones a single sandbox.Specifying the backend
At install time
At sandbox creation time
FailedScheduling message listing which backends are.
Backend-specific behavior
kata-qemu-longhorn
- Each sandbox gets a Longhorn PVC named
<sandbox>-root-lh, defaulting to 10Gi (override with--root-disk-size 20Gior in YAML). - The container runs privileged to allow the persistence wrapper to bind-mount
/mnt/statefrom the PVC. - Image base must include
/bin/sh,tar, andmount(Debian/Ubuntu/Alpine all work). - Image
ENTRYPOINT+CMDare preserved by default — override with--entrypoint/--cmd. pausetakes a crash-consistent VolumeSnapshot before scaling to 0 (optional; pass--snapshot <name>).forksnapshots the source PVC, clones it via Longhorn’s CSI VolumeSnapshot+Restore, then creates a new Deployment pointing at the cloned PVC.--dockeradds a second Longhorn Block PVC (<name>-docker-lh, default 20Gi via--docker-disk) for the overlay2 graph; it is included in pause / fork / restore. The two VolumeSnapshots are crash-consistent per volume, not cross-volume atomic.
kata-firecracker-devmapper
- Sandbox storage is a per-pod logical volume on the LVM thin-pool — fast to create, lost on delete.
- The Firecracker process runs inside the jailer: a chroot, with dropped capabilities and a restrictive seccomp filter, as an unprivileged UID.
- Kata’s guest seccomp is enforced (
disable_guest_seccomp = false): the container’sRuntimeDefaultseccomp profile is applied by the in-guest runtime, not silently dropped. - No
pause/resume/fork— there’s no persistent disk to snapshot. --root-disk-sizehas no effect (warned by the CLI).--dockerputs the overlay2 graph on a generic ephemeral volume from StorageClassk7-docker-lvm(OpenEBS LVM LocalPV overkata-vg/thin-pool); it is deleted with the pod andk7 forkof a kfd--dockersandbox is rejected. Docker-heavy kfd nodes share the thin-pool with these LVs — sizekata_thinpool_pv_sizeaccordingly.
k7d
- Pods run as k7d microVMs via
runtimeClassName: k7— a small containerd shim talks to thek7ddaemon over/run/k7d/k7d.sock. - Fork copies the whole VM: memory, disk, processes, and network identity — not just the disk. Warm fork is ~5 ms.
- Multi-vCPU guests are supported: the vCPU count is derived from the pod’s CPU limit (
cpu: "2"boots a 2-vCPU guest), with fork/snapshot parity. - VM ops work for sandboxes on any node. The k7d daemon and its socket are node-local, but
k7 pause/resume/forkthrough the API are forwarded to thek7-agentDaemonSet pod on the sandbox’s node when needed. A fork still lands on the source’s node (cross-node fork is on the k7d roadmap). --dockerdoes not add a second container: the pod is stampedk7d.katakate.org/docker=trueand the guest agent (PID 1) supervises a pinneddockerdwhose graph lives on a per-sandbox virtio-blk scratch disk (overlay2, default 20Gi). Because it is not a CRI sidecar,k7 forkof a--dockersandbox works — the child keepsdockerdand its running inner containers. Requires k7d 0.6.0+ (payload at/usr/local/share/k7d/docker); an older k7d fails loudly withthis k7d has no docker service; upgrade.- Warm fork works for single-workload sandboxes (including
--docker); forking a sandbox with a real CRI sidecar is rejected (usekqlfor that). - Per-node k7d disk-pool utilization is visible via
k7 nodes storage(see CLI reference). - See RuntimeClass k7 for how the runtime is registered, and the feature matrix for current Kubernetes feature support.
k7d-fc
- Same daemon, shim, guest agent, and
--dockerservice ask7d; pods useruntimeClassName: k7-fc. The daemon boots the guest on upstream Firecracker under the upstream jailer (sha-pinned binaries installed to/usr/local/binby the playbook — a different binary from Kata’s/opt/kata/binFirecracker used bykfd). k7 0.4.0 and k7d both pin v1.16.2. k7 0.3.1 still vendored v1.16.1. k7 install --backend k7d-fcwrites/etc/k7d/shim-k7-fc.toml(backend = "firecracker"), registers containerdruntimes.k7-fcwith aConfigPathoption (and noBinaryName), creates RuntimeClassk7-fcwith a PodOverhead of32Mi/50m, and labels the nodek7.katakate.org/backend-k7d-fc=true(plusbackend-k7d, so nativek7dpods still schedule there).- Fork and pause go through the same
/run/k7d/k7d.sockverbs andfork-source-*annotations ask7d. Under the hood a fork is a Firecracker Diff snapshot materialised onto a reflinked base image andLoadSnapshoted into a fresh jail (~2.5 s end-to-end via k7; ~2.45 s fork→exec measured). - hostPath / PVC
volumesare refused at create time — Firecracker has no virtiofs. Time warp / dilation is unavailable on this backend. - Pause / resume → exec needs Firecracker v1.16.2+. k7 0.4.0 copies v1.16.2. k7 0.3.1 still copied v1.16.1, which gated vsock RX after a bare resume (upstream #6100 / k7d CHALLENGES); current k7d then fails
k7 resumeloudly (Firecracker < v1.16.2). Nativek7dis unaffected. - Requires k7d 0.6.0+ (Firecracker engine +
ConfigPath). The stock 0.5.0 tarball does not knowConfigPathand the RuntimeClass will not come up.
