KubeVirt Explained: Running Virtual Machines on Kubernetes
KubeVirt lets infrastructure teams manage traditional virtual machines through Kubernetes instead of operating a separate VM control plane for every workload. It is useful when a platform needs both containerized applications and guests that require a complete operating system, such as a legacy service, a Windows workload, or a network appliance. KubeVirt does not turn a VM into a container: it connects VM lifecycle operations to the Kubernetes API while retaining the guest kernel and virtual hardware model.
This distinction explains why KubeVirt is relevant to Kubernetes operators and virtualization administrators alike. It offers a common way to declare, schedule, observe, and automate VMs alongside Pods, but it still depends on hypervisor capabilities, appropriate storage, and network configuration. The KubeVirt project develops this integration as an open-source Kubernetes extension.
What Is KubeVirt?
KubeVirt adds virtual-machine resources and controllers to a Kubernetes cluster. An administrator can describe a VM with a Kubernetes object, then use familiar access controls, namespaces, scheduling constraints, and declarative workflows to manage it. The KubeVirt user guide documents the supported features and installation options.
The two central resources are a VirtualMachine (VM) and a VirtualMachineInstance (VMI). The VM is the durable configuration and lifecycle object: it describes how the guest should be started and what it needs. A VMI represents a running guest. Starting a VM creates a VMI; stopping it removes the running instance while leaving the VM definition available to start again.
Underneath those APIs, a guest still runs as a virtual machine, commonly using QEMU and KVM on a Linux worker. KubeVirt wraps the VM process in a launcher Pod so Kubernetes can place and monitor the workload. The Pod is part of the management and isolation design; it does not mean the guest has lost its own kernel or become an ordinary application container.
The Problem KubeVirt Solves
Kubernetes was built around container workloads. Many organizations have adopted it for applications but still depend on systems that need a full guest OS: older software with OS-level assumptions, Windows applications, appliances, or workloads that are not ready to be refactored. Running those workloads on a separate virtualization platform can leave teams maintaining independent inventories, access policies, monitoring, automation, and capacity processes.
KubeVirt makes Kubernetes an option for orchestrating both kinds of workload. A platform team can expose a consistent API and operational workflow without rewriting every application. This is especially useful during gradual modernization: a VM can continue to run while nearby services move into containers, and teams can automate their lifecycle using Kubernetes tooling.
The trade-off is additional cluster complexity, not elimination of virtualization. Operators must provide VM-capable worker nodes, account for guest resource needs, choose storage and networking, and understand which features depend on the underlying hypervisor. KubeVirt is not automatically a simpler replacement for a mature virtualization platform.
How KubeVirt Works
The KubeVirt architecture connects Kubernetes API objects to VM processes on cluster nodes. Controllers observe desired state and create the resources needed to run it. A virt-handler service runs on VM-capable nodes and coordinates guest lifecycle operations there; a virt-launcher Pod hosts an individual VMI and its QEMU process. Kubernetes schedules that launcher Pod, while KubeVirt components handle the VM-specific work.
The guest sees virtual CPU, memory, disks, and network interfaces. On Linux/KVM, guest storage and network devices commonly use VirtIO drivers. The OASIS VirtIO specification defines standard interfaces for virtual I/O devices. KubeVirt can expose additional hardware and device configurations, but those options depend on the host, guest, and cluster configuration.
| Workload model | What Kubernetes schedules | Operating-system boundary | Typical fit |
|---|---|---|---|
| Native container workload | A Pod containing one or more containers | Shares the worker’s kernel | Cloud-native services and jobs |
| KubeVirt VM | A launcher Pod that hosts a VMI and guest VM | Guest has its own kernel and virtual hardware | Legacy or OS-dependent software managed through Kubernetes |
| VM on an external hypervisor | The hypervisor platform manages the VM; Kubernetes may run inside it | Guest has its own kernel and virtual hardware | Existing virtualization environments or clusters hosted on VMs |
Kubernetes provides a scheduler and control plane, not a hypervisor by itself. Kubernetes architecture documentation describes how its control plane assigns Pods to nodes; KubeVirt adds the VM-specific controllers and runtime required for the guest. For the lower-level CPU, memory, and device mechanisms, see hardware virtualization and hypervisors.
Components and Key Concepts
VM and VMI resources: The VM object holds the desired configuration and startup behavior. The VMI is the live instance. This separation lets automation request that a VM remain available without representing the current running process as the long-term configuration. The distinction resembles the difference between a workload controller and its Pods, but a VMI also describes the state of a virtual machine.
KubeVirt controllers and node services: The operator installs and maintains KubeVirt components. Controllers reconcile VM and VMI resources, while node-level handlers coordinate VM processes on eligible workers. Each running VMI is associated with a launcher Pod. This is why ordinary Kubernetes inspection commands can reveal placement and Pod status, while KubeVirt-specific resources expose guest lifecycle and conditions.
Scheduling and host requirements: VM resource requests influence placement, just like other scheduled workloads. However, a node must also provide the virtualization support KubeVirt needs, such as accessible KVM hardware or an explicitly configured alternative. Labels, affinity, tolerations, and resource requests can help keep VMs on suitable nodes. If no eligible node has enough capacity, the VMI remains pending rather than starting successfully.
Storage: A disposable demonstration image can be supplied as a containerDisk, but that is not equivalent to a durable system disk. Production VMs typically use persistent volumes; the Containerized Data Importer can help populate volumes from VM images. Storage class capabilities, access modes, snapshots, backup procedures, and live-migration requirements should be reviewed before choosing a design. Kubernetes container storage concepts are relevant, but a VM disk also needs to be usable by the guest.
Networking: KubeVirt can connect a guest to the cluster’s default Pod network or attach additional networks, commonly through Multus and network attachment definitions. Those choices affect guest addressing, reachability, and migration behavior. Kubernetes networking concepts still apply, but a VM’s guest interface and operating-system network configuration add another layer. See the container networking guide for the cluster-side basics.
Real-World Use Cases
KubeVirt can help teams consolidate a container platform and selected VM workloads under a shared API. A legacy application that requires a specific operating system can run as a guest while newer components run as containers. Teams can use Kubernetes namespaces and role-based access control to organize responsibilities, then build GitOps or deployment automation around VM definitions.
It can also support development and test environments. A team can create short-lived VMs from known images, test software against multiple operating systems, and delete the instances when finished. In a home lab, KubeVirt can be a way to learn VM orchestration with Kubernetes, provided the hardware and maintenance overhead are understood.
These use cases are not proof that every VM belongs in Kubernetes. If an organization needs mature hypervisor-specific workflows, a broad range of hardware features, or established migration and disaster-recovery tooling, its current virtualization platform may remain the better control plane. KubeVirt is strongest when Kubernetes APIs and automation are meaningful advantages for the VM workloads in question.
Getting Started with KubeVirt
Start with a Kubernetes cluster whose version is supported by the KubeVirt release you intend to install. Review the official installation guide and check that at least one worker can provide virtualization support. On each candidate Linux node, verify that /dev/kvm is available; also confirm that the cluster has enough memory and CPU for both the Kubernetes system and the guest.
The commands below install the KubeVirt operator and its custom resource using the pinned v1.9.0 release. Check the release’s compatibility requirements before applying it to a real cluster, and use the matching manifest version for both files:
export KUBEVIRT_VERSION=v1.9.0
kubectl apply -f "https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-operator.yaml"
kubectl apply -f "https://github.com/kubevirt/kubevirt/releases/download/${KUBEVIRT_VERSION}/kubevirt-cr.yaml"
kubectl wait kv kubevirt -n kubevirt \
--for=condition=Available \
--timeout=10m
kubectl get pods -n kubevirt
After the custom resource becomes available, create a VM for a disposable CirrOS test. This example uses a container disk so it does not demonstrate persistent storage:
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: cirros
spec:
runStrategy: Always
template:
spec:
domain:
resources:
requests:
memory: 512Mi
devices:
disks:
- name: rootdisk
disk:
bus: virtio
volumes:
- name: rootdisk
containerDisk:
image: quay.io/kubevirt/cirros-container-disk-demo:latest
Save the manifest as cirros-vm.yaml, then apply and inspect it:
kubectl apply -f cirros-vm.yaml
kubectl get virtualmachine,virtualmachineinstance,pods
kubectl describe virtualmachineinstance cirros
The VM controller should create a VMI and a launcher Pod if the cluster has an eligible node and sufficient resources. If the VMI remains pending, inspect its events and the Pod’s scheduling events; check node labels, resource requests, KVM availability, and admission errors. If the Pod starts but the guest does not become ready, inspect the VMI conditions and launcher logs. For durable workloads, replace the test container disk with a suitably provisioned persistent volume and define backup and restore procedures before storing important data.
Common Misconceptions
KubeVirt turns VMs into containers. It does not. Kubernetes schedules a launcher Pod, but the guest still has its own kernel, virtual devices, and operating-system lifecycle. The Pod is the bridge into Kubernetes orchestration.
A working Kubernetes cluster is automatically ready for VMs. Not necessarily. Worker nodes need compatible virtualization support and capacity, and the cluster needs storage and network configurations that fit the guests. A VMI can stay pending if no suitable node is available.
KubeVirt removes the need for a virtualization platform. KubeVirt is itself a VM management layer built into the Kubernetes ecosystem. It provides useful API integration, but teams should compare its supported features and operational model with their existing hypervisor platform rather than assume they are interchangeable.
Related Articles
- Kubernetes architecture explained covers the control plane, worker nodes, and Pod scheduling.
- Containerization vs. virtualization compares the isolation models KubeVirt brings together.
- Hardware virtualization explained describes KVM, CPU support, and virtual devices.
- Kubernetes homelab guide covers running Kubernetes on small hardware and virtualized nodes.
- Container networking explained introduces the networking concepts used by cluster workloads.
Changelog
- Initial publication.

