I used to hate building operating system images. It was an arduous process that took up too much of my time. I would put off building them as much as possible. Need a change? No, do you really need that change because I need to devote a few hours to this. Churning out a new image was a slow, error prone, and frustrating task and was a friction point at times between the our TechOps team and other teams. Now with the help of Packer they are an order of magnitude faster to create and much easier to reliably build. Below is how we got there.
Building an OS image is easy, right? You just grab something from the AWS marketplace or if you want to get fancy maybe you create an image with a kickstart and use your own AMI. That’s your golden image which you use for your instances. Need to make updates? Take the golden image, make your changes, and rebundle it. Need to support different platforms? Maybe you have VMware in your data center, you’re experimenting with cloud providers, and your developers want something they can use locally. You can get by building a VMware template, using a pre-built cloud image, and have a VirtualBox image that’s shared around.
However we have our own set of requirements which made those processes unsuitable for us. They are:
This is where Packer started to help us out. Packer is a tool for creating identical OS images using a single source template. Packer starts with builders that describes the process for building images. The builders section of the template can take a list of builder. An organization’s OS maintainer could for example list builders for VMware, AWS, and VirtualBox. Below is a template that specifies Virtualbox, VMware, and AWS builders. Each time Packer is run using this template it will produce three OS images.
The next section of the template would be the provisioners. These are the scripts that would be run on each image after it was created during the builder phase. These can be anything from simple shell scripts to more complex configuration management like Puppet manifests or Chef recipes. If you’re familiar with RedHat kickstarts this would be like the scripts run in the kickstart %post section. Here you’re ensuring that all the images you’ve built go through the same set of configuration steps. In the example below we do familiar tasks such as cleaning NIC information and ensuring SSHD is locked down among other things.
Finally there’s the post-processors section where after you’ve built and configured your images you put the final touches on them. One popular post-processors is the Vagrant post processors. This will take an image and package it into a suitable Vagrant .box file for distribution to your developers. Through plugins this section can be extended to perform actions like deploying an image to VMware vSphere or arching your images to AWS S3. Below our template is just creating a Vagrant box.
Packer has made our process of making OS images far simpler than it used to be and it helps us to do so while maintaining the constraints we impose to make our environment more predictable. What was formerly a several hour process that required precise steps (not to mention repeated steps due to mistakes) is now handles by a few commands. We’ve even scripted Packer so that all our images can be generated with just a single command and no other developer intervention. This has freed us to experiment at a greater pace with new approaches to images and how we can make host deployments faster. No tool is perfect though. In another post I’ll write about how we scripted Packer to meet all of our needs.
If you'd like to talk more about how we use Packer or other DevOps related tools, find me on Twitter at @tmclaughbos - I love this stuff.