KVM MicroVM Isolation vs Docker Shared-Kernel Security: A Technical Comparison in CubeSandbox
KVM MicroVMs utilize hardware-assisted virtualization to run isolated guest kernels with minimal attack surface, whereas Docker containers share the host kernel and depend on namespaces and cgroups for isolation, with CubeSandbox implementing both paradigms through Cloud Hypervisor and Containerd.
TencentCloud/CubeSandbox employs a dual-isolation architecture that allows users to choose between KVM-based micro-virtualization and traditional containerization. Understanding how KVM MicroVM isolation compares to Docker shared-kernel security is essential for selecting the appropriate workload boundary in multi-tenant environments. The platform unifies these models under a single control plane, enabling strict isolation for untrusted workloads and lightweight efficiency for trusted applications.
Isolation Architecture Fundamentals
The core distinction lies in the virtualization boundary. KVM MicroVMs leverage the Linux KVM kernel module to create hardware-assisted virtualization contexts where each VM runs its own guest kernel, memory spaces, and virtual devices. This architecture is implemented in hypervisor/vmm/src/vm.rs, which configures separate address spaces through vm.set_identity_map_address and vm.set_tss_address, ensuring complete separation from the host kernel.
Docker containers, managed by CubeSandbox's Cubelet component, operate as isolated processes sharing the host kernel. Isolation relies on Linux namespaces, cgroups, and optional security hooks like seccomp and AppArmor. The namespace enforcement appears in Cubelet/services/cubebox/service.go, where namespaces.WithNamespace binds containers to specific isolation contexts. Unlike MicroVMs, containers do not virtualize the kernel; they merely restrict access to host resources through kernel-level abstraction.
Attack Surface and Security Boundaries
KVM MicroVMs minimize the attack surface by restricting host kernel access to strictly controlled hypervisor calls. The seccomp policy defined in hypervisor/vmm/src/seccomp_filters.rs explicitly allows only specific KVM ioctls such as KVM_CREATE_VM, KVM_RUN, and KVM_SET_USER_MEMORY_REGION. A compromised guest kernel remains confined within the virtual machine unless a hypervisor vulnerability is exploited, as the guest cannot directly execute arbitrary host kernel code.
Docker containers present a broader attack surface because all containers share the same host kernel. A vulnerability in the kernel or a misconfigured namespace can potentially compromise every container on the host. CubeSandbox mitigates this by applying seccomp filters to container processes and enforcing namespace isolation, but the fundamental security model remains weaker than hardware virtualization. As implemented in the Cubelet, namespace checks provide process-level separation, but they cannot prevent kernel-level privilege escalation that bypasses namespace boundaries.
Resource Isolation Mechanisms
The hypervisor enforces strict resource boundaries for MicroVMs through hardware-level memory management and CPU scheduling. In hypervisor/vmm/src/vm.rs, the VMM configures distinct memory regions and virtual device mappings, preventing VMs from accessing host memory or interfering with other tenants' CPU cycles. This hardware-enforced isolation ensures that resource exhaustion in one VM cannot trigger denial-of-service conditions for neighboring workloads.
Containers rely on cgroups for resource limitation, specifying CPU shares, memory limits, and I/O bandwidth. While effective for soft multi-tenancy, cgroups do not provide the same isolation guarantees as hardware virtualization. Containers competing for the same physical resources can experience performance interference, and memory pressure in one container may trigger host-level OOM killers that affect other processes.
State Management and Snapshot Isolation
KVM MicroVMs support complete state capture through VM snapshots. The implementation in hypervisor/vmm/src/migration.rs enables full serialization of guest memory, CPU registers, and device states, providing clean rollback points that include the entire kernel state. This capability allows CubeSandbox to restore a workload to its exact execution point without host kernel contamination.
Docker container snapshots capture only filesystem layers and process trees, excluding the host kernel state. Consequently, rolling back a container cannot revert kernel-level changes, module loads, or system-wide parameter modifications that occurred during execution. This limitation makes containers unsuitable for workloads requiring immutable, reproducible system states at the kernel level.
Practical Implementation in CubeSandbox
CubeSandbox unifies both isolation models through distinct control plane components: CubeMaster for MicroVMs and Cubelet for containers.
Launching KVM Micro-VMs via CubeMaster
The CubeMaster service orchestrates MicroVM creation by interfacing with the Cloud Hypervisor component. The following simplified Go implementation demonstrates how CubeSandbox initializes a VM with dedicated resources:
// CubeMaster – create a VM from an image (simplified)
func CreateVM(ctx context.Context, imgPath string) (*hypervisor.VM, error) {
// Load the VM image
vm, err := hypervisor.NewVM(imgPath)
if err != nil { return nil, err }
// Configure memory and CPU (example values)
vm.SetMemory(2 * 1024 * 1024 * 1024) // 2 GiB
vm.SetCPU(2)
// Start the VM – internally calls KVM_RUN via the hypervisor
if err := vm.Start(ctx); err != nil { return nil, err }
return vm, nil
}
This code leverages the hypervisor package to configure memory layout and CPU allocation before invoking KVM_RUN through the underlying Rust implementation in hypervisor/vmm/src/vm.rs.
Running Docker Containers via Cubelet
The Cubelet service handles container execution through Containerd integration, applying namespace isolation as shown in Cubelet/services/cubebox/service.go and image management in Cubelet/services/images/service.go:
// Cubelet – run a container in a specific namespace
func RunContainer(ctx context.Context, img string, ns string) (containerd.Container, error) {
// Attach namespace to context
ctx = namespaces.WithNamespace(ctx, ns)
// Pull the image (Containerd client)
client, _ := containerd.New("/run/containerd/containerd.sock")
imgRef, err := client.Pull(ctx, img, containerd.WithPullUnpack)
if err != nil { return nil, err }
// Create container with sandbox ID (CubeBox ID)
cont, err := client.NewContainer(
ctx,
"my-container",
containerd.WithImage(imgRef),
containerd.WithSandboxID("cube-box-id"),
)
if err != nil { return nil, err }
// Start the task
task, _ := cont.NewTask(ctx, cio.NewCreator(cio.WithStdio))
return task.Start(ctx)
}
This implementation demonstrates how CubeSandbox binds containers to specific namespaces while integrating with the Containerd ecosystem.
Performance Trade-offs and Use-Case Guidance
KVM MicroVMs incur slightly higher overhead due to full virtualization, guest kernel initialization, and hardware abstraction layers. However, this cost is justified when running untrusted code, multi-tenant workloads, or compliance-sensitive applications requiring strong isolation boundaries.
Docker containers offer lower overhead and faster startup times because they run as native processes without kernel initialization overhead. Select containerization when hosting trusted workloads that require high density, rapid scaling, and minimal resource consumption.
Summary
- KVM MicroVMs provide hardware-level isolation with separate guest kernels through Cloud Hypervisor, as configured in
hypervisor/vmm/src/vm.rs - Docker containers share the host kernel and rely on namespaces and seccomp filters defined in
hypervisor/vmm/src/seccomp_filters.rsand enforced inCubelet/services/cubebox/service.go - CubeSandbox unifies both models under a single control plane via CubeMaster (VMs) and Cubelet (containers)
- VM snapshots capture complete guest state including kernel memory, while container snapshots lack kernel state isolation
- Choose KVM MicroVMs for untrusted workloads and strict security boundaries; choose Docker for trusted, high-density applications requiring minimal overhead
Frequently Asked Questions
How does KVM MicroVM isolation prevent kernel-level attacks compared to Docker?
KVM MicroVMs run independent guest kernels that are isolated from the host via hardware virtualization, meaning a compromised guest kernel cannot directly access the host kernel except through strictly controlled KVM syscalls defined in hypervisor/vmm/src/seccomp_filters.rs. Docker containers share the host kernel, so a single kernel vulnerability can compromise all containers on the host.
What files control resource isolation in CubeSandbox's KVM implementation?
Resource isolation for KVM MicroVMs is implemented in hypervisor/vmm/src/vm.rs, which configures separate address spaces using vm.set_identity_map_address and vm.set_tss_address. Docker containers rely on cgroup configurations managed through Containerd APIs in Cubelet/services/images/service.go.
Can CubeSandbox migrate running workloads between nodes?
Yes, but only for KVM MicroVMs. The hypervisor/vmm/src/migration.rs file implements full VM snapshot and live migration capabilities that capture complete guest state. Docker containers in CubeSandbox do not support equivalent stateful migration because they lack the isolated kernel state present in MicroVMs.
When should I choose a KVM MicroVM over a Docker container in CubeSandbox?
Select KVM MicroVMs when running untrusted code, multi-tenant workloads, or compliance-sensitive applications requiring strong isolation boundaries. Choose Docker containers when you need faster startup times, higher density, and the workload is sufficiently trusted to share the host kernel.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →