Adding Virtualization Support

Author: Peter Boy (pboy) | Creation Date: 2021-03-31 | Last update: N/A | Affected Fedora Version(s): 33,34

Qemu-kvm in combination with Libvirt management toolkit is the standard virtualization methodology in Fedora. This includes a local virtual network for protected communication between the virtual guest systems with each other and with the host.

Preparation

QEMU / KVM require hardware virtualization support. The first thing to do is to make sure that it is available.

[…]# egrep --color 'vmx|svm' /proc/cpuinfo

The command will return one line per cpu core if virtualization is enabled. If not, you should first check in the BIOS whether virtualization is disabled.

Libvirt stores its data including the image files of the virtual hard disk(s) for the guest systems in /var/lib/libvirt. If you adhere to the default partitioning concept, the libvirt application data is stored in its own logical volume that you have to create in advance. You need to specify the size of the storage area, a unique name, and the accommodating VG (fedora_fedora in case of default partitioning). In the new logical volume, create an xfs file system and mount at /var/lib/libvirt.

Cockpit

The easiest way is to use Cockpit. Start your favorite browser and navigate to your server, named example.com here.

https://example.com:9090

If there is no valid public certificate installed so far, a browser warning appears and you have to accept an exception for the self-signed certificate. The subsequent login can use either the root account or an unprivileged administrative user account.

In Cockpit select "Storage" in the left navigation column and then the target volume group in the device list at the top of the right column of the opening window. The center content area changes to show the selected volume group at the top and a list of existing logical volumes below it that may be empty for now.

To create a logical volume select "Create logical volume" next to the 'Logical volumes' section title. In the form that opens, fill in the name of the new logical volume at the top, e.g. in this case 'libvirt'. Leave the usage field as 'File system' and adjust the size at the bottom, e.g. 500 GiB. Then create the LV.

In the 'Logical volumes' list, a new line appears with the LV name, libvirt in this example, as part of the device part on the right side. Expand that line and select 'format' on the right side. In the form that opens, fill in the name of the new file system, e.g. in this case 'libvirt', and the mount point, /var/lib/libvirt in this case. Leave the other fields at their default values. Select 'Format' and Cockpit will handle everything else.

After completion, the file system is immediately available and is also permanently configured in the system accordingly.

Command line

Some administrators may prefer the command line for easy scripting. Adjust size and VG name accordingly.

[…]# lvcreate -L 50G -n libvirt  fedora_fedora
[…]# mkfs.xfs /dev/fedora_fedora/libvirt
[…]# mkdir -p /var/lib/libvirt
[…]# vim /etc/fstab
/dev/mapper/fedora_fedora-root     /                  xfs   defaults    0 0
/dev/mapper/fedora_fedora-libvirt  /var/lib/libvirt   xfs   defaults    0 0
[…]# mount -a

Installing libvirt Virtualization Software

Installing the software is quite simple.

[…]# dnf install qemu-kvm libvirt virt-install cockpit-machines libguestfs-tools

Package libguestfs-tools provides various useful tools to maintain virtual disks. It is recommended not to install the group @virtualization onto a Fedora Server. It includes various graphical programs and libraries that are not usable on headless servers.

Next check the SELinux labels

[…]# ls -alZ /var/lib/libvirt

Usually, the installation adjusts the labels accordingly. Otherwise, an adjustment must be made manually.

[…]# /sbin/restorecon -R -vF /var/lib/libvirt

If everything is correct, libvirtd must be activated and started.

[…]# systemctl enable libvirtd  --now

By default, libvirt creates a bridge with an interface virbr0, the IP 192.168.122.1 and the internal name default. In addition, a separate firewall zone libvirt is set up. Check if everything is running as expected.

[…]# ip a
[…]# firewall-cmd --get-active-zones

Adjusting libvirt Configuration

The internal network should be used for the internal, protected communication of the VMs with each other and with the host. For this purpose, it is advantageous to set up a DNS for the internal network so that the VMs can be addressed by their names.

The first step is to decide about a domain name. A top-level ".local" is explicitly not recommended, nor taking one if the official top-level names. But for example, you can take the official domain name and replace the top-level domain with 'lan' or 'internal'. An official domain example.com would translate to an internal domain example.lan. We use that one throughout this tutorial. The host gets the internal name host.example.lan.

Modify libvirt default network

[…]# virsh  net-edit  default
<network>
  <name>default</name>
  <uuid>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</uuid>
  <bridge name='virbr0' stp='on' delay='0'/>
  <mac address='52:54:00:xx:yy:zz'/>
  <forward mode='nat'/>
  <mtu size='8000'/>
  <domain name='example.lan' localOnly='yes'/>
  <dns forwardPlainNames='no'>
    <forwarder domain='example.lan' />
    <host ip='192.168.122.1'>
      <hostname>host</hostname>
      <hostname>host.example.lan</hostname>
    </host>
  </dns>
  <ip address='192.168.122.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.122.2' end='192.168.122.254'/>
    </dhcp>
  </ip>
</network>

Activate the modified configuration

[…]# virsh net-destroy default
[…]# virsh net-start default

Converting the Hosts DNS Configuration

Local DNS systemd-resolved introduced with Fedora 33 fails to work with libvirt network configuration so far. As a consequence, DNS-split for forwarding internal name queries to libvirt DNS does not work. As for guest VM’s, however, their local DNS capabilities are not affected. Hence, the host cannot resolve the names of the VMs, but conversely, the VMs can resolve to each other and to the host.

As far as the latter is sufficient, no adjustment and no conversion are required. With the former, systemd-resolved must be disabled and replaced by NetworkManager’s dnsmasq plugin.

Configuration of NetworkManager’s dnsmasq plugin

Activate dnsmasq plugin

[…]# vim /etc/NetworkManager/conf.d/00-use-dnsmasq.conf
# /etc/NetworkManager/conf.d/00-use-dnsmasq.conf
#
# This enabled the dnsmasq plugin.
[main]
dns=dnsmasq

Define the local domain and DNS service

[…]# vim /etc/NetworkManager/dnsmasq.d/00-example-lan.conf
# /etc/NetworkManager/dnsmasq.d/00-example-lan.conf
#
# This file directs dnsmasq to forward any request to resolve
# names under the .example.lan domain to 192.168.122.1, the
# local libvirt DNS server.
server=/example.lan/192.168.122.1

Activate modified local DNS resolving

[…]# systemctl  stop  systemd-resolved
[…]# systemctl  disable  systemd-resolved
[…]# rm /etc/resolv.conf
[…]# nmcli con mod enp3s0 ipv4.dns-search 'example.lan'
[…]# nmcli con mod enp3s0 ipv6.dns-search 'example.lan'
[…]# systemctl  restart  NetworkManager

Check the functionality of name resolution with internal and external addresses.

[…]# ping host
[…]# ping host.example.lan
[…]# ping host.example.com
[…]# ping guardian.co.uk

Virtualization is now ready to use on the server and you can start setting up guest VMs.

These nice people helped write this page:

Fredrik Arneving, Peter Boy, Jan Kuparinen

Want to help? Learn how to contribute to Fedora Docs.