Friday, August 30, 2013

Auto register chef clients with EC2 auto scaling

I recently deployed an auto scale policy at work increasing front ends on demand. One of the challenges I found is to register each chef client on boot up and get it removed on termination.

First thing, the ami must contain - or must obtain on boot time trough scripts, there's some cool stuff the people have post in internet about this - these things:

  • a chef client installation
  • a valid client.rb file
  • a role file
  • the validation certificate (based on your chef setup)
In my case, my ami already has a chef client installed but with only these three files (the ones mentioned above) in the /etc/chef folder. My client.rb loos like this:


$ cat /etc/chef/client.rb
log_level        :warn
log_location     STDOUT
chef_server_url  "http://ec2-.us.compute.amazonaws.com:4000"
validation_client_name "chef-validator" 

My json file specifing the role - just one rule, frontend. Other cookbooks and roles can be added.

$ cat /etc/chef/first-boot.json
{"run_list":["role[frontend]"]}

As you may have noticed already my client.rb does not specify any node_name. We add this parameter on boot time - each node, different node_name. We also create a knife configuration file to delete the node and client on shutdown - I place it on /root/.chef but you can choose anywhere else:

$ sudo cat /root/.chef/knife.rb

log_level                :info
log_location             STDOUT
client_key               '/etc/chef/client.pem'
validation_client_name   'chef-validator'
validation_key           '/etc/chef/validation.pem'
chef_server_url          'http://ec2-us-west-1.compute.amazonaws.com:4000'
cache_type               'BasicFile'

Ok, we have the skeleton ready. Now we just need to validate the client in order to register the client and node. For this, I use a script named /etc/init.d/chef-register :
#!/bin/sh
### BEGIN INIT INFO
# Provides:           chef-register
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:      2 3 4 5
# Default-Stop:      0 2 3 4 5 6
# Short-Description:  registers / deletes chef client
case $1 in
        start)
        echo "***** Registering node and client *****"
        instance_id=`wget -q -O - http://169.254.169.254/latest/meta-data/instance-id`
        echo "node_name \"$instance_id\"" >> /etc/chef/client.rb
        echo "node_name '$instance_id'" >> /root/.chef/knife.rb
        /usr/bin/chef-client -j /etc/chef/first-boot.json
        ;;
        stop)
        echo "***** Deleting node and client *****"
        instance=`cat /etc/chef/client.rb | grep node_name | cut -d '"' -f 2`
        knife node delete $instance -c /root/.chef/knife.rb -y
        knife client delete $instance -c /root/.chef/knife.rb -y
        ;;
        *)
        echo $0 start or stop
        ;;
esac
Note that only once we validate the client we will obtain the client.pem on the /etc/chef folder.

To enable this script, we execute chmod +x /etc/init.d/chef-register  and update-rc.d chef-client defaults (for redhat based distros you will need to use chkconfig). On start, it will base the client name on the instance-id and put this parameter into both client.rb and knife.rb. On termination, it will delete the node and client - otherwise gets annoying when receiving timeouts deploying settings to the role.

That's it !

No comments:

Post a Comment