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 !