Prerequisites
- A Linux worker with usable
/dev/kvm; virtual workers need nested virtualization. - A namespace that permits privileged pods and host device mounts.
- An application image matching the worker’s architecture:
amd64orarm64. - Docker,
kubectlaccess, and a registry the worker can pull from. - Pod egress for downloading the guest image.
Native macOS microsandbox uses Apple’s hypervisor; Linux containers need KVM. Neither CPU emulation nor enabling Kubernetes supplies missing KVM support.
Build the application
This sample application runs a command in a sandbox with a shared workspace.Required application files
Required application files
In an empty directory, save The wheel bundles the runtime and kernel firmware. No Docker daemon is needed inside the pod.
agent.py:agent.py
Volume.bind() reads a path inside the application container. Here, a Kubernetes volume is shared at /workspace in both the container and guest; application files need no node hostPath.Add Dockerfile:Dockerfile
REGISTRY/PROJECT here and in the manifest, then build and push:
--platform linux/amd64. Private application images need Kubernetes imagePullSecrets; private guest images need separate microsandbox registry credentials.
Run the pod
Label the KVM-capable worker and create a test namespace:pod.yaml with your image reference:
pod.yaml
kubernetes.io/arch to amd64. CharDevice requires an existing KVM device. Host networking, host PID access, and container-engine sockets are unnecessary.
Apply and wait for completion:
Succeeded.
To rerun, delete the pod and reapply. To clean up:
Device plugins
A device plugin can expose KVM as a schedulable resource and grant device access. AhostPath mount alone may leave unprivileged containers blocked by runtime device rules.
With a KVM plugin installed:
- Find its resource name and capacity with
kubectl describe node YOUR_KVM_NODE. - Request the resource in container limits as the plugin documents. Names such as
devices.kubevirt.io/kvmare plugin-specific. - Remove the
kvmvolume and mount; the plugin supplies the device. - Remove
privileged: trueand verify sandbox boot, device permissions, and seccomp/AppArmor/SELinux compatibility. Device access alone does not prove VM startup works.
Operational notes
- Files:
emptyDirsurvives container restarts but not pod deletion. Use a PVC for durable output andVolume.bind(path, readonly=True)for protected inputs. - Runtime state: keep
/msbprivate to each pod. It contains the database, image cache, and sandbox files. Persisting it does not preserve running VMs. - Resources: budget for the application, all guests, and runtime overhead. This example allows 2 GiB for one 512 MiB guest. Measure concurrent workloads and disk usage; keep runtime volumes disk-backed.
- Networking: both cluster egress rules and microsandbox policies apply. Guest images download through the application container.
- Shutdown: the context manager kills and removes the sandbox on exit. For graceful shutdown, call
await sandbox.stop()before leaving the context. Long-running applications need aSIGTERMhandler that stops accepting work, finishes or cancels tasks, and awaits shutdown within the pod’s grace period. Default signal handling does not unwind Python contexts. No sandbox survives pod deletion.
Troubleshooting
Check KVM access inside the pod
Check KVM access inside the pod
To run a diagnostic instead of the application, add this under the Delete the existing pod, reapply the manifest, and read the diagnostic output:Check the KVM device and access results. Passing these checks does not guarantee
microVM boot. Remove
agent
container in pod.yaml:command, then delete and recreate the pod to run the
application again.Validation status
Checked: ARM64/AMD64 image builds, OrbStack guest-image pulls, Kubernetes v1.34 schema, and native macOS file sharing, read-only mounts, cleanup, and concurrency. Kubernetes microVM execution remains unverified: the test OrbStack VM lacked/dev/kvm. A KVM-capable Linux worker is still needed to validate boot, admission, and device-plugin setup.