KVM Tutorial On Ubuntu Server (KVM Networking)
Copyright (C) 2021 Exforge exforge@x386.xyz
# This document is free text: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
# This document is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# 0.0. Definition
# KVM virtualization tutorial 2 on Ubuntu 20.04 LTS Server.
# Please refer to 1st KVM tutorial before reading this one.
# This tutorial specializes on KVM Networking.
#
#
# 0.1. Infrastructure
# Server: (srv) Ubuntu 20.04 LTS Server on a 4 core CPU, 8 GB RAM no GUI
# IP: 192.168.0.240/24 and 10.1.1.1/24
# Workstation: (lahana) Ubuntu 20.04 LTS IP: 192.168.0.243
# Network1: 192.168.0.0/24 which is supplied by my internet modem (1st interface)
# Network2: 10.1.1.0/24 with an external switch (2nd interface)
#
# 0.2. Resources
# ISBN: 978-1-78829-467-6 KVM Virtualization Cookbook by Konstantin Ivanov
# ISBN 978-1-83882-871-4 Mastering KVM Virtualization 2nd Ed. by Vedran Dakic,
# Humble Devassy Chirammal, Prasad Mukhedkar, Anil Vettathu
1. KVM Networks – Configuration Commands
# Although it is possible to produce endless variations, there are 3 basic network types
# in KVM: Bridged, NAT, and Isolated.
# Before exploring KVM networking more, let's revise the commands for it.
#
# 1.1. Active Networks
# List KVM Networks:
virsh net-list
# We've already configured a bridged network on tutorial 1, so my server gives the
# following output:
#______________________________________________________
Name State Autostart Persistent
-------------------------------------------------
host-bridge active yes yes
#______________________________________________________
#
# To display information about a network, the following command can be used:
virsh net-info NETWORKNAME
virsh net-info host-bridge
# Output on my server:
#______________________________________________________
Name: host-bridge
UUID: a67dfcef-86e9-4e4c-832f-bc14443da475
Active: yes
Persistent: yes
Autostart: yes
Bridge: br0
#______________________________________________________
#
# We can display the information for the network as an XML file too:
virsh net-dumpxml NETWORKNAME
virsh net-dumpxml host-bridge
# Output on my server:
#______________________________________________________
<network>
<name>host-bridge</name>
<uuid>a67dfcef-86e9-4e4c-832f-bc14443da475</uuid>
<forward mode='bridge'/>
<bridge name='br0'/>
</network>
#______________________________________________________
#
# 1.2. Adding a Network
# To add a network, we must prepare the configuration in an XML file, and use the name
# of the file as a parameter.
virsh net-define XMLFILE
# As an example, I'm going to create another bridge on my 2nd interface and add that bridge
# to the KVM as another network.
# First create the bridge in the netplan file (If your netplan file is named as something
# else, change it to that.
sudo nano /etc/netplan/01-netcfg.yaml
#____________________________________________________
network:
ethernets:
enp3s0f0:
dhcp4: false
dhcp6: false
enx00e04c534458:
dhcp4: false
dhcp6: false
bridges:
br0:
interfaces: [ enp3s0f0 ]
addresses: [192.168.0.240/24]
gateway4: 192.168.0.1
mtu: 1500
nameservers:
addresses: [8.8.8.8,8.8.4.4]
parameters:
stp: true
forward-delay: 4
dhcp4: no
dhcp6: no
br1:
interfaces: [ enx00e04c534458 ]
addresses: [10.1.1.1/24]
gateway4: 10.1.1.1
mtu: 1500
nameservers:
addresses: [8.8.8.8,4.4.4.4]
dhcp4: no
dhcp6: no
version: 2
renderer: networkd
#_____________________________________________________
#
# enp3s0f0 is my 1st interface, its name is a bit funny, but my 2nd interface really has
# a weird name as enx00e04c534458. I guess that is because it is a USB network adapter.
# Anyway, don't forget to change the names as your adapters'.
# Now, it is time to create the XML file for the second bridge (namely br1).
sudo nano host-bridge2.xml
#_____________________________________________________
<network>
<name>host-bridge2</name>
<uuid>c723a80b-d496-460e-9235-9eced7b218cf</uuid>
<forward mode='bridge'/>
<bridge name='br1'/>
</network>
#_____________________________________________________
#
# Now we can define it
virsh net-define host-bridge2.xml
# Start it:
virsh net-start host-bridge2
virsh net-start NETWORKNAME
# Make it autostart (Starts when the server starts)
virsh net-autostart host-bridge2
virsh net-autostart NETWORKNAME
#
# Now we have 2 bridges. If we want a VM in 192.168.0.0/24 network we use br0, if we want it
# in 10.1.1.0/24 then we use br1.
#
# 1.3. Stopping and Removing KVM Networks
# Stop a KVM Network
virsh net-destroy NETWORKNAME
virsh net-destroy host-bridge2
# Disable autostart property of a KVM Network
virsh net-autostart NETWORKNAME --disable
virsh net-autostart host-bridge2 --disable
# Remove a KVM Network
virsh net-undefine NETWORKNAME
virsh net-undefine host-bridge2
2. KVM Networks – Network Types
# When preparing XML files for creating KVM networks, we use UUID and MAC values. These
# UUID and MAC must be unique for each network. Remember to replace them with unique values.
# Random UUID Generator
uuidgen
# Random MAC Address Generator
https://www.browserling.com/tools/random-mac
#
# 2.1. Bridged Networks
# I believe you already have an idea of bridged networks. It is like the host is sharing its
# interface and network with the VM. VM is in the same network as the host. If there is a
# DHCP Server on the network the host resides, the VM can use it to get an IP.
# If you are going to use a server which directly serves information or a service to the
# users, most probably you'll use a Bridged Network.
# To use a bridged network, first you need to create the bridge in the netplan file, and
# then prepare an XML file and add the network to the KVM with "virsh net-define"
# command, as we did in 1.2.
# A sample Bridged Network XML File:
#_____________________________________________________
<network>
<name>host-bridge2</name>
<uuid>c723a80b-d496-460e-9235-9eced7b218cf</uuid>
<forward mode='bridge'/>
<bridge name='br1'/>
</network>
#_____________________________________________________
# Considerations:
# Replace host-bridge2 with your chosen network name.
# Replace c723a80b-d496-460e-9235-9eced7b218cf with your generated uuid.
# Replace br1 with your bridge name in netplan file.
#
# 2.2. NAT Network
# A NAT (Network Address Translation) Network is similar (actually the same) to your home
# network behind your internet router. Your host's interface stands like your internet
# router and VMs are like your home devices. When VMs want to access to the network, they
# use host's IP address, but the other devices on the network cannot access to your VMs.
# This type of network is useful when you don't want anyone to access your VMs, but you
# want your VMs to access everywhere.
# An example of Routed Network XML File:
#_____________________________________________________
<network>
<name>nat</name>
<uuid>d589efd6-7d61-4f92-976b-bde62956cca7</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='brnat' stp='on' delay='0'/>
<mac address='4a:c3:6a:72:c2:30'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.101' end='192.168.122.254'/>
</dhcp>
</ip>
</network>
#_____________________________________________________
# Considerations:
# Replace nat with your chosen network name.
# Replace d589efd6-7d61-4f92-976b-bde62956cca7 with your generated uuid.
# Replace brnat with your chosen bridge name.
# Replace 52:54:00:6e:a9:d8 with your generated MAC address.
# Our nat bridge will have 192.168.122.1/24 IP and a DHCP server will announce addresses
# between 192.168.122.101 and 192.168.10.254. Change these values as you like.
#
# 2.3. Isolated Network
# An Isolated Network, as the name implies, is isolated. Noone can go out, noone can come in.
# The VMs in the isolated network cannot reach outside, and the devices outside cannot
# reach the VMs in the isolated network.
# Although it is very useful for testing purposes, there might be some situations that
# isolated network could be very useful. Consider you have a web server and a database
# server. The DB server can only be accessed by the web server and the web server will be
# accessed by everyone. You can put the DB server in an isolated network and define 2
# interfaces for the web server as 1 in a bridged network and the other one in the
# isolated network. That way, noone other than the web server can access the DB server.
# An example of Isolated Network XML File:
#_____________________________________________________
<network>
<name>isolated</name>
<uuid>a67bbbaf-81e9-4e4c-832f-bc14443da475</uuid>
<bridge name='brisolated' stp='on' delay='0'/>
<mac address='4a:c3:6a:72:c2:26'/>
<domain name='myisolateddomain'/>
<ip address='192.168.20.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.20.101' end='192.168.20.200'/>
</dhcp>
</ip>
</network>
#_____________________________________________________
# Considerations:
# Replace isolated with your chosen network name.
# Replace a67bbbaf-81e9-4e4c-832f-bc14443da475 with your generated uuid.
# Replace brisolated with your chosen bridge name.
# Replace 55:33:00:dd:dd:ee with your generated MAC address.
# Our nat bridge will have 192.168.20.1/24 IP and a DHCP server will announce addresses
# between 192.168.20.101 and 192.168.20.200. Change these values as you like.
3. Case Study A: Bridged and Isolated Networks Together
# 3.1. Specs:
# Our host has a bridged network on 192.168.0.0/24 (Network 1)
# Our host has an isolated network on 192.168.20.0/24 (Network 2)
# Our VM1 has 2 interfaces, 1 in Network1 and 1 in Network2
# Our VM2 has 1 interface in Network2
# After the installations, VM2 will be accessed by VM1 only, but VM1 will be accessed
# by all the devices on the network.
#
# 3.2. Create the Networks
# We already have Network1, lets create Network2
# Prepare XML File
nano isolated.xml
#_____________________________________________________
<network>
<name>isolated</name>
<uuid>a67bbbaf-81e9-4e4c-832f-bc14443da475</uuid>
<bridge name='brisolated' stp='on' delay='0'/>
<mac address='4a:c3:6a:72:c2:26'/>
<domain name='myisolateddomain'/>
<ip address='192.168.20.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.20.101' end='192.168.20.200'/>
</dhcp>
</ip>
</network>
#_____________________________________________________
#
# Create the network
virsh net-define isolated.xml
# Start it:
virsh net-start isolated
# Make it autostart
virsh net-autostart isolated
#
# 3.3. Create VM1 and VM2
# VM1
sudo virt-install --name vm1 \
--connect qemu:///system --virt-type kvm \
--memory 1024 --vcpus 1 \
--disk /srv/kvm/vm1.qcow2,format=qcow2,size=10 \
--cdrom /srv/isos/ubuntu20.04.iso \
--network bridge=br0 \
--network bridge=brisolated \
--graphics vnc,port=5901,listen=0.0.0.0 \
--os-type linux --os-variant ubuntu20.04 \
--noautoconsole
# VM2
sudo virt-install --name vm2 \
--connect qemu:///system --virt-type kvm \
--memory 1024 --vcpus 1 \
--disk /srv/kvm/vm2.qcow2,format=qcow2,size=10 \
--cdrom /srv/isos/ubuntu20.04.iso \
--network bridge=brisolated \
--graphics vnc,port=5902,listen=0.0.0.0 \
--os-type linux --os-variant ubuntu20.04 \
--noautoconsole
# Now you can connect VM1 and VM2 from your workstation and install them.
#
# 3.4. Considerations for Isolated Networks
# If a VM is in an isolated network, and if it has no connections to other networks, it
# cannot connect to the internet. That means, VM1 can connect to the internet and VM2
# cannot connect to the internet.
# Actually, when we put it in an isolated network, we accepted that it won't connect to
# other networks. But we need internet to install or update application.
# I have a not so bad solution for this situation. Install squid proxy to the host, make it
# listen to Isolated Network IP of host (192.168.20.1), allow all IPs to access it.
# Configure your VMs to use "apt" command through a proxy.
# I won't go in the details of installing and configuring squid proxy here, there are tons
# of materials on the internet about it.
# Configure your VM to use apt commands through a proxy:
# !!! Run on your VM !!!
sudo nano /etc/apt/apt.conf
# Add following line:
#_____________________________________________________
Acquire::http::proxy "http://10.1.1.1:3128";
#_____________________________________________________
#
# If you use username/password for the proxy, use the following format:
#_____________________________________________________
Acquire::http::proxy "http://user:pass@proxyserver:port";
#_____________________________________________________
4. Case Study B: Separating Host and VM Access with 2 NICs
# I don't know if it would be a best practice but definitely it will be a good practice to
# separate host's and VMs' network. That means, we will connect our host to our network
# with 2 interfaces; 1 interface will be used for accessing the host and the other will be
# used to access VMs.
#
# 4.1. Specs:
# Both interfaces of host are connected to my internet router.
# Our host has a bridged network on 192.168.0.0/24 (192.168.0.240-NIC 1)
# Our host has a standart network on 192.168.0.0/24 (192.168.0.241-NIC 2)
# Our VM will have 1 interface on bridged network.
# The first nic will be used by VMs and the second nic will be used to access the host.
#
# 4.2. Host Network Configuration
# Before the KVM network configuration, we need to configure the server's network.
# Edit netplan file (change if your netplan file has a different name):
sudo nano /etc/netplan/01-netcfg.yaml
#_______________________________________________________
network:
ethernets:
enp3s0f0:
dhcp4: false
dhcp6: false
enx00e04c534458:
addresses: [192.168.0.241/24]
gateway4: 192.168.0.1
nameservers:
addresses: [8.8.8.8,4.4.4.4]
bridges:
br0:
interfaces: [ enp3s0f0 ]
addresses: [192.168.0.240/24]
gateway4: 192.168.0.1
nameservers:
addresses: [8.8.8.8,8.8.4.4]
version: 2
renderer: networkd
#_______________________________________________________
#
# Apply the configuration, (You'd better restart the host)
sudo netplan apply
#
# 4.3. KVM Network Configuration
# We already configured our br0 bridge on KVM. But in case you didn't do it, or removed it.
# If you already have it, skip this step.
nano host-bridge.xml
#___________________________________________
<network>
<name>host-bridge</name>
<forward mode="bridge"/>
<bridge name="br0"/>
</network>
#___________________________________________
# Define the KVM Network
virsh net-define host-bridge.xml
# Start and make it autostarted:
virsh net-start host-bridge
virsh net-autostart host-bridge
#
# 4.4. Create a VM on the Bridged Network
# Now if we create a VM on br0 bridge, it will use the first interface of the host, and
# we will keep using the second interface at 192.168.0.241
sudo virt-install --name vm3 \
--connect qemu:///system --virt-type kvm \
--memory 1024 --vcpus 1 \
--disk /srv/kvm/vm3.qcow2,format=qcow2,size=10 \
--cdrom /srv/isos/ubuntu20.04.iso \
--network bridge=br0 \
--graphics vnc,port=5901,listen=0.0.0.0 \
--os-type linux --os-variant ubuntu20.04 \
--noautoconsole
5. Case Study C: NAT KVM Network
# We will create a VM, in a NAT network.
# 5.1. Specs:
# Server:
# Interface 1 is in bridged mode (as in 4.)
# Interface 2 is in standard mode (as in 4.)
# A NAT KVM network will be added through interface 2
# VM (Named vmn):
# An interface will be connected to the nat network
#
# 5.2. Host Network Configuration
# There is no change needed if you applied 4.2. Otherwise do it now.
#
# 5.3. KVM NAT Network Configuration
# Prepare XML File
nano nat.xml
#_______________________________________________________________
<network>
<name>nat</name>
<uuid>d589efd6-7d61-4f92-976b-bde62956cca7</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='brnat' stp='on' delay='0'/>
<mac address='4a:c3:6a:72:c2:30'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.101' end='192.168.122.254'/>
</dhcp>
</ip>
</network>
#_______________________________________________________________
# Remember to generate a new uuid and a new MAC address
# Remember to rename enx00e04c534458 to your second interface name
#
# Define the KVM Network
virsh net-define nat.xml
# Start and make it autostarted:
virsh net-start nat
virsh net-autostart nat
#
# 5.4. Create the VM
sudo virt-install --name vmn \
--connect qemu:///system --virt-type kvm \
--memory 1024 --vcpus 1 \
--disk /srv/kvm/vmn.qcow2,format=qcow2,size=10 \
--cdrom /srv/isos/ubuntu20.04.iso \
--network bridge=brnat \
--graphics vnc,port=5902,listen=0.0.0.0 \
--os-type linux --os-variant ubuntu20.04 \
--noautoconsole
# Your VM will be able to connect to your network, but the devices on your
# network will not be able to connect to it.
6. Adding and Removing Networks From a VM
# I assume that we have bridged and isolated networks ready on our host.
#
# 6.1. Specs
# VM Name: vm
# Initial Network: host-bridge (bridge br0)
# Network to be added: isolated
# Network to be removed: host-bridge (br0)
#
# We will create a VM with br0, then we will add it to the isolated network, and then
# we will remove the br0 network.
#
# 6.2. Create a VM with Bridged Network
sudo virt-install --name vm \
--connect qemu:///system --virt-type kvm \
--memory 1024 --vcpus 1 \
--disk /srv/kvm/vm.qcow2,format=qcow2,size=10 \
--cdrom /srv/isos/ubuntu20.04.iso \
--network bridge=br0 \
--graphics vnc,port=5902,listen=0.0.0.0 \
--os-type linux --os-variant ubuntu20.04 \
--noautoconsole
#
# 6.3. Add an Interface to the VM at the Isolated Network
virsh attach-interface vm bridge brisolated --target ens1 --config
# Add an interface to the VM named vm, network type is bridge and bridge name is brisolated,
# interface name on the VM (--target) will be ens1 and it will be active after shutdown
# and start again.
# Restart the VM, either by logging into it, or using the following commands at the host:
virsh destroy vm
virsh start vm
# "virsh reboot" does not work, it restarts the VM but the interface does not become active.
#
# 6.4. Configure the New Network at the VM
# The new interface ens1 will become active at the VM but it won't start, because it is not
# configured. We need to configure it using the netplan file.
sudo nano /etc/netplan/00-installer-config.yaml
# Change it as below
#______________________
network:
ethernets:
enp1s0:
dhcp4: true
ens1:
dhcp4: true
version: 2
#______________________
#
# Activate it
sudo netplan apply
# Now the VM will have an IP from 192.168.20.0/24 (isolated) network for the 2nd interface.
#
# 6.5. Remove the Bridged Network from the VM
# We want to remove the Bridged Network from the VM, we will accomplish it by removing its
# first interface (enp1s0).
# To do it, we need the MAC Address of the interface. Run the following command on the VM:
# !!! Run on the VM !!!
ip link show
# It will display something like below:
#____________________________________________________________________________
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: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 52:54:00:fe:4a:51 brd ff:ff:ff:ff:ff:ff
3: ens1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
link/ether 52:54:00:70:55:cf brd ff:ff:ff:ff:ff:ff
#____________________________________________________________________________
# My first interface is enp1s0, most probably yours will be the same, or something like it.
# At the line under the one starting with "2: enp1s0...", the part after link/ether is
# the MAC Address. Mine is: 52:54:00:fe:4a:51
#
# Now we return back to our host
virsh detach-interface ubuntu2 bridge --mac 52:54:00:fe:4a:51 --config
# When you shutdown and start your VM, the interface will be gone.