I have been setting up a computer at home to act as a host for virtual machines. The machine is a recycled 10-year-old desktop with 4 cores, 32GB RAM and a 220GB SSD.
Growing the default disk
lvdisplay
lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
lvdisplay
df -h
resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv
df -h
Installing kvm and libvirt
Installing packages:
apt install qemu-kvm libvirt-bin virtinst bridge-utils cpu-checker
apt install libvirt-daemon-system virtinst libvirt-clients bridge-utils cloud-utils
Setting up users and starting daemons
systemctl enable --now libvirtd
systemctl start libvirtd
systemctl status libvirtd
usermod -aG libvirt simon
Setting up Networking
I needed to put the instance on a static IP and then create a bridge so any VMs that were launched were on the same network as everything else at home.
I followed these articles
First remove the default networks created by KVM
~# virsh net-destroy default
Network default destroyed
~# virsh net-undefine default
Network default has been undefined
then run “ip add show” to check just the physical network is left
backup and edit file in /etc/netplan ( 00-installer-config.yaml in my case) that has config for the network
Config created by installer:
# This is the network config written by 'subiquity'
network:
ethernets:
enp2s0:
dhcp4: true
version: 2
Replacement config:
network:
ethernets:
enp2s0:
dhcp4: false
dhcp6: false
bridges:
br0:
interfaces: [enp2s0]
addresses: [192.168.1.27/24]
routes:
- to: default
via: 192.168.1.254
mtu: 1500
nameservers:
addresses: [122.56.237.1, 210.55.111.1]
parameters:
stp: true
forward-delay: 4
dhcp4: false
dhcp6: false
version: 2
Note: The format in the 20.04 doc is slightly out of date (for the default route). Corrected in my file and the following link.
I used yamllint to check the config and “netplan try” and “netplan apply” to update.
Now we can make KVM aware of this bridge. create a scratch XML file called host-bridge.xml
and insert the following:
<network>
<name>host-bridge</name>
<forward mode="bridge"/>
<bridge name="br0"/>
</network>
Use the following commands to make that our default bridge for VMs:
virsh net-define host-bridge.xml
virsh net-start host-bridge
virsh net-autostart host-bridge
And then list the networks to confirm it is set to autostart:
$ virsh net-list --all
Name State Autostart Persistent
------------------------------------------------
host-bridge active yes yes
Booting a Virtual Machine
Now I want to create a Virtual machine image that I can base others I create off. I followed this guide:
Create Ubuntu 22.04 KVM Guest from a Cloud Image
First I downloaded the jammy-server-cloudimg-amd64.img from cloud-images.ubuntu.com. Note this is the ones that doesn’t have “disk” in it’s name.
~# wget http://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.im
g
Then I grew the disk image to 10GB and copied it to where libvirt could see it.
~# qemu-img resize jammy-server-cloudimg-amd64.img +8G
~# cp ubuntu-18.04-server-cloudimg-arm64.img /var/lib/libvirt/images/jammy2204.img
Now I need to configure the image, especially with a user and password so I can login. The way to do this is with cloud-init. This is a special file of commands to config a booting virtual machine. The weird thing with KVM is that the file is on a virtual cdrom attached to the virtual machine.
First create the config
#cloud-config
system_info:
default_user:
name: simon
home: /home/simon
password: hunter2
chpasswd: { expire: False }
hostname: ubuntu-22-cloud-image
# configure sshd to allow users logging in using password
# rather than just keys
ssh_pwauth: True
and save as bootconfig.txt . Then convert it to an iso and copy that to the images folder
~# cloud-localds bootconf.iso bootconf.txt
~# cp bootconf.iso /var/lib/libvirt/images/
~# virsh pool-refresh default
Now I run the program virt-manager locally. This is a graphical program that connects from my desktop over ssh to the the KVM server.
I use virt manager to connect to the KVM server and create a new virtual machine
- Machine Type should be “Ubuutu 22.04 LTS”
- It should boot off the jammy2204.img disk
- The bootconf.iso should be attached to the CDROM. But the machine does not need to boot off it.
- Set networking to be “Virtual network ‘host-bridge’: Bridge Network”
Boot the machine and you should be able to login to the console using the user:password you created in the cloud-config. You can then change passwords, update packages and otherwise configure the instance to you liking. Once you have finished you can shutdown the machine.
To create a new VM you just need to clone the disk:
~# virsh vol-clone --pool default jammy2204.img newvm.img
and then create a new Virtual machine in virt-manager using the disk (no need for the iso since the disk has the correct passwords)