Table of Contents

Ubuntu - KVM - Install and Configure KVM

Install KVM

sudo apt install qemu qemu-kvm libvirt-clients libvirt-daemon-system virtinst bridge-utils

where


Start libvertd Service

sudo systemctl enable libvirtd
sudo systemctl start libvirtd
systemctl status libvirtd

returns:

● libvirtd.service - Virtualization daemon
     Loaded: loaded (/lib/systemd/system/libvirtd.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2020-08-10 18:44:51 BST; 5h 1min ago
TriggeredBy: ● libvirtd-admin.socket
             ● libvirtd.socket
             ● libvirtd-ro.socket
       Docs: man:libvirtd(8)
             https://libvirt.org
   Main PID: 1300 (libvirtd)
      Tasks: 19 (limit: 32768)
     Memory: 44.4M
     CGroup: /system.slice/libvirtd.service
             ├─1300 /usr/sbin/libvirtd
             ├─1595 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/lib/libvirt/libvirt_leaseshelper
             └─1596 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/lib/libvirt/libvirt_leaseshelper
 
Aug 10 23:46:37 bigmamba dnsmasq[1595]: reading /etc/resolv.conf
Aug 10 23:46:37 bigmamba dnsmasq[1595]: using nameserver 127.0.0.53#53
Aug 10 23:46:37 bigmamba dnsmasq[1595]: reading /etc/resolv.conf
Aug 10 23:46:37 bigmamba dnsmasq[1595]: using nameserver 127.0.0.53#53
Aug 10 23:46:47 bigmamba dnsmasq[1595]: reading /etc/resolv.conf
Aug 10 23:46:47 bigmamba dnsmasq[1595]: using nameserver 127.0.0.53#53
Aug 10 23:46:47 bigmamba dnsmasq[1595]: reading /etc/resolv.conf
Aug 10 23:46:47 bigmamba dnsmasq[1595]: using nameserver 127.0.0.53#53
Aug 10 23:46:47 bigmamba dnsmasq[1595]: reading /etc/resolv.conf
Aug 10 23:46:47 bigmamba dnsmasq[1595]: using nameserver 127.0.0.53#53

Setup Bridge networking with KVM

A bridged network shares the real network interface of the host computer with other VMs to connect to the outside network. Therefore each VM can bind directly to any available IPv4 or IPv6 addresses, just like a physical computer.

By default KVM setups a private virtual bridge, so that all VMs can communicate with one another, within the host computer. It provides its own subnet and DHCP to configure the guest’s network and uses NAT to access the host network.

Have a look at the IP address of the KVM default virtual interfaces using the ip command:

ip a

returns:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp4s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether b4:2e:99:3e:e5:20 brd ff:ff:ff:ff:ff:ff
3: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br0 state UP group default qlen 1000
    link/ether b4:2e:99:3e:e5:22 brd ff:ff:ff:ff:ff:ff
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether b4:2e:99:3e:e5:22 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.69/24 brd 192.168.1.255 scope global br0
       valid_lft forever preferred_lft forever
    inet6 fe80::b62e:99ff:fe3e:e522/64 scope link 
       valid_lft forever preferred_lft forever
5: wlp5s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether d0:ab:d5:91:98:3f brd ff:ff:ff:ff:ff:ff
6: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:99:38:bc brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
7: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:99:38:bc brd ff:ff:ff:ff:ff:ff

NOTE: Check the bottom 2 results.

The KVM default network virbr0 uses 192.168.122.1/24 IP address. All the VMs will use an IP address in the 192.168.122.0/24 IP range and the host OS will be reachable at 192.168.122.1. You should be able to ssh into the host OS (at 192.168.122.1) from inside the guest OS and use scp to copy files back and forth.

This is OK if you only access the VMs inside from the host itself. However we can't access the VMs from other remote systems in the network. Because they use different IP range i.e. 192.168.1.0/24 in my case. In order to access the VMs from other remote hosts, we must setup a public bridge that runs on the host network and uses whatever external DHCP server is on the host network. To put this in layman terms, we are going to make all VMs to use the same IP series used by the host system.


Disable Netfilter (optional)

You could disable Netfilter for performance and security reasons. Netfilter is currently enabled on bridges by default.

To disable netfilter, create a file called /etc/sysctl.d/bridge.conf:

sudo vi /etc/sysctl.d/bridge.conf

Add the following lines:

/etc/sysctl.d/bridge.conf
net.bridge.bridge-nf-call-ip6tables=0
net.bridge.bridge-nf-call-iptables=0
net.bridge.bridge-nf-call-arptables=0

Save and close the file.

Then create another file called /etc/udev/rules.d/99-bridge.rules :

sudo vi /etc/udev/rules.d/99-bridge.rules

Add the following line:

/etc/udev/rules.d/99-bridge.rules
ACTION=="add", SUBSYSTEM=="module", KERNEL=="br_netfilter", RUN+="/sbin/sysctl -p /etc/sysctl.d/bridge.conf"

This will set the necessary flags to disable netfilter on bridges at the appropriate place in system start-up. Save and close the file.

Reboot your system to take effect these changes.


Disable the default networking that KVM installed for itself

Find the name of KVM default network interfaces using ip link command:

ip link

returns:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp4s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether b4:2e:99:3e:e5:20 brd ff:ff:ff:ff:ff:ff
3: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br0 state UP mode DEFAULT group default qlen 1000
    link/ether b4:2e:99:3e:e5:22 brd ff:ff:ff:ff:ff:ff
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether b4:2e:99:3e:e5:22 brd ff:ff:ff:ff:ff:ff
5: wlp5s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DORMANT group default qlen 1000
    link/ether d0:ab:d5:91:98:3f brd ff:ff:ff:ff:ff:ff
6: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
    link/ether 52:54:00:99:38:bc brd ff:ff:ff:ff:ff:ff
7: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc fq_codel master virbr0 state DOWN mode DEFAULT group default qlen 1000
    link/ether 52:54:00:99:38:bc brd ff:ff:ff:ff:ff:ff

NOTE: The entries virbr0 and virbr0-nic are the KVM networks.


Remove the default KVM network

virsh net-destroy default

returns:

Network default destroyed

Undefine the default network

virsh net-undefine default

returns:

Network default has been undefined

NOTE: If the above commands do not work for any reason, you can use these commands to disable and undefine KVM default network:

sudo ip link delete virbr0 type bridge
sudo ip link delete virbr0-nic

Verify that the virbr0 and virbr0-nic interfaces are actually deleted

ip link

returns:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp4s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether b4:2e:99:3e:e5:20 brd ff:ff:ff:ff:ff:ff
3: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br0 state UP mode DEFAULT group default qlen 1000
    link/ether b4:2e:99:3e:e5:22 brd ff:ff:ff:ff:ff:ff
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether b4:2e:99:3e:e5:22 brd ff:ff:ff:ff:ff:ff
5: wlp5s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DORMANT group default qlen 1000
    link/ether d0:ab:d5:91:98:3f brd ff:ff:ff:ff:ff:ff

NOTE: The KVM default networks should be gone.


Setup the KVM public bridge to use when creating a new VM

WARNING: Do not use wireless network interface cards for bridges.

Most wireless interlaces do not support bridging.

Always use wired network interfaces for seamless connectivity!

To create a network bridge in host, edit 01-network-manager-all.yaml file and add the bridge details.

NOTE: Before editing this file, back it up.

sudo cp /etc/netplan/01-network-manager-all.yaml{,.backup}

Now edit similar to the following.

01-network-manager-all.yaml
 Let NetworkManager manage all devices on this system
#network:
#  version: 2
#  renderer: NetworkManager
 
# Let NetworkManager manage all devices on this system
network:
  version: 2
  #renderer: NetworkManager
  renderer: networkd
  ethernets:
    enp3s0:
      dhcp4: no
      # disable existing configuration for ethernet
      #addresses: [192.168.1.69/24]
      #gateway4: 192.168.1.1
      #nameservers:
        #addresses: [192.168.1.1]
      dhcp6: no
 
  # add configuration for bridge interface
  bridges:
    br0:
      interfaces: [enp3s0]
      dhcp4: no
      addresses: [192.168.1.69/24]
      gateway4: 192.168.1.1
      nameservers:
        addresses: [192.168.1.1,192.168.1.25]
      parameters:
        # stp: false
        stp: true
        forward-delay: 4
      dhcp6: no

After modifying the network config file, save and close it.

Apply the changes by running the following command:

sudo netplan --debug  apply

Now check if the IP address has been assigned to the bridge interface:

ip a

returns:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp4s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether b4:2e:99:3e:e5:20 brd ff:ff:ff:ff:ff:ff
3: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br0 state UP group default qlen 1000
    link/ether b4:2e:99:3e:e5:22 brd ff:ff:ff:ff:ff:ff
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether b4:2e:99:3e:e5:22 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.69/24 brd 192.168.1.255 scope global br0
       valid_lft forever preferred_lft forever
    inet6 fe80::b62e:99ff:fe3e:e522/64 scope link 
       valid_lft forever preferred_lft forever
5: wlp5s0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether d0:ab:d5:91:98:3f brd ff:ff:ff:ff:ff:ff

NOTE: The bridged network interface br0 is assigned with IP address 192.168.1.69 and the enp3s0 entry now has an master br0 entry. It means that enp3s0 belongs to the bridge.


Show the Bridge Status

brctl show br0

returns:

bridge name	bridge id		STP enabled	interfaces
br0		8000.b42e993ee522	yes		enp3s0

Configure KVM to use the bridge

Create a an XML file called bridge.xml.

Add the following lines:

bridge.xml
<network>
  <name>br0</name>
  <forward mode="bridge"/>
  <bridge name="br0"/>
</network>

Start the newly created bridge and make it as default bridge for VMs.

virsh net-define bridge.xml

returns:

Network br0 defined from bridge.xml

Start the bridge.

virsh net-start br0

returns:

Network br0 started

Configure the bridge to autostart each time the system reboots.

virsh net-autostart br0

returns

Network br0 marked as autostarted

Verify that the bridge is active and started

virsh net-list --all

returns:

 Name   State    Autostart   Persistent
-----------------------------------------
 br0    active   yes         yes

NOTE: Congratulations! The KVM bridge is active now.