# KubeVirt: running virtual machines as Kubernetes objects

> KubeVirt adds a VM resource type to Kubernetes and runs the controllers and agents that turn it into a running libvirt domain. It suits teams already operating clusters who need VMs under the same API, not teams looking for a standalone hypervisor.

**kubevirt/kubevirt** — Kubernetes Virtualization API and runtime in order to define and manage virtual machines.

- Repository: https://github.com/kubevirt/kubevirt
- Website: https://kubevirt.io
- Stars: 7,088 · Forks: 1,803
- Language: Go
- License: Apache-2.0
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/kubevirt-kubevirt

## The gap KubeVirt fills between pods and virtual machines

Kubernetes schedules containers. It has no concept of a virtual machine, no way to boot one, stop one, or move one between nodes. KubeVirt's stated aim in the README is to "provide a common ground for virtualization solutions on top of Kubernetes", and it does this by registering additional resource types, especially the VM type, through Kubernetes's Custom Resource Definitions API.

The target reader is an operator who already runs a cluster and has workloads that cannot be containerized. Legacy applications, kernels that need their own boot path, or images that assume a full machine. Those workloads currently live on a separate virtualization platform with its own API, its own scheduler and its own identity model. KubeVirt's pitch is that you stop maintaining that second control plane: a VM becomes another object in the same cluster, subject to the same RBAC, the same namespaces and the same tooling.

It is not a hypervisor in the classical sense, and the repository does not present it as one. It is an add-on. The README is explicit that the resources alone are not enough to launch virtual machines, and that the functionality is not added to Kubernetes itself but added to a cluster by running additional controllers and agents.

## What KubeVirt actually installs into your cluster

The architecture section of the repository separates the API surface from the runtime. Registering the VM custom resource gives you a place to write intent. Something has to reconcile that intent, and that something is a set of controllers and agents that KubeVirt runs on the existing cluster.

The README lists the declarative operations the project supports today: create a predefined VM, schedule a VM on a Kubernetes cluster, launch a VM, stop a VM, delete a VM. Read that list carefully. It is a lifecycle list, not a feature list. Scheduling is delegated to Kubernetes, which means the VM competes for the same node capacity as pods, and the same scheduling constraints apply.

The libvirt dependency is visible in the repository metadata: libvirt appears in the topics list and in the related resources, and the go.mod pulls in networking libraries such as containernetworking/cni and the network attachment definition client, plus vsock and VNC packages. That combination tells you what the runtime is doing: each VM is backed by a libvirt domain on a node, with networking wired through CNI and console access exposed over VNC or vsock. The examples directory makes the same point from the user side, with files such as examples/vm-cirros.yaml, examples/vmi-arm.yaml and examples/vmi-dra-pgpu.yaml, covering a plain VM, an ARM guest and a passthrough GPU claim respectively.

One design consequence is worth stating plainly. Because the VM is a Kubernetes object, its lifecycle is bound to cluster conventions that were designed for stateless workloads. Deletion, eviction and node pressure all apply. The examples directory includes examples/preemtible.yaml and examples/non-preemtible.yaml, which is a hint that preemption behaviour is something you configure rather than something you inherit for free.

## Installing KubeVirt and booting a first VM

The README does not carry install commands. It points to the quickstart at kubevirt.io/get_kubevirt and the user documentation at kubevirt.io/user-guide, so treat those as the authoritative source for the current install path rather than any snippet pasted elsewhere. What the repository does give you is a set of example manifests under examples/ that you apply to a cluster where KubeVirt is already running.

The simplest starting point in that directory is the CirrOS VM, a small image intended for exactly this kind of smoke test. After KubeVirt is installed, applying the example creates a VirtualMachine object and, through it, a VirtualMachineInstance that the controllers reconcile into a running domain. The manifest to apply is examples/vm-cirros.yaml.

For a guest that needs a disk provisioned from a container registry image, the repository ships examples/vm-alpine-datavolume.yaml, which pairs a VM with a DataVolume. That manifest is the one to read if your interest is persistent storage rather than a throwaway boot. A DataVolume creates and populates a PersistentVolumeClaim, so a bound claim should appear in your namespace once the import finishes. If it does not appear, the problem is storage or the importer, not the VM definition.

The repository's own development instructions are the only build commands the README documents, and they are not the path a cluster operator takes. For reference, the Makefile wraps the build in a container:

```bash
make bazel-build
```

That target runs hack/dockerized with the Bazel build scripts, which is how the project builds its own images. It is not how you install KubeVirt on a cluster.

## Where KubeVirt is the wrong tool

The first limitation is hardware. KubeVirt's topics list includes libvirt, and libvirt on Linux normally means KVM. The README never states that KVM is optional, and it never documents a software-emulation fallback. If your nodes are themselves virtual machines without nested virtualization exposed, or if you are on an architecture where the acceleration path is unavailable, you have no documented answer from the repository about whether a VM will start. That is a question to resolve before, not after, you migrate a workload.

