Ubuntu QEMU VM

From MK Wiki EN
Jump to navigation Jump to search

So far I installed operating systems in virtual machines to its virtual hard disk using a CD or DVD image (an ISO file), similar to what I would do on a real PC. Some years ago I noticed that Qemu has options to directly load a kernel and initial ramdisk (initrd) into the virtual ROM of the virtual computer, so it can directly start the kernel without needing a firmware to detect hard disks, seek for boot loader and the like (similar to what many embedded systems do as well, PCs normally don't do that). It's quite clear that this reduces the time for the machine to come up and also reduces the complexity and number of things that could go wrong. So I decided to make an experiment and see which steps are necessary to get such a virtual machine running.

Creating files for VM

First, I created a directory that contains all the files needed and copied my currently used kernel and initrd to that directory.

mkdir ubuntu_qemu
cp -v /boot/*$(uname -r)* ubuntu_qemu/
cd ubuntu_qemu

Next, I created a file that would represent the virtual hard disk (a raw image) and formatted that file with an ext3 file system. The size of that virtual hard disk is just 512 MiB, which would be enough for that experiment. For real world scenarios I strongly recommend a larger file!

dd if=/dev/zero of=testimage bs=1048576 count=512 # create 512 MiB image
mkfs.ext4 -L testpart testimage # format image with ext4

An alternative is to create an QCOW image and format it:

qemu-img create -f qcow2 drive0.img 1G
modprobe nbd max_part=16
qemu-nbd -c /dev/nbd0 drive0.img
partprobe /dev/nbd0
mkfs.ext4 -L label /dev/nbd0

If you want to have some spare disks, let them create in a batch:

for i in $(seq 1 4); do echo "Creating spare disk $i"; dd if=/dev/zero of=sparedisk$i bs=1048576 count=128; done

Installing Ubuntu

Ubuntu won't be installed using ubiquity as usual, but just by using "debootstrap" on my host system (which is Xubuntu 14.04 x64 with Linux 4.2.0-36 at time of writing).

dnsmasq on host

My bridge "br0" has an IP address of 10.92.92.253 and dnsmasq is listening on that address. YMMV - change as needed.

dnsmasq --interface=br0 --bind-interfaces --dhcp-range=10.92.92.1,10.92.92.128 # on host, start dnsmasq

debootstrap and network configuration

So we install Ubuntu using debootstrap and configure the installation.

mkdir mnt
mount testimage mnt/
debootstrap --arch=amd64 trusty mnt/ http://archive.ubuntu.com/ubuntu/ # downloads about 40 MiB; takes about 30 min
echo "/dev/sda	/	ext4	errors=remount-ro	0	1" > mnt/etc/fstab
echo "ubuntu_qemu" > mnt/etc/hostname # set a meaningful hostname
echo "auto eth0" > mnt/etc/network/interfaces

If dnsmasq (or some other DHCP server) is running on the host and listening on the bridge used, use this line

echo "iface eth0 inet dhcp"  >> mnt/etc/network/interfaces

Otherwise, use a static configuration:

echo "iface eth0 inet static" >> mnt/etc/network/interfaces
echo "    address 10.92.92.123" >> mnt/etc/network/interfaces
echo "    netmask 255.255.255.0" >> mnt/etc/network/interfaces
echo "    gateway 10.92.92.253" >> mnt/etc/network/interfaces

For more information on network configuration, see NetworkConfiguration in Debian Wiki.

Tell the system which DNS resolver you would like to use:

echo "nameserver 10.92.92.253" >  mnt/etc/resolv.conf

Setting passwords

Next, we'll chroot into the system:

chroot mnt/

In the chrooted environment:

passwd # set root password
useradd someuser # add a user
passwd someuser # set user's password

Then leave with Ctrl+D.

Booting the VM

qemu-system-x86_64 -kernel vmlinuz-4.2.0-36-generic -initrd initrd.img-4.2.0-36-generic \
  -boot d testimage -net nic,macaddr=52:54:e:2:11:10 -enable-kvm -name ubuntu1404qemu -net none -net bridge,br=br0 -m 512

Statistics

Disk usage

Right after the installation, df reported this:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda        488M  253M  210M  55% /

Then I installed the openssh server, which loaded a bunch of dependencies on the system:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda        488M  319M  144M  69% /

Memory

With 512 MiB RAM, /proc/meminfo reported this:

MemTotal:         500844 kB
MemFree:          408108 kB
MemAvailable:     464828 kB
Buffers:            5936 kB
Cached:            51096 kB
SwapCached:            0 kB
Active:            40088 kB
Inactive:          25776 kB
Active(anon):       8868 kB
Inactive(anon):      264 kB
Active(file):      31220 kB
Inactive(file):    25512 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:          8856 kB
Mapped:             9200 kB
Shmem:               304 kB
Slab:              17504 kB
SReclaimable:      10548 kB
SUnreclaim:         6956 kB
KernelStack:        1040 kB
PageTables:         1212 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      250420 kB
Committed_AS:      38900 kB
VmallocTotal:   34359738367 kB
VmallocUsed:        3304 kB
VmallocChunk:   34359730020 kB
HardwareCorrupted:     0 kB
AnonHugePages:         0 kB
CmaTotal:              0 kB
CmaFree:               0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       36856 kB
DirectMap2M:      487424 kB

Boot time

6 seconds after starting Qemu, Linux starts writing its output. After 20, I see the login prompt.

On my host, btrfs-tools is installed, so the initrd contains the code to seek for btrfs partitions, which takes about 3 seconds. Apparently, the boot time could be improved if btrfs was not used in the VM and the code was removed.

Outlook

This can be done also with a virtual machine using ARM architecture. Further information can be found here: