Amazon AWS EC2 + Puppet, get Puppet to know AWS instance tags

amazon-web-servicespuppet

I am having a problem with my AWS deployment, fairly new to AWS and Puppet.

So coming to my question – can you distinguish puppet nodes with AWS machine tags or CNAME domains?

A little background about the plan:

  • have multiple clusters of machines, one php cluster, one legacy php cluster, one java cluster, one perl cluster
  • control configuration with puppet – still pretty new to puppet but as a developer I like the idea of being able to version control configuration of servers
  • have autoscaling enabled on those clusters – obviously the main benefit of the cloud that makes the much hight cost when it comes to any reasonable performance worth it (those amazon machines are slower than my phone…)
  • deployment controlled by Capistrano, this makes things a lot easier

So in AWS you get those super nasty public/private machine dns's… no way you can identify machines on those. In order to easer the problem, seams like AWS want's you to tag everything – so I did. Found a script that makes a CNAME record for each machine with the tag "ShortName" thanks to the Route53 API.

Every machine has a ShortName tag that becomes its CNAME, unfortunately puppet still resolves the private dns name.

I'd like to have

node 'perl-cluster'{}

in puppet, anyone any clue ho to achieve this?

Thanks

Best Answer

The way I've done it is to write a custom fact for the server to identify its role from user data, which can be accessed on 169.254.169.254, see your own user data...

AWS user-data documentation

curl http://169.254.169.254/latest/

so when I type facter role ill get 'dbserver', 'webserver' whatever, then use that to define a node, its important not to have autoscaling groups care the slightest about what the name of the server is.

/etc/puppet/manifests/nodes.pp

node default{
  include nodes::type
}

/etc/puppet/modules/nodes/manifests/init.pp

import “type.pp”

/etc/puppet/modules/nodes/manifests/type.pp

class nodes::type{
   case $role {
     “dbserver” : {
       include mysql
     }
   }
   case $role {
      “webserver” : {
       include httpd
     }
   }
}

/etc/puppet/manifests/modules.pp

 import nodes

I dont want to tell you exactly how to do it in your case, but here I'll show you how to create a custom fact to report the EC2 instance ID.

Facter, curl, are installed.

mkdir -p /home/ec2-user/lib/ruby/facter
export FACTERLIB=/home/ec2-user/lib/ruby/facter

cat > /home/ec2-user/lib/ruby/facter/instance_id < EOF
# instance_id.rb
#
require 'facter'
Facter.add("instance_id") do
    setcode "/usr/bin/curl -s http://169.254.169.254/latest/meta-data/instance-id"
    end
EOF

And lo, a custom fact was written.

Now I can use it to get the ec2 instance id:

$ facter instance_id
i-a1c0ffee

I dont have puppet installed on this machine, but if i wanted it available to puppet, id put in it /var/lib/puppet/lib/facter, and to distribute it to clients id ensure pluginsync=true in puppet.conf.

Bear in mind, all that ive said is highly subjective, its just how I do it, if theres a better way, I'd be interested.