This page looks best with JavaScript enabled

Hiera in Puppet

 ·  🎃 kr0m

Hiera is a very simple key/value database that can be queried from our Puppet classes so that the code part is completely isolated from the data part, allowing us to write more reusable and generic classes.

We configure the path of the hiera config file.

vi /etc/puppet/puppet.conf

[main]
    hiera_config = $confdir/hiera.yaml

Hiera allows storing the config in various formats, we choose yaml. We also indicate the path where to look for the hierarchy and the structure in which to search. When a host meets the hierarchy, it will have access to the key/value parameters.

vi /etc/puppet/hiera.yaml
---
:backends:
  - yaml
:yaml:
  :datadir: /etc/puppet/hieradata
:hierarchy:
  - "%{::environment}/location/%{::location}"
  - "%{::environment}/common"

We create the necessary directories of the hierarchy.

mkdir -p /etc/puppet/hieradata/production/location/
mkdir -p /etc/puppet/hieradata/development/location/

We create a parameter common to all hosts in the production environment as an example and some parameters specific to each location:

vi /etc/puppet/hieradata/production/common.yaml

---
environment: prod
chmod 755 /etc/puppet/hieradata/production/common.yaml
vi /etc/puppet/hieradata/production/location/ISP1.yaml
---
zbx_server: 1.1.1.1
zbx_proxy: 1.1.1.2
bacula_server: 1.1.1.3
vi /etc/puppet/hieradata/production/location/ISP2.yaml
---
zbx_server: 2.2.2.1
zbx_proxy: 2.2.2.2
bacula_server: 2.2.2.3
chmod 755 /etc/puppet/hieradata/production/location/*
chown -R puppet:pupet /etc/puppet/hieradata/

We restart services.

/etc/init.d/foreman restart
/etc/init.d/apache2 restart

We check that PuppetMaster is reading the correct config.

puppet master --configprint all|grep hiera

data_binding_terminus = hiera
hiera_config = /etc/puppet/hiera.yaml

By default, Hiera looks for /etc/hiera.yaml, but Puppet looks for /etc/puppet/hiera.yaml. We have to do a little hack to make everything work.

rm /etc/hiera.yaml
ln -s /etc/puppet/hiera.yaml /etc/hiera.yaml
rm -rf /var/lib/hiera/
ln -s /etc/puppet/hieradata/ /var/lib/hiera

We manually ask PuppetMaster for the environment parameter.

hiera -d entorno ::environment=production

DEBUG: 2016-05-04 08:56:57 +0200: Hiera YAML backend starting
DEBUG: 2016-05-04 08:56:57 +0200: Looking up entorno in YAML backend
DEBUG: 2016-05-04 08:56:57 +0200: Looking for data source production/common
DEBUG: 2016-05-04 08:56:57 +0200: Found entorno in production/common
prod

We ask for the zbx_proxy parameter with ISP1 location and production environment.

hiera -d zbx_proxy ::location=ISP1 ::environment=production

DEBUG: 2016-05-04 09:35:31 +0200: Hiera YAML backend starting
DEBUG: 2016-05-04 09:35:31 +0200: Looking up zbx_proxy in YAML backend
DEBUG: 2016-05-04 09:35:31 +0200: Looking for data source production/location/ISP1
DEBUG: 2016-05-04 09:35:31 +0200: Found zbx_proxy in production/location/ISP1
1.1.1.1

In principle, the config can be queried from the clients with the puppet cli, but in my case, I couldn’t get it to work until I applied a class that used hiera and showed the data when the class was applied. Using puppet apply never worked for me, later on, you can find that example.

We manually request the data from the client.

puppet apply -e “notice(hiera(’entorno’))”

Error: Could not find data item entorno in any Hiera data file and no default supplied at line 1 on node host00.alfaexploit.com
Error: Could not find data item entorno in any Hiera data file and no default supplied at line 1 on node host00.alfaexploit.com

We create the test class in PuppetMaster.

mkdir -p /etc/puppet/modules/hieratest/manifests
vi /etc/puppet/modules/hieratest/manifests/init.pp

class hieratest {
        $entorno = hiera(entorno)
        $zbx_proxy = hiera(zbx_proxy)
        $bacula_server = hiera(bacula_server)
        notify {"Entorno: $entorno":}
        notify {"ZbxProxy: $zbx_proxy":}
        notify {"BaculaServer: $bacula_server":}
}
chown -R puppet:puppet /etc/puppet/modules/hieratest/

We import and apply the class from Foreman.

On the client, we run puppet.

puppet agent -t

Notice: Entorno: prod
Notice: Zbx_proxy: A.B.C.D
Notice: BaculaDir: bacula00

There are some recommendations to keep in mind:

  • Do not exceed the depth level of the hierarchy of hiera or performance will plummet, max: 5
  • It is possible to use hiera from templates but it is better to do it in the manifest of the class, assign the value to a local variable and reference it from the template.

If something doesn’t work, you can always try debugging with strace.

strace hiera -c /etc/puppet/hieradata/production/common.yaml -d environment ::environment=production 1&> output

If you liked the article, you can treat me to a RedBull here