I’ve been meaning to write this up for the last few months but I wanted to get the code into a shape I liked first. The way EC2 works you spin up fresh virtual machines by doing: ec2-run-instance AMI-123 … and so the natural thing to do is if you need machines configured for different roles you take the time to stamp out a different AMI (aka Amazon Machine Image) for each role. That’s tedious. Alternately you can gin up an image which learns what role it should fill as it starts up. Some folks already build their AMI to let you do that. For example the kind folks at Alestic provide assorted AMI that include this feature: “On first boot, runs instance user-data script if it starts with #!”.
So here’s what I do. First I arrange to have the custom personality packed up in what I call a start-up-bundle. I put that someplace. In the example below it’s at: <http://example.s3.amazonaws.com/starters/start-up-example>. I prefer to have the file publicly available, so that fetching it trivial. But since it’s content is private I encrypt the file. In the example below the password for decrypting the file is “stirringdullroots”.
To start an machine up and have it take on this personality I then do: “ec2-run-instance ami-115db978 -f start-up-example-userdata …”
This is what you’d find in the file start-up-example-userdata, i.e. the script which grabs the starter bundle, decrypts it, and then recurs into the bundle to let the personality take shape.
trap 'echo ERROR Bootstrapping failed; exit 1' ERR
echo "Bootstrapping from <http://example.s3.amazonaws.com/starters/start-up-example>"
set -o pipefail
curl -s "http://example.s3.amazonaws.com/starters/start-up-example" | openssl enc -d -aes-256-cbc -k stirringdullroots | tar x
echo "Unpacked: `find start-up-bundle | wc -l` files"
echo "Run start-up scripts for various modules"
for i in */start-up.sh ; do
echo "Starting module $MODULE: via $i"
(cd $MODULE; bash start-up.sh)
echo "Finished starting module $MODULE"
So each startup bundle has two parts the userdata script, and the encrypted lump-o-personality.
Of course there are scripts for building start-up-bundles and other orchustration of the scheme, but that’s the heart of the story.
As you can see each machine’s personality consists of a set of modules. I have a collection of standard modules for things like java, perl, erlang, tinydns, rabbitmq, sbcl, etc. etc. One nice feature of this design is that it should be possible to make and share these with other folks.