Stage 0 learning document. It covers request sections 1 (first principle), 2 (KVM / QEMU / libvirt) and 3 (nested virtualization).
Evidence markers used in this document:
Take one concrete workload: a small Linux server that runs nginx and serves a static site from /var/www.
VirtualMachine custom resource that you kubectl apply, store in Git, and let controllers reconcile.Deployment + Service. Scaling is horizontal (more replicas), not bigger VMs.A and B both run a full guest OS on virtual hardware. Only the manager changes. Moving from A to B is migration (rehosting). C removes the VM entirely. Moving from A or B to C is modernization (see modernization-model.md).
ESXi VM source: .vmx + .vmdk on VMFS; runs as a VMX process on VMkernel
| migration: translate metadata, convert + import disks
v
KubeVirt VirtualMachine (VM) persistent desired state (kubevirt.io/v1); survives stop/start
| virt-controller creates a VMI when spec.runStrategy says "run"
v
VirtualMachineInstance (VMI) one running instance; deleted when the VM stops
| virt-controller creates the launcher Pod; kube-scheduler places it
v
virt-launcher Pod normal Pod: cgroups, namespaces, pod IP, PVC mounts
| virt-handler (on the node) tells virt-launcher to define/start the libvirt domain
v
QEMU process user-space process that emulates the machine and its devices
| ioctl() calls on /dev/kvm
v
KVM Linux kernel module; runs guest code on the CPU using VT-x/EPT
|
v
guest OS the same Linux + nginx that ran on ESXi, now on virtio devices
| Layer | Owner (who creates / changes it) | Comparable ESXi concept |
|---|---|---|
| ESXi VM (source) | ESXi hostd / VMkernel; our migration platform only reads it | - |
VirtualMachine |
You (kubectl, GitOps) or our migration controller | The VM object in inventory (.vmx) |
VirtualMachineInstance |
virt-controller (owner reference to the VM) | A powered-on VM |
| virt-launcher Pod | virt-controller creates it; kube-scheduler places it; kubelet runs it | The VMX “world” on a host |
| libvirt domain | virt-handler asks virt-launcher to define it | VMX configuration in memory |
| QEMU process | libvirt inside virt-launcher | VMX process + device emulation |
| KVM | Node Linux kernel | The VMM part of VMkernel |
| Guest OS + app | Application / OS team | Same |
DOCUMENTED: KubeVirt architecture, KubeVirt components (kubevirt/kubevirt docs/components.md).
Four pieces, each solving one problem. Together they do what ESXi does as one product.
kvm.ko plus kvm-intel.ko or kvm-amd.ko). It turns Linux into a hypervisor and exposes the device file /dev/kvm./dev/kvm and uses ioctl() calls to create a VM, add vCPUs and map memory. Each vCPU is a normal Linux thread. When that thread “runs” the vCPU, the CPU switches into guest mode (Intel VT-x “VMX non-root”) and executes guest code natively until something needs attention (an I/O access, an interrupt). Then it exits back to KVM, which handles it or passes it to user space.-accel kvm), QEMU leaves CPU execution to KVM and does device emulation and VM setup itself.virt-launcher Pod
libvirtd --(domain XML)--> QEMU process
|- device emulation: virtio-net, virtio-blk, UEFI/BIOS, ...
|- vCPU threads --(ioctl KVM_RUN)--> /dev/kvm
Node Linux kernel
KVM module --(VT-x / EPT)--> physical CPU and RAM
tap / bridge / nftables <-- host side of the virtual NIC
block device or file <-- backing store of the virtual disk (from a PVC)
This is a conceptual mapping for learning. KVM and ESXi are not identical. ESXi is a purpose-built type-1 hypervisor OS where VMkernel does scheduling, memory management, storage and networking. KVM makes a general-purpose Linux kernel into a hypervisor, and many ESXi functions are split across Linux, QEMU, libvirt and (on Kubernetes) KubeVirt and CNI/CSI plugins.
| VMware concept | Closest KVM / QEMU / KubeVirt concept | Important difference |
|---|---|---|
| ESXi (hypervisor product) | Linux + KVM + QEMU + libvirt (+ KubeVirt on Kubernetes) | ESXi is one integrated product. The KVM stack is assembled from parts. |
| VMkernel | Linux kernel with the KVM module | VMkernel is purpose-built. Linux is general-purpose and also runs containers. |
| VMM (inside VMkernel) | KVM (CPU/memory virtualization in the kernel) | Similar role. |
| VMX process (per VM) | QEMU process (per VM) | Both are per-VM user-space processes that emulate devices. |
.vmx file |
libvirt domain XML; in KubeVirt the VM/VMI spec | In KubeVirt the source of truth is a Kubernetes object, not a file. |
| VMDK | Disk image: raw or qcow2 file, or a raw block device | CDI converts imported disks to raw. |
| VMFS datastore | Filesystem or block storage behind a PVC/StorageClass | Kubernetes storage is per-volume (PVC), not a shared clustered filesystem. |
| Thin-provisioned VMDK | Sparse raw file or qcow2 | Sparseness can be lost if tools are used carelessly. |
| VM snapshot (delta VMDK chain) | qcow2 backing chain; in KubeVirt VirtualMachineSnapshot via CSI snapshots |
Different mechanisms. |
| vNIC (VMXNET3, E1000) | virtio-net (or e1000) exposed by QEMU | Guest driver changes from vmxnet3 to virtio_net. |
| PVSCSI controller | virtio-scsi or virtio-blk | Guest driver changes. |
| vSwitch | Linux bridge / OVS / CNI plugin inside the Pod network | In KubeVirt, the VM NIC connects to the Pod’s network namespace first. |
| Port group | Kubernetes Pod network, or a Multus NetworkAttachmentDefinition |
See networking-model.md. |
| VMware Tools | QEMU guest agent (qemu-guest-agent) |
Reports IPs, allows graceful shutdown, freezes filesystems. |
| hostd / Host Client | libvirtd per VM + KubeVirt virt-handler per node | |
| vCenter | Kubernetes API + KubeVirt controllers | Declarative desired state instead of imperative tasks. |
| vMotion | KubeVirt live migration (VirtualMachineInstanceMigration) |
Needs shared RWX storage or storage migration, and a suitable network binding. |
| DRS placement | kube-scheduler (requests, affinity, taints) | |
| HA restart | runStrategy: Always / RerunOnFailure + Kubernetes rescheduling |
Physical laptop: Intel Core i7-14650HX, 32 GB RAM, VT-x + SLAT enabled in firmware
|
Windows 11 Home (Windows hypervisor OFF: hypervisorlaunchtype Off)
|
VMware Workstation Pro 17.6.4, monitor mode CPL0 (native), hv-vt.vmm + gphys-ept.vmm loaded <- L0 hypervisor
|
esxi-8-lab: ESXi 8.0.3 build 24677879, 8 vCPU, 16 GB, vhv.enable = TRUE, HV Support: 3 <- L1 hypervisor
|
future legacy-source-vm (not created yet) <- L2 guest
Why the Windows hypervisor had to be off (OBSERVED in the handoff): with it running, Workstation ran on top of Hyper-V/WHP, which does not support “Virtualize Intel VT-x/EPT”. With it off, Workstation owns VT-x directly and can pass it to ESXi. The cost is that WSL2 and Docker Desktop cannot run.
AWS Nitro hypervisor on physical host <- L0
|
EC2 instance of a supported family, NestedVirtualization=enabled <- L1: Linux + KVM
|
Kubernetes node (kubelet, containerd) + KubeVirt virt-handler
|
virt-launcher Pod -> QEMU -> /dev/kvm (KVM in the L1 kernel)
|
target VM (the migrated legacy-source-vm) <- L2
DOCUMENTED (AWS: Use nested virtualization, AWS What’s New 2026-02-16):
aws ec2 describe-instance-types (look for nested-virtualization in ProcessorInfo.SupportedFeatures).--cpu-options NestedVirtualization=enabled), or on a stopped instance with modify-instance-cpu-options. The launch template API also has a NestedVirtualization CPU option (LaunchTemplateCpuOptionsRequest).*.metal) instance, where KVM runs at L0 on real hardware. AWS recommends bare metal for performance-sensitive workloads./dev/kvm on worker nodes for hardware-accelerated VMs. A normal cloud VM does not have it unless the cloud exposes VT-x (nested virtualization) or you pay for bare metal. KubeVirt has a software-emulation fallback (useEmulation), which is only useful for functional smoke tests (KubeVirt installation).