Vagrant with the libvirt plugin

Here is a post about how to create virtual machines with Vagrant and the libvirt plugin.

Why use libvirt as a vagrant provider

Because when on a modern Linux distro running Gnome, chances are it's already there!

I use Vagrant extensively to run quick, short lived virtual machines to test and try out things. I always used and use Virtualbox as a virtual machine provider for Vagrant. Maybe I am late to the party but I recently discovered Gnome Boxes and I was wondering about the underlying architecture. Then I went on vacation and finally took the time to investigate.

The answer is: KVM. Together with QEMU and libvirt. (I remember using Qemu back in the 2007 or so but thinking it was terribly slow and left it for what is was. But its 2020 now, so let's dive in again!)

KVM, QEMU, libvirt: lost in the limbo

To refresh the memory a bit, a hypervisor is software that creates and runs virtual machines. Type 1 hypervisors (like Xen, ESXi and Hyper-V) run directly on the hardware. Type 2 hypervisors (Parallels, Virtualbox, Vmware Fusion) run on top of an OS. KVM turns Linux into a type 1 hypervisor, but at the same time runs a fully functional OS. So it is a special case of a hypervisor.

KVM provides device abstraction but does not emulate a machine. It exposes the /dev/kvm interface, which a user mode host can then use to:

  • Bootstrap an iso (set up theguest VM address space)
  • Feed the guest simulated I/O
  • Map the guest's video display back onto the system host

On Linux, QEMU is one such userspace host. QEMU uses KVM when available to virtualize guests at near-native speeds, but otherwise falls back to software-only emulation.

The last piece of the puzzle is libvirt Libvirt provides a convenient way to storage and network interface management for virtual machines. Libvirt includes an API library, a daemon (libvirtd), and a command line utility (virsh).

Gnome Boxes uses libvirt, as does Vagrant. Hence the blog title: using Vagrant with the libvirt plugin.

plaatje

Let's run a VM already

If you run this on Fedora 32, you can see that lots of packages are already installed:

1dnf list --installed | grep libvirt
2dnf list --installed | grep qemu

We need Vagrant and the vagrant-libvirt plugin:

1sudo dnf install vagrant
2sudo vagrant plugin install vagrant-libvirt

Then make a folder and add a Vagrantfile in it

 1
 2mkdir ~/vagrant/centos && cd ~/vagrant/centos
 3
 4cat > Vagrantfile <<'EOF'
 5$extra = <<-EXTRA
 6dnf update -y && dnf install vim net-tools git lsof tar -y
 7EXTRA
 8
 9Vagrant.configure("2") do |config|
10  config.vm.define "node01" do |node01_config|
11    node01_config.vm.box ="generic/centos8"
12    node01_config.vm.hostname = "centos01"
13    node01_config.vm.provider :libvirt do |domain|
14      domain.memory = 4096
15      domain.cpus = 2
16      domain.nested = true
17      domain.volume_cache = 'none'
18    end
19  end
20  config.vm.provision "shell", inline: $extra
21end
22EOF

And then do

1vagrant up

Hooray!

centos

Afterthought: What about LXC and LXD?

You can also run LXD instead of KVM. I think that LXD is the Canonical way, while KVM has been adopted by RedHat (fact check probably needed). Traditionally, LXD is used to create system containers, light-weight virtual machines that use Linux Container features and not hardware virtualization. However with LXD you can create both system containers and virtual machines. Here is a nice blog post explaining that.