J'aime pas les piles

My lost place

Node-less Puppet Setup Using Hiera

| Comments

Why?

Following a big puppet 2.7 => 3.3 space jump (it took quite some times to test/setup/adapt everything) I am trying to get a cleaner/saner puppet usage to avoid errors, duplication (allowing to easily override some conf for a specific deployment site at some specific location) and to avoid slapping my lazyness with a truit.

So I crawled a bit the web, and read a lot of different posts/bugs/idas/rants, and did not find the golden-wonderfull-definitive set-up guide, so here are the things that are on the way: * Use hiera for storing the nodes configuration * Assign classes using hiera (node-less setup?) * Create roles and profiles modules to allow to encapsulate contents not configurable using hiera

How?

Hiera base setup

Nothing to fancy here as shown in the hiera.yaml file, just an environment-dependent datadir and a first draft of the hierarchy that will be used.

hiera.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
---
:backends:
  - json
:json:
  :datadir: /etc/puppet/environments/%{::environment}/hieradata/
:hierarchy:
  - "%{::fqdn}"
  - "%{::company_role}"
  - "%{::company_location}"
  - "%{::virtual}"
  - "%{::operatingsystem}-${lsbdistrelease}"
  - "%{::operatingsystem}-${lsbmajdistrelease}"
  - "%{::operatingsystem}"
  - "%{::osfamily}"
  - common

# vim: set ft=yaml et smarttab sw=2 ts=2 sts=2:

Custom facts for hiera

Here two hiera data sources are meant to be able to easily configure a node according to its location or role. (location meaning more or less a more or less physical location with some specific network configuration or other specific rules/requirements)

In order to be able to assign the role and location, custom facts were added (company_role and company_location), based on the content of a file (/etc/company.conf) that have to be available on the server. (see XXX for more)

/etc/company.conf
1
2
role=puppet
location=ki
dist/site/lib/facter/gnbila-facts.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
require 'facter'

if File.exist?('/etc/company.conf')
  File.readlines('/etc/company.conf').each do |line|
    if line =~ /^(.+)=(.+)$/
      varname = "company" + $1.strip
      value = $2.strip

      Facter.add(varname) do
        setcode { value }
      end
    end
  end
end

# vim: set expandtab smarttab shiftwidth=2 tabstop=2 softtabstop=2 nocindent noautoindent:

Assigning class to nodes using hiera

hieradata/common.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
  "classes" : [
    "unix",
    "skel",
    "requiredsoftware",
    "pamldap",
    "git",
    "liquidprompt",
    "ruby",
    "ruby::dev",
    "postfix",
    "ntp",
    "sudo"
  ],

  "ntp::server" : [
      "0.fr.pool.ntp.org",
      "1.fr.pool.ntp.org",
      "2.fr.pool.ntp.org"
  ],
}
manifests/site.pp
1
2
# Load classes from hiera conf merging all classes for inclusion
hiera_include('classes')

Assigning defines to nodes using hiera

Defines parameters are stored in a hash, the key is the resource title and the value is a hash of define parameters.

hieradata/common.json
1
2
3
4
5
6
7
8
9
10
  "rsyslog_configs" : {
    "iptables.conf" : {
      "ensure" : "present",
      "source" : "puppet:///modules/site/rsyslog/rsyslog.d/iptables.conf"
    },
    "puppet-agent.conf" : {
      "ensure" : "present",
      "source" : "puppet:///modules/site/rsyslog/rsyslog.d/puppet-agent.conf"
      },
  },

Defines have to be instanciated calling create_resource with the retrieved define configuration hash.

manifests.y/site.pp
1
2
3
4
5
6
7
8
node default {
  # Load classes from hiera conf merging all classes for inclusion
  hiera_include('classes')

  # Retrieve rsyslog configurations if any
  $rsyslog_configs = hiera_hash('rsyslog_configs', {})
  create_resources('rsyslog::config', $rsyslog_configs)
}

Comments