The biggest misconception about KVM and libvirt is that they are separate, competing technologies; in reality, libvirt is the management layer that makes KVM usable for everyday tasks.
Let’s get a virtual machine (VM) up and running. We’ll use virt-install, a command-line tool that leverages libvirt to orchestrate the creation of new VMs.
First, ensure you have the necessary packages installed. On a Debian/Ubuntu system, this would be:
sudo apt update
sudo apt install qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst
On a Fedora/CentOS/RHEL system:
sudo dnf install qemu-kvm libvirt-daemon libvirt-client bridge-utils virt-install
Next, start and enable the libvirt daemon:
sudo systemctl start libvirtd
sudo systemctl enable libvirtd
Now, let’s create a simple VM. We’ll use a minimal CentOS Stream ISO. Replace /path/to/CentOS-Stream-x86_64-dvd1.iso with the actual path to your ISO image.
virt-install \
--name my-centos-vm \
--ram 2048 \
--vcpus 2 \
--disk size=20 \
--os-variant centos8 \
--network bridge=virbr0 \
--graphics spice \
--cdrom /path/to/CentOS-Stream-x86_64-dvd1.iso
Let’s break this down:
--name my-centos-vm: Assigns a unique name to our VM.--ram 2048: Allocates 2048 MB (2GB) of RAM.--vcpus 2: Assigns 2 virtual CPUs.--disk size=20: Creates a new virtual disk image of 20GB. By default, this will be aqcow2format disk image stored in/var/lib/libvirt/images/.--os-variant centos8: Helps libvirt optimize the VM configuration for a CentOS 8 system. You can see a list of supported variants withosinfo-query os.--network bridge=virbr0: Connects the VM to the default NAT network managed by libvirt, namedvirbr0. This provides internet access to the VM.--graphics spice: Configures graphical access via the SPICE protocol. This is what you’ll connect to for the VM’s console.--cdrom /path/to/CentOS-Stream-x86_64-dvd1.iso: Specifies the installation media.
Once virt-install completes, it will typically launch a graphical console or provide instructions on how to connect. If it doesn’t automatically open a console, you can use virt-viewer:
virt-viewer my-centos-vm
This will open a window displaying the VM’s boot process and the OS installer. Follow the on-screen prompts to complete the CentOS installation.
After the OS is installed and the VM reboots, the virt-viewer window will show the OS login prompt. You can now manage this VM using virsh commands. For instance, to list running VMs:
virsh list --all
To shut down the VM gracefully:
virsh shutdown my-centos-vm
To forcefully destroy it:
virsh destroy my-centos-vm
To start it again:
virsh start my-centos-vm
The virsh tool interacts directly with the libvirt daemon, which in turn controls the KVM hypervisor (QEMU). This separation means libvirt can manage other hypervisors too, like Xen or even LXC containers, though KVM is its primary focus. The configuration for each VM is stored in an XML file, typically found in /etc/libvirt/qemu/. You can inspect or edit this file using virsh edit my-centos-vm.
The network configuration bridge=virbr0 is a crucial detail. virbr0 is a virtual bridge created and managed by dnsmasq (which libvirtd often uses) to provide NAT networking. This means your VM gets an IP address from a private subnet (e.g., 192.168.122.0/24) and can access the internet through your host’s network connection. If you need your VM to be on the same physical network as your host (e.g., to get an IP from your router’s DHCP server), you’d configure a different type of network, often involving a physical bridge interface on the host.
The real power of libvirt lies in its API and the tools that use it, allowing for automation, live migration, snapshots, and more, all abstracted from the underlying hypervisor details.
When you create a disk with virt-install without specifying a pool, it uses the default default storage pool, which usually points to /var/lib/libvirt/images/. If you attempt to create a VM with a disk image that already exists, virt-install might complain unless you explicitly tell it to use an existing disk.