Cryptocracy

A blog

Bootstrapping Chef with ubuntu-vm-builder

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.

1
$ 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.

1
2
3
4
5
$ 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.

1
2
3
$ 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.

~/.vmbuilder.cfg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[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.

ubuntu/sources.list.tmpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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.

~/.vmbuilder/copy-files
1
/home/zts/.chef/validation.pem /etc/chef/validation.pem

Finally, we need a script to run when the guest first boots.

~/.vmbuilder/first-boot.sh
1
2
3
4
5
6
7
8
9
10
# 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:

  1. Create a volume for the guest’s disk.
  2. Run ubuntu-vm-builder, passing a hostname and IP address along with the path to the volume.
  3. Start the guest.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ 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:

1
2
3
4
5
6
7
8
9
$ 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!

Comments