Hiera

Hiera allows you to create a hierarchy of node information. Using Hiera, you can separate your variables and data from your modules. You start by defining what that hierarchy will be, by ordering lookups in the main configuration file, hiera.yaml. The hierarchy is based on facts. Any fact can be used, even your own custom facts may be used. The values of the facts are then used as values for the YAML files stored in a directory, usually called hieradata. More information on Hiera can be found on the Puppet Labs website at http://docs.puppetlabs.com/hiera/latest.

Tip

Facts are case sensitive in Hiera and templates. This could be important when writing your hiera.yaml script.

Configuring Hiera

Hiera only needs to be installed on your Puppet master nodes. Using the Puppet Labs repo, Hiera is installed by the puppet-agent package. Our installation pulled down puppet-agent-1.2.2-1.el7.x86_64, which installs Hiera version 3.0.1, as shown here:

[thomas@stand ~]$ hiera --version
3.0.1

Previous versions of the command-line Hiera tool would expect the Hiera configuration file, hiera.yaml, in /etc/hiera.yaml. The previous versions of Puppet would expect the configuration file in /etc/puppet/hiera.yaml or /etc/puppetlabs/puppet/hiera.yaml, depending on the version of Puppet. This caused some confusion, as the command-line utility will, by default, search in a different file than Puppet. This problem has been corrected in Puppet 4; the Hiera configuration file is now located in the /etc/puppetlabs/code directory. The default location for the hieradata directory includes the value of the current environment and is located at /etc/puppetlabs/code/environments/%{environment}/hieradata.

Now, we can create a simple hiera.yaml in /etc/puppet/hiera.yaml to show how the hierarchy is applied to a node, as shown here:

---
:hierarchy:
  - "hosts/%{::hostname}"
  - "roles/%{::role}"
  - "%{::kernel}/%{::os.family}/%{:os.release.major}"
  - "is_virtual/%{::is_virtual}"
  - common
:backends:
  - yaml
:yaml:
  :datadir:

This hierarchy is quite basic. Hiera will look for a variable starting with the hostname of the node in the host's directory and then move to the top scope variable role in the directory roles. If a value is not found in the roles, it will look in the /etc/puppet/hieradata/kernel/osfamily/ directory (where kernel and osfamily will be replaced with the Facter values for these two facts) for a file named lsbmajdistrelease.yaml. On my test node, this would be /etc/puppet/hieradata/Linux/RedHat/6.yaml. If the value is not found there, then Hiera will continue to look in hieradata/is_virtual/true.yaml (as my node is a virtual machine, the value of is_virtual will be true). If the value is still not found, then the default file common.yaml will be tried. If the value is not found in common, then the command-line utility will return nil.

When using the hiera function in manifests, always set a default value, as failure to find anything in Hiera will lead to a failed catalog (although having the node fail when this happens is often used intentionally as an indicator of a problem).

As an example, we will set a variable syslogpkg to indicate which syslog package is used on our nodes. The syslog package is responsible for system logging. For EL7 and EL6 machines, the package is rsyslog; for EL5, the package is syslog. Create three YAML files, one for EL6 and EL7 at /etc/puppetlabs/code/environments/production/hieradata/Linux/RedHat/7.yaml using the following code:

---
syslogpkg: rsyslog  

Create another YAML file for EL5 at /etc/puppetlabs/code/environments/production/hieradata/Linux/RedHat/5.yaml using the following code:

---
syslogpkg: syslog

With these files in place, we can test our Hiera by setting top scope variables (facts), using a YAML file. Create a facts.yaml file with the following content:

is_virtual: true
kernel: Linux
os:
  family: RedHat
  release:
    major: "7"

We run Hiera three times, changing the value of os.release.major from 7 to 5 to 4 and observe the following results:

[thomas@stand ~]$ hiera syslogpkg -y facts.yaml environment=production
rsyslog
[thomas@stand ~]$ hiera syslogpkg -y facts.yaml environment=production
syslog
[thomas@stand ~]$ hiera syslogpkg -y facts.yaml environment=production
nil

In the previous commands, we change the value of os.release.major from 7 to 5 to 4 to simulate the nodes running on EL7, EL5 and EL4. We do not have a 4.yaml file, so there is no setting of syslogpkg and hiera that returns nil.

Now to use Hiera in our manifests, we can use the hiera function inline or set a variable using Hiera. When using Hiera, the syntax is hiera('variable','default'). The variable value is the key you are interested in looking at; the default value is the value to use when nothing is found in the hierarchy. Create a syslog module in /etc/puppet/modules/syslog/manifest/init.pp that starts syslog and makes sure the correct syslog is installed, as shown here:

class syslog {
  $syslogpkg = hiera('syslogpkg','syslog')
  package {"$syslogpkg":
    ensure => 'installed',
  }
  service {"$syslogpkg":
    ensure => true,
    enable => true,
  }
}

Then create an empty /etc/puppet/manifests/site.pp file that includes syslog, as shown here:

node default {
  include syslog
}

