The article tells how to install qemu-kvm on Ubuntu linux and how how to boot first VM using cloud-init
Installation on ubuntu:
apt-get install qemu-kvm libvirt-bin virtinst cloud-image-utils libguestfs-tools
Validate if the machine can act as a hypervisor, see host properties:
virt-host-validate
libvirtd --version
virsh nodeinfo
virsh domcapabilities
Validation errors:
IOMMU appears to be disabled in kernel. Add intel_iommu=on to kernel cmdline arguments:
sudo vim /etc/default/grub:
GRUB_CMDLINE_LINUX="intel_iommu=on"
sudo update-grub
sudo reboot
Image info and resize:
qemu-img info ~/OS_Images/xenial-server-cloudimg-amd64-disk1.img
qemu-img resize ~/OS_Images/xenial-server-cloudimg-amd64-disk1.img +5
Now we need to resize the underlying filesystems using “virt-resize“. Note, however, that that “virt-resize” CANNOT resize disk images in-place. So we need to use make a backup copy and use the backup copy of the qcow as input and use the original qcow as output:
cp xenial-server-cloudimg-amd64-disk1.img xenial-server-cloudimg-amd64-disk1_orig.img
sudo virt-resize -v -x --expand /dev/sda1 xenial-server-cloudimg-amd64-disk1_orig.img xenial-server-cloudimg-amd64-disk1.img
FS info:
sudo virt-filesystems -l --all -a xenial-server-cloudimg-amd64-disk1.img
Prepare cloud-init user-data and meta-data:
cat user-data
#cloud-config
chpasswd: { expire: False }
ssh_pwauth: True
groups:
- ubuntu: [root,sys]
users:
- name: agrudev
gecos: Alex Grudev
primary_group: ubuntu
groups: users
lock_passwd: false
sudo: ALL=(ALL) NOPASSWD:ALL
plain_text_passwd: 'djkujuhf9'
ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDilSKhVkANZQLOY6zhLBxhKD0OabfORbuxL3H1o+\
#cloud-config
chpasswd: { expire: False }
ssh_pwauth: True
groups:
- ubuntu: [root,sys]
users:
- name: agrudev
gecos: Alex Grudev
primary_group: ubuntu
groups: users
lock_passwd: false
sudo: ALL=(ALL) NOPASSWD:ALL
plain_text_passwd: 'djkujuhf9'
ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDilSKhVkANZQLOY6zhLBxhKD0OabfORbuxL3H1o+\
Q0TfL223/I2A8FAqpZzu9RdX0FoOcP3S85S51IX1p4odipTAA9Wyp4jEtMNUUWvRkXWTvVR99+QNCq4QiB78c\
0JhtydKPu29DJNQr3/UHG877BCrLvOyiXFNrVZI+EBC+Md2SEqSN8e1P/DlORUrjgQKAxuKhMhDyoBbyBvnfK3\
2IYbs8bKlYZRusj1dlL3Jv/nR4VvN4YT+CzNOPCBTljFdcxuqdPZvqdAyMBIYDxaCxx2id96L98kYavKlqUZJn0x6m\
J8ndtHtfn+Fwjom/+8cPFUjuhULWsQiPRjfqA6p8r agrudev@agrudev-pc
cat meta-data
instance-id: ubuntu04
local-hostname: ubuntu-host-004
instance-id: ubuntu04
local-hostname: ubuntu-host-004
Prepare ISO image with user-data and meta-data:
genisoimage -output ./ubuntu04-cidata.iso -volid cidata -joliet -rock user-data meta-data
Boot OS image with KVM:
sudo virt-install --import --name kvm-ubuntu --ram 1024 --vcpus 1 --disk /home/agrudev/OS_Images/xenial-server-cloudimg-amd64-disk1.qcow2,bus=virtio --disk /home/agrudev/cloud-init/ubuntu04-cidata.iso,device=cdrom --network bridge=virbr0,model=virtio --os-type=linux --os-variant=ubuntu16.04 --graphics vnc,port=-1,listen=0.0.0.0
Check IP on the bridge virbr0:
cat /var/lib/libvirt/dnsmasq/virbr0.status
View libvirt networks:
virsh net-list --all
View certain network parameters:
virsh net-dumpxml default
<network>
<name>default</name>
<uuid>f93b1d19-b850-474a-a736-5a3973618404</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='virbr0' stp='on' delay='0'/>
<mac address='52:54:00:e3:32:60'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254'/>
</dhcp>
</ip>
</network>
<network>
<name>default</name>
<uuid>f93b1d19-b850-474a-a736-5a3973618404</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='virbr0' stp='on' delay='0'/>
<mac address='52:54:00:e3:32:60'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254'/>
</dhcp>
</ip>
</network>
if NAT is enabled like shown above the masquerade rule will be added to iptables:
Chain POSTROUTING (policy ACCEPT 54266 packets, 7611K bytes)
pkts bytes target prot opt in out source destination
134 13897 RETURN all -- * * 192.168.122.0/24 224.0.0.0/24
0 0 RETURN all -- * * 192.168.122.0/24 255.255.255.255
50 3000 MASQUERADE tcp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
1488 280K MASQUERADE udp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
1 84 MASQUERADE all -- * * 192.168.122.0/24 !192.168.122.0/24
pkts bytes target prot opt in out source destination
134 13897 RETURN all -- * * 192.168.122.0/24 224.0.0.0/24
0 0 RETURN all -- * * 192.168.122.0/24 255.255.255.255
50 3000 MASQUERADE tcp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
1488 280K MASQUERADE udp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
1 84 MASQUERADE all -- * * 192.168.122.0/24 !192.168.122.0/24
Start network:
virsh net-start isolated
Set network to start automatically:
virsh net-autostart <network>
Examples of Network XMLs (to be used in virsh net-define command. Note that KVM will add some stuff which you`ll see in virsh net-dumpxml output afterwards):
Isolated network (only VMs connected to the bridge can communicate):
# cat isolated.xml
<network> <name>isolated</name>
</network>
<network> <name>isolated</name>
</network>