====== Ubuntu - KVM - Install and Configure KVM ======
===== Install KVM =====
sudo apt install qemu qemu-kvm libvirt-clients libvirt-daemon-system virtinst bridge-utils
where
* **qemu** - A generic machine emulator and virtualizer,
* **qemu-kvm** - QEMU metapackage for KVM support (i.e. QEMU Full virtualization on x86 hardware),
* **libvirt-clients** - programs for the libvirt library,
* **libvirt-daemon-system** - Libvirt daemon configuration files,
* **virtinst** - programs to create and clone virtual machines,
* **bridge-utils** - utilities for configuring the Linux Ethernet bridge.
----
===== 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: 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: 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: 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: 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: 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: 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: 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:
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:
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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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.
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: 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: 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: 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: 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: 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:
br0
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.