The second limitation is operational weight. KubeVirt is not a binary you install on a host. It is controllers and agents running inside a cluster, and the Makefile shows how much machinery the project itself carries to build and test that: hack/dockerized, hack/multi-arch.sh, Bazel targets, and a provider abstraction under kubevirtci/. You inherit a Kubernetes cluster as a prerequisite, which means you inherit its upgrade cadence too. The repository points to a KubeVirt to Kubernetes version support matrix in the sig-release repo precisely because the pairing is not arbitrary. Running a KubeVirt release against an unsupported Kubernetes version is a configuration the project does not claim to support.

The third case is scale and shape of workload. If you have one physical host and a handful of VMs, a conventional hypervisor with a local management UI is less moving parts for the same result. KubeVirt pays off when the cluster already exists and the value is consolidation of control planes, not when the cluster would be built solely to host VMs.

## KubeVirt compared with Proxmox and Kata Containers

Proxmox is the comparison people reach for, and the difference is architectural rather than a matter of feature counts. Proxmox is a hypervisor platform with its own management layer, its own web interface and its own clustering. KubeVirt has no separate management plane: the Kubernetes API server is the management plane, and the objects you create are ordinary cluster objects. That means your existing kubectl workflows, admission policies and GitOps pipelines apply unchanged. It also means you cannot use KubeVirt without Kubernetes, whereas Proxmox stands alone.

Kata Containers is a different kind of comparison, and a common source of confusion. Kata is a container runtime that isolates containers using lightweight virtual machines. The unit of work stays a container and the container interface stays intact. KubeVirt goes the other way: the unit of work is a full virtual machine with its own guest kernel, and the VM is what you define and manage. If your workload is a container that needs stronger isolation, Kata is aimed at that problem. If your workload is a machine image that cannot be containerized, KubeVirt is aimed at that problem. They are not substitutes.

For GPU workloads specifically, the examples directory includes examples/vmi-dra-pgpu.yaml and examples/pgpu-resource-claim-tmpl.yaml, which indicates a dynamic resource allocation path for passthrough GPUs. That is a real capability, and it is also the kind of configuration where the details matter more than the headline.

## Licence, releases and what upgrades cost you

KubeVirt is distributed under the Apache License, Version 2.0. The README carries the standard Apache notice and the repository ships a LICENSE file at the top level. Apache-2.0 is permissive and includes an explicit patent grant, which matters if you are embedding the project in a commercial product. This is a description of the licence text, not legal advice; the terms that bind you are in the LICENSE file and the Apache 2.0 text it references.

On cadence, the release list shows v1.9.0 in July 2026 and a v1.10.0-alpha.0 in September 2026, with release candidates appearing before the stable cut. The repository maintains a sig-release repo holding the support matrix, pre-release notes for the upcoming release, and the release schedule. The practical upgrade cost is not the KubeVirt binary; it is the coupled upgrade of KubeVirt and Kubernetes. Because the support matrix is version-specific, an upgrade plan that moves Kubernetes without checking the corresponding KubeVirt release is how clusters end up in an unsupported combination.

The contribution process also carries a compliance requirement worth knowing if you intend to submit patches: every commit needs a Signed-off-by line certifying the Developer's Certificate of Origin 1.1, which git commit -s adds automatically.

## Conclusion

Adopt KubeVirt when Kubernetes is already your control plane and you want VMs declared, scheduled and deleted through the same API, with the k8s support matrix checked against your cluster version first. Do not adopt it as a replacement for a standalone hypervisor on a single host, or if you cannot run privileged workloads on the nodes. Before committing, verify that your Kubernetes version appears in the KubeVirt to Kubernetes support matrix in the sig-release repository, and confirm whether your workloads need KVM, since the README does not document a software-emulation fallback path.

## FAQ

### What is KubeVirt used for?

KubeVirt is a virtual machine management add-on for Kubernetes. It lets you declaratively create, schedule, launch, stop and delete VMs through the Kubernetes API alongside your other resources.

### How do you install KubeVirt?

The README does not include install commands. It directs readers to the quickstart at kubevirt.io/get_kubevirt and the user documentation at kubevirt.io/user-guide.

### Is KubeVirt a hypervisor?

No. The README describes it as a virtual machine management add-on for Kubernetes, and states that the resources alone are not enough to launch VMs; controllers and agents must run on the cluster. Libvirt appears in the project topics and related resources.

### Can you run Windows on KubeVirt?

The examples directory contains Windows-oriented manifests such as examples/vm-cirros-clarge-windows.yaml and examples/vm-windows-clarge-windows.yaml. The README itself does not document Windows support requirements.

### What is the difference between KubeVirt and Kata Containers?

The repository does not compare the two. From what it does state, KubeVirt manages full virtual machines as Kubernetes resources, while Kata Containers is not mentioned in the README, so the isolation model difference cannot be confirmed from this repository alone.

### What is CDI in KubeVirt?

The README does not define CDI. The examples directory does include examples/vm-alpine-datavolume.yaml, which pairs a VM with a DataVolume backed by a PersistentVolumeClaim.

## Sources

- [kubevirt/kubevirt on GitHub](https://github.com/kubevirt/kubevirt)
- [License: Apache-2.0](https://github.com/kubevirt/kubevirt/blob/main/LICENSE)
- [Project website](https://kubevirt.io)
- [README](https://github.com/kubevirt/kubevirt/blob/main/README.md)
- [Releases](https://github.com/kubevirt/kubevirt/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/kubevirt-kubevirt
