Elegant way of categorizing puppet nodes in EC2 in Ubuntu Precise

amazon ec2amazon-web-servicespuppet

I'm trying to find a simple and elegant way of having puppet identify what kind of node it's working with in EC2. For simplicity, let's say I have 3 node types: web, api and db.

Now, the very simplest way would be to make the node names in the puppet manifest be equal to the random hostname that Amazon gives them such as:

node 'domU-12-12-12-12-12-AB' inherits 'common' {
  #you're a web instance
}
node 'domU-13-13-13-13-13-AC' inherits 'common' {
  #you're an api instance
}
node 'domU-14-14-14-14-14-AD' inherits 'common' {
  #you're a db instance
}

However this has the downside of trashing source control with node renames every time you add or shut down an instance and its natural hostname changes. The other downside is that the hostname changes and so the puppet node manifest would have to be patched up every single time.

One route that you often hear proposed is that of editing /etc/hosts and /etc/hostname to something like "web1" and then use a regex in the puppet node statement. The problem is that once again the private IP changes and thus you need to update /etc/hosts, so this is a big headache. You also now need to map the real Amazon-given hostname to the one you just gave to the instance, an additional headache. I read that cloud-init is a solution to this, but I haven't played around with it much.

I'm trying hard to avoid additional overhead / steps in the process that might be fragile and break, so I'm looking for a solution to the above that's first of all simple.

What would you recommend?

Best Answer

The recommended way to do this would be to classify your nodes using a custom fact.

You can use a nodes.pp like this:

node default {
  hiera_include('classes')
}

node /.*some.domain.com$/ inherits default {
}

This way, you can use hiera.yaml to easily assign modules while keeping the common modules in another yaml file. This could be an example:

---
:backends:
  - yaml
:hierarchy:
  - "%{::hostname}"
  - common
:yaml:
  :datadir: "/etc/puppet/hieradata/%{::domain}/%{::location}"

Where the location fact is defined in /etc/facter/facts.d/datacenter.yaml file, which can also have more facts, if needed:

---
location: rohan

The resulting directory structure for your hieradata could look like:


$ tree
.
├── hiera.yaml
└── some.domain.com
    ├── rohan
    │   ├── common.yaml
    │   ├── host.specific.yaml
    │   └── other.host.yaml
    └── mordor
        ├── common.yaml
        ├── some.host.yaml
        └── other.host.yaml

Some more ideas regarding the use of hiera to classify nodes can be found here.

Related Topic