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
- 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: <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.