Cloud computing and being lazy
The need to create template images in our cloud environment is obvious. Especially with Amazon EC2 offering an amazing API and spot instances in ridiculously low prices.
In the following post I’ll show what I am doing in order to prepare a “puppet-ready” image.
Puppet for the rescue
In my environment I have puppet configured and provisioning any of my machines. With puppet I can deploy anything I need – “if it’s not in puppet – it doesn’t exist”.
Coupled with Puppet dashboard the interface is rather simple for manually adding nodes. But doing stuff manually is slow. I assume that given the right base image I (and you) can deploy and configure that machine with puppet.
In other words, the ability to convert a bare machine to a usable machine is taken for granted (although it is heaps of work on its own).
Handling the “bare” image
Most cloud computing providers today provide you (usually) with an interface for starting/stopping/provisioning machines on its cloud.
The images the cloud providers are usually supplying are bare, such as CentOS 6.3 with nothing. Configuring an image like that will require some manual labour as you can’t even auto-login to it without some random password or something similar.
Create a “puppet ready” image
So if I boot up a simple CentOS 6.x image, these are the steps I’m taking in order to configure it to be “puppet ready” (and I’ll do it only once per cloud computing provider):
# install EPEL, because it's really useful rpm -q epel-release-6-8 || rpm -Uvh http://download.fedoraproject.org/pub/epel/6/`uname -i`/epel-release-6-8.noarch.rpm # install puppet labs repository rpm -q puppetlabs-release-6-6 || rpm -ivh http://yum.puppetlabs.com/el/6/products/i386/puppetlabs-release-6-6.noarch.rpm # i usually disable selinux, because it's mostly a pain setenforce 0 sed -i -e 's!^SELINUX=.*!SELINUX=disabled!' /etc/selinux/config # install puppet yum -y install puppet # basic puppet configuration echo '[agent]' > /etc/puppet/puppet.conf echo ' pluginsync = true' >> /etc/puppet/puppet.conf echo ' report = true' >> /etc/puppet/puppet.conf echo ' server = YOUR_PUPPETMASTER_ADDRESS' >> /etc/puppet/puppet.conf echo ' rundir = /var/run/puppet' >> /etc/puppet/puppet.conf # run an update yum update -y # highly recommended is to install any package you might deploy later on # the reason behind it is that it will save a lot of precious time if you # install 'httpd' just once, instead of 300 times, if you deploy 300 machines # also recommended is to run any 'baseline' configuration you have for your nodes here # such as changing SSH port or applying common firewall configuration for instance yum install -y MANY_PACKAGES_YOU_MIGHT_USE # and now comes the cleanup phase, where we actually make the machine "bare", removing # any identity it could have # set machine hostname to 'changeme' hostname changeme sed -i -e "s/^HOSTNAME=.*/HOSTNAME=changeme" /etc/sysconfig/network # remove puppet generated certificates (they should be recreated) rm -rf /etc/puppet/ssl # stop puppet, as you should change the hostname before it will be permitted to run again service puppet stop; chkconfig puppet off # remove SSH keys - they should be recreated with the new machine identity rm -f /etc/ssh/ssh_host_* # finally add your key to authorized_keys mkdir -p /root/.ssh; echo "YOUR_SSH_PUBLIC_KEY" > /root/.ssh/authorized_keys
Power off the machine and create an image. This is your “puppet-ready” image.
Using the image
Now you’re good to go, create a new image from that machine and any machine you’re going to create in the future should be based on that image.
When creating a new machine the steps you should follow are:
- Start the machine with the “puppet-ready” image
- Set the machine’s hostname
hostname=uga.bait.com hostname $hostname sed -i -e "s/^HOSTNAME=.*/HOSTNAME=$hostname/" /etc/sysconfig/network
hostname=uga.bait.com sudo -u puppet-dashboard RAILS_ENV=production rake -f /usr/share/puppet-dashboard/Rakefile node:add name=$hostname sudo -u puppet-dashboard RAILS_ENV=production rake -f /usr/share/puppet-dashboard/Rakefile node:groups name=$hostname groups=group1,group2 sudo -u puppet-dashboard RAILS_ENV=production rake -f /usr/share/puppet-dashboard/Rakefile node:parameters name=$hostname parameters=parameter1=value1,parameter2=value2
# initial run, might actually change stuff puppet agent --test service puppet start; chkconfig puppet on
This is 90% of the work if you want to quickly create usable machines on the fly, it shortens the process significantly and can be easily implemented to support virtually any cloud computing provider!
I personally have it all scripted and a new instance on EC2 takes me 2-3 minutes to load + configure. It even notifies me politely via email when it’s done.
I’m such a lazy bastard.