Managing prebuilt OS images with Ansible

Prebuilt OS images

Prebuilt OS images are usually available for virtualization environments, for example see lists for OpenVZ, Vagrant, EC2, VirtualBox (also here) or Proxmox. As you can guess, some machinery is needed for building and maintaining them all. There is veewee for Vagrant, template creation guides for OpenVZ, dab for Proxmox, and so on.

The chroot connection

Ansible got support recently for executing tasks chrooted inside a local directory. The implementation was straightforward given Ansible agentless nature. chroot was added as a new connection type and that had two nice side effects:

  1. chroot directories can be added to the inventory like any other hostname.
  2. any existing playbook will potentially run chrooted by just setting the chroot connection type.

     - include: tasks/foo.yml ansible_connection=chroot
    

Putting things together

So you can now bootstrap your distro as usual, run a playbook chrooted to it and them archive the directory. That’s exactly what this example playbooks do.

$ git clone https://github.com/mmoya/ansible-playbooks.git
$ cd ansible-playbooks/image-creation
$ sudo ansible-playbook image-creation-stage1.yml
$ sudo ansible-playbook image-creation-stage2.yml

when the cow stops mooing you will have these tar.gz in /var/tmp/built-images:

as you can guess from the inventory, it’s trivial to add another debootstrap’able distribution.

[images-stage1]
/var/tmp/squeeze-raw-amd64          suite=squeeze       arch=amd64
/var/tmp/squeeze-raw-i386           suite=squeeze       arch=i386

[images-stage2]
/var/tmp/debian-6.0-64              baseimage=squeeze-raw-amd64.tar.gz
/var/tmp/debian-6.0-32              baseimage=squeeze-raw-i386.tar.gz

Two stages

I’ve identified two image categories:

  1. bare image: distro bootstrap with zero or minimal configuration.
  2. custom image: bare image with needed customization.

think of bare images as one per distro (squeeze, wheezy, precise, fedora18, etc…) and custom images as the ones typically published (debian-6.0-lamp-server, precise-nagios-server, fedora18-jboss, etc…). One bare image is used as base for building multiple custom images. Each stage builts one said category, this way it’s easier to cache the distro bootstrap for later reuse.

Missing stuff

I’m missing two things from the example:

  1. Make the playbook work with non Debian distros (febootstrap vs. deboostrap, file location differences, etc…)
  2. Specify extra software to install, ideally in the inventory (see 2290). Thinking in something like:

    [images-stage2]
    /var/tmp/debian-6.0-drupal baseimage=squeeze-raw-amd64.tar.gz install=lamp,drupal
    

Why bother?

There are some advantages of using Ansible instead of a custom script: