It's very easy to configure a machine as a KVM host these days. Modern releases of Ubuntu and Centos both offer simple installation methods that provide a useful system with minimal configuration.
Creating guests is a different story. A number of good tools are available, supporting a huge variety of installation scenarios. While it's reassuring to know you won't be limited by your tools, it can be a frustrating experience when you're just getting started.
This post shows how ubuntu-vm-builder can be used to go from zero to
fully-installed Chef client in under 2 minutes.
Installing KVM
Configuring the server as a KVM host is pretty straightforward. Ubuntu's KVM documentation is well-written, and a good place to start.
$ sudo apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder
By default, libvirt will create a host-only NAT network, with DHCP service, for guests to use. All my guests will be using a network I've created manually, so I've removed the default one.
$ virsh net-destroy default
Network default destroyed
$ virsh net-undefine default
Network default has been undefined
(Optional) Install apt-cacher-ng
Using apt-cacher-ng can speed up guest VM creation by keeping required packages on the host. This forum post provides a good walkthrough.
$ sudo apt-get install apt-cacher-ng
$ echo 'Acquire::http::Proxy "http://localhost:3142";' | sudo tee /etc/apt/apt.conf.d/01proxy
$ sudo ufw allow proto tcp from 192.168.42.0/24 to 192.168.42.1 port 3142
Configuring ubuntu-vm-builder
The easiest way of creating Ubuntu guests appears to be the
ubuntu-vm-builder tool. The
wiki documentation
is decent, and the command-line help is comprehensive - see
ubuntu-vm-builder kvm --help.
My ~/.vmbuilder.cfg sets the options that will be used for most (or
all) of my Ubuntu guests.
[DEFAULT]
domain = cryptocracy.com
gw = 192.168.42.1
dns = 192.168.42.1
firstboot = /home/zts/.vmbuilder/first-boot.sh
copy = /home/zts/.vmbuilder/copy-files
[ubuntu]
proxy = http://gateway.cryptocracy.com:3142
mirror = http://mirror.hetzner.de/ubuntu/packages
security-mirror = http://mirror.hetzner.de/ubuntu/security
suite = precise
components = main, universe
addpkg = openssh-server, acpid, chef
[kvm]
libvirt = qemu:///system
bridge = nat0
mem = 1024
cpus = 2
The initial build process happens in a RAM disk, which means that package installation is much faster than inside the guest.
As my guests will all be running Chef, I want to install the required packages during the initial build. This requires enabling an additional package repository, which can be achieved by customising the APT sources template used by vmbuilder.
deb $mirror $suite #slurp
#echo ' '.join($components)
deb $updates_mirror $suite-updates #slurp
#echo ' '.join($components)
deb $security_mirror $suite-security #slurp
#echo ' '.join($components)
#if $ppa
#for $p in $ppa
deb http://ppa.launchpad.net/$p/ubuntu $suite main
#end for
#end if
# The Opscode repository, for Chef
deb http://apt.opscode.com/ precise-0.10 main
For the new VM to register as a Chef client, it needs my validation
key. The copy option in .vmbuilder.cfg lists files on the host to
install in the guest.
/home/zts/.chef/validation.pem /etc/chef/validation.pem
Finally, we need a script to run when the guest first boots.
# Fix locale
echo 'LANGUAGE="en_US.UTF-8"' >> /etc/default/locale
echo 'LC_ALL="en_US.UTF-8"' >> /etc/default/locale
# Configure guest to use the host's apt-cacher-ng
echo 'Acquire::http::Proxy "http://gateway.cryptocracy.com:3142";' > /etc/apt/apt.conf.d/01proxy
# Configure and start chef-client
echo "chef chef/chef_server_url string http://chef.cryptocracy.com:4000" | debconf-set-selections
dpkg-reconfigure -u chef
Creating a Guest
At this point, we're ready to create guests. The required steps are:
- Create a volume for the guest's disk.
- Run ubuntu-vm-builder, passing a hostname and IP address along with the path to the volume.
- Start the guest.
$ sudo lvcreate -L 5G -n guest0 vg0
Logical volume "guest0" created
$ sudo ubuntu-vm-builder kvm -o --tmpfs - \
--raw /dev/mapper/vg0-guest0 \
--hostname guest0 \
--ip 192.168.42.3
2012-05-12 18:08:33,777 INFO : Mounting tmpfs under /tmp/tmpLRgUKMtmpfs
2012-05-12 18:08:33,810 INFO : Calling hook: preflight_check
2012-05-12 18:08:33,814 INFO : Calling hook: set_defaults
2012-05-12 18:08:33,814 INFO : Calling hook: bootstrap
2012-05-12 18:08:55,343 INFO : Calling hook: configure_os
2012-05-12 18:09:00,374 INFO : W: GPG error: http://apt.opscode.com precise-0.10 Release: The following signatures couldn't be verified because the p
ublic key is not available: NO_PUBKEY 2940ABA983EF826A
Extracting templates from packages: 100%
.
. output elided
.
2012-05-12 18:09:59,940 INFO : Calling hook: post_install
2012-05-12 18:09:59,941 INFO : Copying files specified by copy in: /home/zts/.vmbuilder/copy-files
2012-05-12 18:09:59,948 INFO : Calling hook: unmount_partitions
2012-05-12 18:09:59,948 INFO : Unmounting target filesystem
2012-05-12 18:10:03,713 INFO : Calling hook: convert
2012-05-12 18:10:03,714 INFO : Calling hook: fix_ownership
2012-05-12 18:10:03,715 INFO : Calling hook: deploy
2012-05-12 18:10:04,140 INFO : Unmounting tmpfs from /tmp/tmpLRgUKMtmpfs
$ virsh start guest0
Domain guest0 started
After waiting a moment for the guest to boot, we can check that it has registered itself with the Chef server:
$ knife node show guest0.cryptocracy.com
Node Name: guest0.cryptocracy.com
Environment: _default
FQDN: guest0.cryptocracy.com
IP: 192.168.42.3
Run List:
Roles:
Recipes:
Platform: ubuntu 12.04
Voila!