Running virtual machines on your own metal: libvirt and KubeVirt after VMware

Introduction
When Broadcom closed its acquisition of VMware the invoice arrived shortly after. Renewal quotes landed at anywhere from two to ten times what teams had paid before, perpetual licences disappeared and the familiar per socket model gave way to per core billing with steep minimums. The response across the industry has been a quiet exodus. Red Hat reported that the number of virtual machines running on OpenShift Virtualization grew by 417 percent during 2025, with clusters running VMs up 93 percent and accounts up 70 percent.
Those are arresting numbers. They also describe a commercial product, and the headline can hide the more useful fact for any engineering team weighing its options. The engine underneath OpenShift Virtualization is entirely open source and you can run it yourself on hardware you already own. That engine is KubeVirt, and KubeVirt rests on libvirt, KVM and QEMU. None of it carries a licence fee.
I have often wondered if the easy access and ready availability of virtual machines in hyperscalers are causing engineers and product managers to forget that there are many other ways to run workloads, and that they’re simpler than you think. None of the hyperscalers reinvented the wheel after all, they just painted the frame in bright colours.
The open source stack hiding behind the marketing
OpenShift Virtualization, Harvester and the other packaged products courting former VMware customers are essentially convenience layers. Peel away the support contract and the polished console and you reach the same foundation that has powered Linux virtualisation for more than a decade.
At the bottom sits KVM, the kernel module that turns Linux itself into a type one hypervisor by exposing the hardware virtualisation extensions of the CPU. Above KVM runs QEMU, which emulates the devices a guest expects to see such as disks, network cards and a BIOS. On its own QEMU is powerful and fiddly.
It’s very likely you are already using this technology without knowing it. For example, I use a MacBook for work, and I run Colima for my containers (Docker, containerd). Colima essentially runs a virtual machine with QEMU where the containers live. Same if you run Docker Desktop or Rancher Desktop.
Whether you choose a single hypervisor host or a full Kubernetes platform, you are running the same battle tested core. The difference is how much orchestration you wrap around it.
libvirt and KVM: the foundation you can run today
If you have a handful of physical servers and you simply need to slice them into virtual machines, you do not need Kubernetes at all. A current Linux distribution, the KVM module and the libvirt daemon give you a capable hypervisor in minutes. Provisioning a guest is a single command:
1virt-install \
2 --name web01 \
3 --memory 4096 \
4 --vcpus 2 \
5 --cpu host-passthrough \
6 --disk path=/var/lib/libvirt/images/web01.qcow2,size=30,format=qcow2 \
7 --os-variant ubuntu24.04 \
8 --network bridge=br0,model=virtio \
9 --graphics none \
10 --location 'http://archive.ubuntu.com/ubuntu/dists/noble/main/installer-amd64/'From there the virsh command line manages the running estate. Listing, starting, stopping and inspecting guests are all one liners:
1virsh list --all
2virsh start web01
3virsh dominfo web01
4virsh shutdown web01Every guest is described declaratively as an XML domain, so you can keep those definitions in version control and rebuild a host from a known state. Tools such as virt-manager add a graphical view for engineers who want one, and virt-host-validate confirms a server is ready to run virtualisation before you commit to it.
Alternatively, you could use a UI like proxmox. If you come from the VMWare/vSphere world, this will feel more intuitive than the command line.
This is the right answer more often than people expect. For small fleets, edge sites, a lab, or a set of stable long lived appliances that never need to move between machines, the operational overhead of a cluster buys you nothing. A pair of well configured libvirt hosts with sensible backups and monitoring will serve faithfully for years. The moment you need to schedule virtual machines across many nodes, move them while running, treat them like any other declarative workload and unify their operations with the rest of a platform, the calculus changes. That is where KubeVirt enters.
KubeVirt: virtual machines as Kubernetes workloads
KubeVirt is a CNCF incubating project that teaches Kubernetes to run virtual machines as first class citizens alongside containers. Rather than replacing Kubernetes or standing up a separate platform, it extends the API with custom resources so that a virtual machine becomes just another object you describe in YAML and apply with kubectl. You define a VirtualMachine, the cluster creates a running VirtualMachineInstance, and that instance shows up next to your pods, governed by the same scheduling, networking and storage machinery you already operate.
The appeal for a team that has already invested in Kubernetes is obvious. A monolithic legacy application that resists containerisation can sit in the same cluster as the modern microservices that are gradually replacing it. The same GitOps pipeline that ships your containers can ship your virtual machines. The same role based access control, the same observability stack and the same on call runbooks cover both. You stop maintaining two separate worlds.
Inside the architecture
Understanding KubeVirt is easier once you see how it maps onto patterns Kubernetes engineers already know. It is built from controllers, a DaemonSet and a set of custom resource definitions.
The virt-operator installs and upgrades the platform and manages rolling updates with minimal disruption. The virt-api component provides the REST entrypoint that validates and serves the KubeVirt resources. The virt-controller runs at cluster level as a Deployment, watching VirtualMachine and VirtualMachineInstance objects and reconciling desired state into reality. When you ask for a machine to start, it is the controller that creates the pod to host it and that orchestrates the more delicate operations such as live migration by coordinating the source and target nodes.
On every node capable of hosting a guest, the virt-handler runs as a DaemonSet. It is the bridge between the Kubernetes view of the world and the actual hypervisor, watching for instances scheduled to its node and ensuring the underlying libvirt domain is booted or halted to match. The machine itself lives inside a virt-launcher pod, one per running instance. Here is the detail worth internalising: each virt-launcher pod contains its own libvirtd, and that local libvirt manages the QEMU process that is the virtual machine. The pod exists to provide the cgroups and namespaces that sandbox that QEMU process. So a KubeVirt virtual machine is a QEMU process, supervised by a libvirt instance, wrapped in a pod, scheduled by Kubernetes. The familiar foundation never went away. Kubernetes simply became the orchestrator on top of it.
Disks come from the Containerized Data Importer, a companion project that lets persistent volume claims act as virtual machine storage by importing images from a registry or web server, cloning existing volumes or accepting an uploaded image. The flow from intent to running guest reads cleanly: you create a VirtualMachine, the controller materialises an instance, a launcher pod is scheduled, and libvirt inside that pod brings QEMU to life on the chosen node.
What KubeVirt v1.8 changes
The project ships on a steady cadence and the v1.8 release of 25 March 2026 aligns with Kubernetes 1.35 and remains supported on the previous two Kubernetes versions. Several changes in this release matter to anyone planning a serious deployment.
The headline is the new Hypervisor Abstraction Layer. KubeVirt began life firmly wedded to KVM, and this layer opens the door to additional hypervisor backends while keeping KVM as the default. The significance is strategic. KubeVirt is positioning itself as a universal control plane for virtual machines rather than a single hypervisor tool, which is exactly the posture an organisation wants when it is consolidating a sprawling estate.
For teams running sensitive workloads, the Confidential Computing working group added support for Intel TDX attestation, so a confidential guest can now prove it is genuinely running on confidential hardware. For anyone placing machine learning workloads on this platform, the introduction of PCIe NUMA topology awareness lets virtualised AI and high performance computing jobs reach GPUs with latency close to bare metal, which removes much of the historical penalty for running these jobs inside a virtual machine.
On the operational side, incremental backup arrived using Changed Block Tracking built on the backup capabilities of QEMU and libvirt. Because it captures only modified blocks and does not depend on a particular CSI driver, it shrinks both backup windows and the storage footprint while keeping you free of any single storage vendor. The release also promoted the passt network binding from a plugin to a core binding, added ContainerPath volumes for more portable storage configuration, and made it possible to change a machine's backing network through a live migration without restarting the guest. The accumulation of these features is the real story. Capabilities that former VMware administrators consider non negotiable are landing in the open source project release after release.
A first VirtualMachine
A modern KubeVirt definition leans on instance types and preferences, which separate the sizing of a machine from the shape of its operating system and keep manifests tidy:
1apiVersion: kubevirt.io/v1
2kind: VirtualMachine
3metadata:
4 name: web01
5 labels:
6 app: web01
7spec:
8 runStrategy: Always
9 instancetype:
10 kind: VirtualMachineClusterInstancetype
11 name: u1.medium
12 preference:
13 kind: VirtualMachineClusterPreference
14 name: ubuntu
15 dataVolumeTemplates:
16 - metadata:
17 name: web01-root
18 spec:
19 sourceRef:
20 kind: DataSource
21 name: ubuntu2404
22 namespace: kubevirt-os-images
23 storage:
24 resources:
25 requests:
26 storage: 30Gi
27 template:
28 spec:
29 domain:
30 devices:
31 interfaces:
32 - name: default
33 masquerade: {}
34 networks:
35 - name: default
36 pod: {}
37 volumes:
38 - name: rootdisk
39 dataVolume:
40 name: web01-rootNote that the instance type and preference APIs settled on v1beta1 some time ago and the older alpha versions have been removed, so anyone carrying definitions forward from an early experiment should migrate before upgrading. Applying the manifest with kubectl apply is all it takes to bring the machine into being. Day to day interaction uses virtctl, the virtual machine aware companion to kubectl:
1virtctl start web01
2virtctl console web01
3virtctl vnc web01
4virtctl migrate web01That last command is the one that tends to win the room. Live migration of a running guest between nodes, driven by a single command and the same control plane that runs your containers, is the capability most teams are leaving VMware to preserve.
Choosing between a plain libvirt host and KubeVirt
The honest guidance is that KubeVirt is not automatically the answer, and a consultancy that tells you otherwise is selling rather than advising. If you run a small number of hosts, have no existing Kubernetes footprint and your machines rarely move, libvirt and KVM directly on the host will be cheaper to run and far simpler to reason about. You will not be paying the cognitive tax of a distributed system to manage three appliances.
KubeVirt becomes compelling when one or more of a few conditions hold. You already operate Kubernetes and want one platform rather than two. You need machines to migrate live across a fleet, to self heal onto healthy nodes and to be described and deployed through the same declarative pipelines as everything else. You are modernising incrementally and want legacy guests and new containers to coexist while you transition. Or you are placing AI workloads near GPUs and want the unified scheduling that the latest releases now make practical. The cost of KubeVirt is real and it is operational complexity. The benefit is consolidation and a single, well understood operating model. The trade is worth making only when the consolidation pays for the complexity.
Where to run it: on premises or European bare metal
A decision about hypervisors is really two decisions, because once you have stopped paying VMware you still have to choose where the metal lives. On premises is the natural home for organisations with their own datacentre space, predictable demand and a reason to keep everything physically close. For everyone else the more interesting option is hosted bare metal, and here the economics deserve a hard look.
The hyperscalers are superb at breadth, but their virtual machines are expensive and they only grow more expensive at scale, which is the very pattern that made the VMware renewal sting in the first place. A powerful bare metal server rented from a specialist European provider will frequently outperform a comparable cloud virtual machine on both price and performance, and when you run Kubernetes or a database directly on that hardware you also shed the virtualisation tax that a managed cloud quietly charges you. Europe has no hyperscaler of its own, yet it has a deep bench of capable providers such as Hetzner, OVHcloud, Scaleway and IONOS that will rent you serious hardware for a fraction of the equivalent cloud bill. Digitalis has made this case at length and the argument has only sharpened since.
There is an irony worth naming before someone in the comments does it for us. KubeVirt adds a virtualisation layer back on top of bare metal, so are we not reintroducing the overhead we just praised bare metal for avoiding? The answer is that you do it deliberately and only where it pays. You run performance critical databases and Kubernetes nodes straight on the metal and reserve KubeVirt for the legacy guests and mixed estates that genuinely need a virtual machine. The difference from the hyperscaler model is that you hold the dial rather than renting it back at a markup.
Cost is only half the story. Where your data physically sits has become a board level question. Hosting inside the European Union keeps you on the right side of GDPR and data residency obligations without the contortions that cross border transfers demand, and it removes the long reach of foreign legislation such as the US CLOUD Act over data held by American owned providers. The political weather has made the point impossible to ignore. Tariffs, an unpredictable US administration and a renewed appetite for digital sovereignty have pushed a steady stream of European organisations to ask whether their most sensitive systems really belong on infrastructure owned and governed from another continent. Running your own virtual machines on European bare metal answers that question cleanly. You own the stack, you choose the jurisdiction and no single foreign vendor holds the keys to either your data or your bill.
Final Thoughts
The exodus from VMware is real, but the most important number in it is not the 417 percent growth of a commercial product. It is the zero pound licence fee on the open source stack that product is built from, and the freedom to run that stack wherever serves your costs and your compliance, be that your own datacentre or rented European bare metal that undercuts the hyperscalers and keeps your data in your own jurisdiction. KVM, QEMU and libvirt have run serious workloads for over a decade, and you can adopt them today on hardware you already own. For a small, stable estate, libvirt on a well managed host is genuinely all you need. For a team that already runs Kubernetes and wants one platform for machines and containers, KubeVirt v1.8 has quietly closed most of the gap that once justified a proprietary hypervisor, from live migration to confidential computing to near bare metal GPU performance. The remaining hard part is not the technology. It is operating it well, which is a decision about where you want your engineers spending their attention. Start with a small proof of concept on a spare host, migrate one non critical workload end to end including a real restore, and let the operational reality rather than the marketing tell you which path fits.