In this code, we set our default node to include the syslog module and then we define the syslog module. The syslog module looks for the Hiera variable syslogpkg to know which syslog package to install. Running this on our client node, we see that rsyslog is started as we are running EL7, as shown here:

[thomas@client ~]$ sudo puppet agent -t
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for client.example.com
Info: Applying configuration version '1442381098'
Notice: /Stage[main]/Syslog/Package[rsyslog]/ensure: created
Notice: /Stage[main]/Syslog/Service[rsyslog]/ensure: ensure changed 'stopped' to 'running'
Info: /Stage[main]/Syslog/Service[rsyslog]: Unscheduling refresh on Service[rsyslog]
Notice: Applied catalog in 7.83 seconds

Note

If you haven't already disable the LDAP ENC, which we configured in the previous section, the instructions are provided at the end of the LDAP backend section of this chapter.

In the enterprise, you want a way to automatically apply classes to nodes based on facts. This is part of a larger issue of separating the code of your modules from the data used to apply them. We will examine this issue in greater depth in Chapter 9, Roles and Profiles. Hiera has a function that makes this very easy—hiera_include. Using hiera_include, you can have Hiera apply classes to a node based upon the hierarchy.

Using hiera_include

To use hiera_include, we set a Hiera variable to hold the name of the classes we would like to apply to the nodes. By convention, this is called classes, but it could be anything. We'll also set a variable role that we'll use in our new base class. We modify site.pp to include all the classes defined in the Hiera variable classes. We also set a default value if no values are found; this way we can guarantee that the catalogs will compile and all the nodes receive at least the base class. Edit /etc/puppetlabs/code/environments/production/manifest/site.pp, as follows:

node default {
  hiera_include('classes', 'base')
}

For the base class, we'll just set the motd file, as we've done previously. We'll also set a welcome string in Hiera. In common.yaml, we'll set this to something generic and override the value in a hostname-specific YAML file. Edit the base class in /etc/puppetlabs/code/environments/production/modules/base/manifests/init.pp, as follows:

