Bratty Redhead

the sarcasm is free!

Puppet for Chef Users - Part 2 - When Is a Node a Node?

Disclaimer: I have been working with Chef for about 18 months and Puppet for about 5 minutes.  I don’t claim to be an expert on Puppet nor warranty this information in any way.  It could all be egregiously wrong.  This is simply a blog exploring what I’m learning.

When is a node a node?  And when is it a thought?  Or a regex? When is it a description of a certain state of being?

When I first started working in someone else’s existing puppet domain, I was confused.  Everything was described in puppet/manifests/site.pp.  There was a lot of description.  Everything was called a node, regardless of what kind of object it was describing. Lists of manifests/classes were nodes, named servers were nodes, there were some regexs also designated nodes.  I was confused.

Check it out.  In Chef there are nodes.  A node is always the endpoint in question.  It’s a concrete item.  It just….is.  A VM is a node.  An AWS instance is a node.  If you want to describe a node, you add recipes or roles to it.  A recipe is a single thing.  A role is a collection of recipes, attributes and information that comprises a functional entity.

In Puppet, a node is a much more nebulous concept.  A node is still always the client endpoint.  But, the node can also be a described end state.

Let’s use the ubiquitous webserver example.  In my webserver, I will probably need a set of base OS modules/cookbooks and some webserver stuff.  I might have a requirement set that looks like this:

[ dns, ntp, ssh, syslog, puppet-agent|chef-client, apache, openssl, memcached ]

There are some differences in Puppet and Chef management structure.  In Chef, a node is a client, an endpoint. It’s pretty much always a server, whether hardware, VM or cloud instance.

In Chef I would write cookbooks for each of the items in my set.  Then I would probably create two roles: dotcom_base and webserver

roles/com_base.rb
——————–
name “dotcom_base”
description “The base role for ALL systems”
run_list(
    “recipe[chef-client]”,
    “recipe[syslog]”,  
    “recipe[ssh]”,
    “recipe[ntp]”,
    “recipe[dns]”
)

roles/webserver.rb
———————
name “webserver”
description “Role for Webservers”
run_list(
    “recipe[apache]”,
    “recipe[openssl]”,  
    “recipe[memcached]”
)

At this point I would then add both roles to any webserver node in my farm.  Or the roles would be added at bootstrap or your choice.  This information goes into node attributes stored in the attribute database.  There is no flat file representation of actual named nodes.

Puppet is all flat file management, requiring node management to be described in flat files.  Puppet has also chosen a flexible concept of node.

A node can be a collection of similar items:
node “dotcom_base” {
  include dns
  include ntp
  include syslog
  include puppet_agent
}

A node can be a type:
node “webserver”  inherits “dotcom_base” {
  include apache
  include openssl
  include memcached
 }

Given dotcom_web1.domain.com, dotcom_web2.domain.com, dotcom_web3.domain.com:

A node can just be a single endpoint:
node dotcom_web1.domain.com inherits “webserver”{ }

A node can be a collection of nodes matched with regex.
node /^dotcom_web\d+.domain.com$/ inherits “webserver” { }

A thought on node construction: To be more transparent, these could also say

inherits “dotcom_base” { webserver }

While I have not seen this notation, it’s what I would do if I were designing from the bottom up.  This may or may not be correct style-wise, but I’m a fan of transparency in my config statements.

Puppet node information can either be described in the top level puppet/manifests/site.pp or site.pp can include a second file traditionally called nodes.pp.  Site.pp can also include puppet conditionals, environment descriptions and params that might be specific to an environment, similar to Chef’s override attributes.

So, to recap, Chef and Puppet both have nodes.  Puppet describes many different objects which are all designated nodes.  Chef has chosen to break out object descriptions into roles and runlists for nodes.

Chef progression: cookbook/recipe=> role => node
Puppet progression: module/manifest => typed node description => specific/regex matched node description