How to mount /dev/kvm in a non-privileged pod?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
/dev/kvm is the Linux kernel device that provides hardware-accelerated virtualization (KVM). Mounting it inside a Kubernetes pod allows running VMs or Android emulators inside containers. By default, non-privileged pods cannot access host devices. The solution is to use a device plugin (like the kubevirt/device-plugins KVM plugin), a hostPath volume with targeted security context capabilities, or a privileged init container that sets up device access.
Why You Need /dev/kvm
KVM (Kernel-based Virtual Machine) provides hardware virtualization support. Common use cases inside pods include:
- Running Android emulators in CI/CD pipelines
- Nested virtualization for testing
- Running QEMU/KVM virtual machines
- Hardware-accelerated testing environments
Without /dev/kvm, these workloads fall back to software emulation, which is 10-50x slower.
Solution 1: KVM Device Plugin (Recommended)
The KVM device plugin exposes /dev/kvm as a schedulable Kubernetes resource:
Request the device in your pod spec:
The device plugin automatically mounts /dev/kvm into the container and sets the correct permissions. No privileged mode or extra capabilities are needed.
Solution 2: hostPath Volume with Security Context
If you cannot use a device plugin, mount /dev/kvm as a hostPath volume:
To avoid running as root, add the container user to the kvm group on the host:
Solution 3: Init Container for Device Setup
Use a privileged init container that only sets up device permissions, keeping the main container non-privileged:
Node Affinity for KVM Nodes
Not all nodes have /dev/kvm available. Use node affinity to schedule KVM pods on capable nodes:
Label KVM-capable nodes:
Pod Security Standards
With PodSecurityPolicy deprecated since Kubernetes 1.25, use Pod Security Admission:
For more granular control, use a policy engine like Kyverno or OPA Gatekeeper:
Verifying KVM Access Inside the Pod
Common Pitfalls
- Using privileged mode for the entire pod: Setting
privileged: trueon the main container gives it full access to all host devices and capabilities, which is a major security risk. Use the device plugin approach or a privileged init container with a non-privileged main container instead. - Not checking node KVM support: Scheduling a KVM pod on a node without
/dev/kvm(e.g., a VM-based node without nested virtualization) causes the pod to crash. Always use node affinity or the device plugin, which automatically schedules pods only on KVM-capable nodes. - Wrong group ID for /dev/kvm: The
kvmgroup GID varies across Linux distributions (commonly 107, 109, or 36). Hardcoding the wrong GID inrunAsGrouporsupplementalGroupscauses permission denied errors. Check the actual GID on the node withgetent group kvm. - Ignoring Pod Security Admission: In Kubernetes 1.25+, namespaces with
baselineorrestrictedpod security standards reject pods withhostPathvolumes. Set the namespace toprivilegedenforcement level or use the device plugin, which does not require hostPath. - Not setting resource limits: KVM workloads (VMs, emulators) are resource-intensive. Without CPU and memory limits, a single pod can starve other workloads on the node. Always set resource requests and limits for KVM pods.
Summary
- Use the KVM device plugin (
devices.kubevirt.io/kvm) for the cleanest, most secure approach — no privileged mode needed - Alternative: mount
/dev/kvmas ahostPathvolume withtype: CharDeviceand appropriate group permissions - Use a privileged init container to set device permissions while keeping the main container non-privileged
- Schedule KVM pods on capable nodes with node affinity labels or device plugin auto-scheduling
- Use Pod Security Admission (replacing deprecated PodSecurityPolicy) to control hostPath access at the namespace level

