Hey everyone. Matthew Sanabria here. A common question I get asked is,
How do I customize virtual machine images?
People customize virtual machine images for many reasons, to install software, perform security hardening, and to reduce deployment time. There are publicly available virtual machine images for your favorite operating system, but they usually don’t come out of the box with everything you need.
They require customization. There are two approaches to customizing virtual machine images: run-time customization, and build-time customization. Run-time customization involves provisioning a virtual machine and performing what I like to call last mile customization after the operating system has booted.
In this approach, you provision a virtual machine either manually or with Terraform. Then the last mile customization is performed by tools such as cloud-init, Ansible, or Chef. Run-time customization is a popular approach because it’s simple and works with almost every virtual machine image out there.
However, it’s not exactly a stable approach. Let’s say you use run-time customization to install your application dependencies. If you provision a virtual machine today, you might get version one of your dependency, and then if you provision another virtual machine next week, you might get version two of the dependency without further work.
There’s no guarantee that run-time customization will result in repeatable, identical virtual machines. You’ll get drift. What about build-time customization?
Build-time customization involves creating a new virtual machine image with customizations built into the image. You provision a virtual machine, connect to it and customize it.
Then you power it down and create a new virtual machine image. You can do this manually, but there are tools such as Packer that automate this process for you. Build-time customization is less popular than run-time customization, but it’s much more stable since the customization will be present in every virtual machine booted from that image, regardless of when the virtual machine is actually booted.
Let’s revisit the example from earlier using build-time customization to install our application dependencies. If you provision a virtual machine today, you’ll get version one of the dependency. If you then provision another virtual machine next week, you’ll get version one of the dependency again, no more drift.
Next time you’re asked to customize a virtual machine image, think about whether run-time customization, or build-time customization better suit your needs. With that, I’ll see you next time.