Stage 0 learning document for request section 4. Version-sensitive facts come from current official sources, checked on 2026-09-27.
| Item | Current fact (2026-09-27) | Source |
|---|---|---|
| KubeVirt release | v1.9 (released July 2026) | KubeVirt release notes, kubevirt/kubevirt releases |
| Kubernetes support | v1.9 is built for Kubernetes 1.36 and also supported on the previous two minors (1.35, 1.34) | KubeVirt support matrix, kubernetes-compatibility.md |
| Kubernetes releases | 1.37 is the newest upstream minor; 1.34 reaches end of life 2026-10-27 | kubernetes.io/releases |
| EKS | Standard support for 1.36, 1.35, 1.34 | EKS Kubernetes versions |
INFERRED: if KubeVirt v1.9 is used, Kubernetes 1.35 or 1.36 fits its support window; 1.34 is EOL next month and 1.37 is outside the v1.9 window. These are observations, not pins. The actual versions are chosen at deployment time as one compatibility tuple (KubeVirt, Kubernetes, CDI) and must pass the runtime validation gate in feasibility.md.
KubeVirt extends Kubernetes with three things (KubeVirt architecture):
VirtualMachine and VirtualMachineInstance.Scheduling, networking and storage are delegated to Kubernetes. KubeVirt only adds virtualization. All KubeVirt components run as Pods on the cluster; they are not installed on the hosts like a package.
| Component | Kind | Runs where | What it does |
|---|---|---|---|
| virt-operator | Deployment | Control-plane / infra nodes | Installs, upgrades and removes the rest of KubeVirt. It watches the KubeVirt custom resource. |
KubeVirt CR |
Custom resource (one per cluster, usually kubevirt/kubevirt) |
API server | The install configuration: feature gates, node placement (.spec.infra.nodePlacement, .spec.workloads.nodePlacement), useEmulation, and so on. |
| virt-api | Deployment | Infra nodes | Serves KubeVirt’s API pieces: defaulting and validating admission webhooks for VMs/VMIs, and subresources such as start, stop, restart, console, vnc, migrate. |
| virt-controller | Deployment | Infra nodes | Cluster-wide reconciliation: VM -> VMI, VMI -> virt-launcher Pod, migrations, and similar. |
| virt-handler | DaemonSet (privileged) | Every node that can run VMs | Watches VMIs assigned to its node, tells virt-launcher to define and start the libvirt domain, keeps domain state and VMI status in sync, sets up node-level networking and devices, and advertises /dev/kvm as a node resource. |
| virt-launcher | One Pod per running VMI | The node the scheduler chose | Its compute container runs the virt-launcher process, a private libvirtd, and the QEMU process for that one VM. |
| libvirt | Daemon inside virt-launcher | Per VM | Receives domain XML (generated from the VMI) and manages the QEMU process. |
| QEMU | Process inside virt-launcher | Per VM | Emulates the machine and devices. Uses KVM for CPU/memory virtualization. |
| KVM | Kernel module | Node kernel | Hardware-accelerated execution through /dev/kvm. |
References: KubeVirt architecture, components.md, KubeVirt installation.
This is the most important distinction to learn.
VirtualMachine (VM) |
VirtualMachineInstance (VMI) |
|
|---|---|---|
| Analogy | A StatefulSet with replicas: 1, or the VM in vCenter inventory |
A Pod, or “the VM while it is powered on” |
| Lifetime | Persistent. Exists while stopped. | Ephemeral. Created when the VM starts, deleted when it stops. |
| Holds | spec.template (what a VMI should look like) and spec.runStrategy (whether one should exist) |
The concrete running spec, plus live status: phase, node, interfaces, guest info |
| Created by | You, GitOps, or our migration controller | virt-controller, from the VM template |
| Status field of interest | status.printableStatus (Stopped, Provisioning, Starting, Running, Paused, Migrating, Stopping, Terminating, Unknown, …) |
status.phase (Pending, Scheduling, Scheduled, Running, Succeeded, Failed, …) |
spec.runStrategy values (Run Strategies):
virtctl start / stop.You can also create a bare VMI without a VM. It will not be restarted if it stops. For migration we will always create a VirtualMachine, because a migrated server must survive restarts.
kubectl apply to a running guestkubectl apply -f vm.yaml
|
v
kube-apiserver -- virt-api webhooks default + validate the VirtualMachine --> stored in etcd
|
v
VirtualMachine CR (runStrategy: Always)
| virt-controller watches VMs; sees "should run, no VMI exists"
v
VirtualMachineInstance CR (owner reference -> VM)
| virt-controller watches VMIs; renders a virt-launcher Pod spec
| (requests: CPU, memory + overhead, devices.kubevirt.io/kvm; volumes: PVCs; network: pod network / Multus)
v
virt-launcher Pod -- kube-scheduler picks a node; kubelet starts the Pod; CNI wires the network; CSI mounts the PVC
| virt-controller records the node on the VMI; virt-handler on that node takes over
v
virt-handler -- converts the VMI into libvirt domain XML and asks virt-launcher to define + start it
|
v
libvirtd (in the Pod) -- starts QEMU with the right devices
|
v
QEMU -- opens /dev/kvm, creates vCPU threads, loads firmware
|
v
KVM -- runs guest code on the CPU with VT-x/EPT
|
v
guest OS boots (bootloader -> kernel -> initramfs -> systemd -> nginx)
|
v
virt-handler reports status back: VMI phase Running, IPs (from the guest agent if installed); VM printableStatus Running
Stopping reverses this: set runStrategy: Halted (or virtctl stop), virt-controller deletes the VMI, the guest receives an ACPI shutdown, the Pod terminates, and the VM object remains with printableStatus: Stopped.
DOCUMENTED in KubeVirt installation:
--allow-privileged=true), because virt-handler and parts of virt-launcher need privileges.virt-host-validate qemu checks for /dev/kvm, /dev/vhost-net and /dev/net/tun.useEmulation). This is slow and only suitable for testing.Nothing here was installed in Stage 0.