class base {
  $welcome = hiera('welcome','Welcome')
  file {'/etc/motd':
    mode => '0644',
    owner => '0',
    group => '0',
    content => inline_template("<%= @welcome %>
Managed Node: <%= @hostname %>
Managed by Puppet version <%= @puppetversion %>
"),
  }
}

This is our base class; it uses an inline template to set up the message of the day file (/etc/motd). We then need to set the welcome information in hieradata; edit /etc/puppet/hieradata/common.yaml to include the default welcome message, as shown here:

---
welcome: 'Welcome to Example.com'
classes:
  - 'base'
syslogpkg: 'nothing'

Now we can run Puppet on our node1 machine. After the successful run, our /etc/motd file has the following content:

Welcome to Example.com
Managed Node: client
Managed by Puppet version 4.2.1

Now, to test if our hierarchy is working as expected, we'll create a YAML file specifically for client, /etc/puppetlabs/code/environments/production/hieradata/hosts/client.yaml, as follows:

---
welcome: 'Welcome to our default node'

Again, we run Puppet on client and examine the contents of /etc/motd, as shown here:

[thomas@client ~]$ cat /etc/motd
Welcome to our default node
Managed Node: client
Managed by Puppet version 4.2.1

Now that we have verified that our hierarchy performs as we expect, we can use Hiera to apply a class to all the nodes based on a fact. In this example, we'll use the is_virtual fact to do some performance tuning on our virtual machines. We'll create a virtual class in /etc/puppet/modules/virtual/manifests/init.pp, which installs the tuned package. It then sets the tuned profile to virtual-guest and starts the tuned service, as shown here:

class virtual {
  # performance tuning for virtual machine
  package {'tuned':
    ensure => 'present',
  }
  service {'tuned':
    enable => true,
    ensure => true,
    require => Package['tuned']
  }
  exec {'set tuned profile':
    command => '/usr/sbin/tuned-adm profile virtual-guest',
    unless => '/bin/grep -q virtual-guest /etc/tune-profiles/activeprofile',
  }
}

Note

In a real-world example, we'd verify that we only apply this to nodes running on EL6 or EL7.

This module ensures that the tuned package is installed and the tuned service is started. It then verifies that the current tuned profile is set to virtual-guest (using a grep statement in the unless parameter to the exec). If the current profile is not virtual-guest, the profile is changed to virtual-guest using tuned-adm.

Note

Tuned is a tuning daemon included on enterprise Linux systems, which configures several kernel parameters related to scheduling and I/O operations.

To ensure that this class is applied to all virtual machines, we simply need to add it to the classes Hiera variable in /etc/puppet/hieradata/is_virtual/true.yaml, as shown here:

---
classes:
  - 'virtual'

Now our test node client is indeed virtual, so if we run Puppet now, the virtual class will be applied to the node and we will see that the tuned profile is set to virtual-guest. Running tuned-adm active on the host returns the currently active profile. When we run it initially, the command is not available as the tuned rpm has not been installed yet, as you can see here:

[thomas@client ~]$ sudo tuned-adm active
sudo: tuned-adm: command not found

Next, we run puppet agent to set the active profile (tuned is installed by default on EL7 systems):

[thomas@client ~]$ sudo puppet agent -t
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for client.example.com
Info: Applying configuration version '1442383469'
Notice: /Stage[main]/Virtual/Exec[set tuned profile]/returns: executed successfully
Notice: Applied catalog in 1.15 seconds

Now, when we run tuned-adm active we see that the active profile has been changed accordingly:

[thomas@client ~]$ sudo tuned-adm active
Current active profile: virtual-guest

This example shows the power of using Hiera, with hiera_include and a well-organized hierarchy. Using this method, we can have classes applied to nodes based on facts and reduce the need for custom classes on nodes. We do, however, have the option of adding classes per node since we have a hosts/%{hostname} entry in our hierarchy. If you had, for instance, a module that only needed to be installed on 32-bit systems, you could make an entry in hiera.yaml for %{architecture} and only create an i686.yaml file that contained the class in question. Building up your classes in this fashion reduces the complexity of your individual node configurations.

In fact, in Puppet version 3, architecture is available as both architecture and os.architecture.

Another great feature of Hiera is its ability to automatically fill in values for parameterized class attributes. For this example, we will create a class called resolver and set the search parameter for our /etc/resolv.conf file using Augeas.

Note

Augeas is a tool to modify configuration files as though they were objects. For more information on Augeas, visit the project website at http://augeas.net. In this example, we will use Augeas to modify only a section of the /etc/resolv.conf file.

First, we will create a resolver class as follows in /etc/puppetlabs/code/environments/production/modules/resolver/manifests/init.pp:

class resolver($search = "example.com") {
  augeas { 'set resolv.conf search':
    context => '/files/etc/resolv.conf',
    changes => [
      "set search/domain '${search}'"
    ],
  }
}

Then we add resolver to our classes in /etc/puppetlabs/code/environments/production/hieradata/hosts/client.yaml, so as to have resolver applied to our node, as shown here:

---
welcome: 'Welcome to our default node'
classes:
  - resolver

Now we run Puppet on the client; Augeas will change the resolv.conf file to have the search domain set to the default example.com:

[thomas@client ~]$ sudo puppet agent -t
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for client.example.com
Info: Applying configuration version '1442411609'
Notice: Augeas[set resolv.conf search](provider=augeas): 
--- /etc/resolv.conf 2015-09-16 09:53:15.727804673 -0400
+++ /etc/resolv.conf.augnew 2015-09-16 09:53:28.108995714 -0400
@@ -2,3 +2,4 @@
 nameserver 8.8.8.8
 nameserver 8.8.4.4
 domain example.com
+search example.com

Notice: /Stage[main]/Resolver/Augeas[set resolv.conf search]/returns: executed successfully
Notice: Applied catalog in 1.41 seconds

Now, to get Hiera to override the default parameter for the parameterized class resolver, we simply set the Hiera variable resolver::search in our /etc/puppetlabs/code/environments/production/hieradata/hosts/client.yaml file, as shown here:

---
welcome: 'Welcome to our default node'
classes:
  - resolver
resolver::search: 'devel.example.com'

Running puppet agent another time on node1 will change the search from example.com to devel.example.com, using the value from the Hiera hierarchy file, as you can see here:

[thomas@client ~]$ sudo puppet agent -t
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Caching catalog for client.example.com
Info: Applying configuration version '1442411732'
Notice: Augeas[set resolv.conf search](provider=augeas): 
--- /etc/resolv.conf	2015-09-16 09:53:28.155509013 -0400
+++ /etc/resolv.conf.augnew	2015-09-16 09:55:30.656393427 -0400
@@ -2,4 +2,4 @@
 nameserver 8.8.8.8
 nameserver 8.8.4.4
 domain example.com
-search example.com
+search devel.example.com

Notice: /Stage[main]/Resolver/Augeas[set resolv.conf search]/returns: executed successfully
Notice: Applied catalog in 0.94 seconds

By building up your catalog in this fashion, it's possible to override parameters of any class. At this point, our client machine has the virtual, resolver and base classes, but our site manifest (/etc/puppet/manifests/site.pp) only has a hiera_include line, as shown here:

node default {
  hiera_include('classes',base)
}

In the enterprise, this means that you can add new hosts without modifying your site manifest and that you can customize the classes and any parameters to those classes.

Note

Using hiera_include to specify the classes assigned to a node ensures that the node cannot assign itself to a different role. Some site.pp manifests will use a fact to determine the classes to be applied, this will allow anyone who can control facts on the node to change the classes on the node and potentially access configurations for different types of nodes.

Two other functions exist for using Hiera; they are hiera_array and hiera_hash. These functions do not stop at the first match found in Hiera and instead return either an array or hash of all the matches. This can also be used in powerful ways to build up definitions of variables. One good use of this is in setting the name servers a node will query. Using hiera_array instead of the hiera function, you can not only set nameservers based on the hostname of the node or some other facts, but also have the default nameservers from your common.yaml file applied to the node.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.94.153