An uncommented guide to libvirt

Published » 2019-11-20

I've been quite a stout proponent of LXD aka Linux Containers inside my circles but unfortunately I've been running into some issues with reproducibility. This results from rapidly iterating snap builds and daily builds of Debian via distrobuilder. Without extra work, I fear that most people will encounter non-deterministic behavior on a more frequent cadence due to having a rolling distros and dismiss LXD as a real solution.

To avoid this, I encourage people to create their own build with Debian's debootstrap (see my earlier post and also pin your LXD version by using the stable channel only. In some cases, it might even be better to only use the LXD available in your distro's repository. Remember, back up frequently and assume things may fail.

That being said, libvirt is another rock solid alternative if you can handle the performance and resource costs. Here I'd like to share the configuration I used to quickly set up libvirt+debian.

Aside from the XML-based configuration, which I found quite enjoyable and refreshing, there aren't that many differences between the two. Yes you're running a virtual machine instead of a container but I have to say the qcow2+kvm backed VM feels incredibly more portable than the container. I hope this will change in the future but for now, I'm managing to run both Jira and Nextcloud in tiny containers (512MB RAM + 20G disk + 1 vCPU + 100Mbit network with macvlan) and I haven't noticed any performance concerns. This vCPU is running on a Intel J1900 by the way!

Here's the commands I ran to get the initial setup. I also consulted the following pages for additional help.

I found the XML format very descriptive and mostly self-evident. Do you agree? Can you understand what is being done?

Notes

  • If connecting to a remote server with qemu+ssh protocol, then make sure you have netcat installed on the remote side.

Debian configuration

# sudo apt install qemu qemu-utils libvirt

Network configuration

<network>      
  <name>isolated</name>
  <bridge name='virbr0' stp='on' delay='0'/>
  <ip address='172.16.1.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='172.16.1.2' end='172.16.1.16'/>
    </dhcp>
  </ip>
</network>

Pool (storage) configuration

mkdir /mnt/virtpool /mnt/virtdisks
mount /dev/mapper/virtual_pool /mnt/virtpool
chmod 770 /mnt/virtpool
$ virsh -c qemu:///system pool-define-as virtpool dir --target /mnt/virtpool
$ virsh -c qemu:///system pool-autostart virtpool
$ virsh -c qemu:///system pool-start virtpool
$ virsh -c qemu:///system net-define /tmp/isolated.xml
$ virsh -c qemu:///system net-autostart /tmp/isolated.xml
$ virsh -c qemu:///system net-start /tmp/isolated.xml
$ sudo systemctl enable serial-getty@ttyS0.service
$ sudo systemctl start serial-getty@ttyS0.service
virt-install --connect qemu:///system --name nextcloud --memory 1024 --cpu host-model --vcpus 1 --location http://deb.debian.org/debian/dists/stable/main/installer-amd64/ --disk pool=virtpool,size=20,sparse=false,format=qcow2,serial=BT-2 --disk pool=virtpool,size=64,sparse=false,format=qcow2,serial=BT-1 --graphics vnc,listen=0.0.0.0 --os-type linux --os-variant debian10 --network network=isolated --network type=direct,source=enp1s0,source_mode=bridge,model=virtio --extra-args="console=ttyS0,115200"

Guest (domain) configuration

<domain type="kvm">
  <name>debian-amd64-buster-10-2</name>
  <uuid>b04930b7-67dc-47d3-a22d-c2b1a431a610</uuid>
  <memory>1048576</memory>
  <currentMemory>1048576</currentMemory>
  <vcpu>1</vcpu>
  <os>
    <type arch="x86_64" machine="pc-i440fx-3.1">hvm</type>
    <boot dev="hd"/>
  </os>
  <features>
    <acpi/>
    <apic/>
  </features>
  <cpu mode="host-model"/>
  <clock offset="utc">
    <timer name="rtc" tickpolicy="catchup"/>
    <timer name="pit" tickpolicy="delay"/>
    <timer name="hpet" present="no"/>
  </clock>
  <pm>
    <suspend-to-mem enabled="no"/>
    <suspend-to-disk enabled="no"/>
  </pm>
  <devices>
    <emulator>/usr/bin/qemu-system-x86_64</emulator>
    <disk type="file" device="disk">
      <driver name="qemu" type="qcow2"/>
      <source file="/mnt/data/virtpool/debian-amd64-buster-10-2.qcow2"/>
      <target dev="hda" bus="ide"/>
      <serial>BT-DA61</serial>
    </disk>
    <disk type="file" device="disk">
      <driver name="qemu" type="qcow2"/>
      <source file="/mnt/data/virtpool/debian-amd64-buster-10-2-1.qcow2"/>
      <target dev="hdb" bus="ide"/>
      <serial>BT-EBB0</serial>
    </disk>
    <controller type="usb" index="0" model="ich9-ehci1"/>
    <controller type="usb" index="0" model="ich9-uhci1">
      <master startport="0"/>
    </controller>
    <controller type="usb" index="0" model="ich9-uhci2">
      <master startport="2"/>
    </controller>
    <controller type="usb" index="0" model="ich9-uhci3">
      <master startport="4"/>
    </controller>
    <interface type="network">
      <source network="isolated"/>
      <mac address="52:54:00:13:41:14"/>
      <model type="e1000"/>
    </interface>
    <interface type="direct">
      <source dev="enp1s0" mode="bridge"/>
      <mac address="52:54:00:ee:db:0c"/>
      <model type="virtio"/>
    </interface>
    <console type="pty">
      <target type="serial"/>
    </console>
    <input type="tablet" bus="usb"/>
    <graphics type="vnc" port="-1"/>
    <video>
      <model type="qxl"/>
    </video>
  </devices>
</domain>