Configuring Puppet Server (part 3)
Setting up Hiera on Puppet Server⌗
It’s been a while due to, well, life. As promised, this blog will conclude the Configuring Puppet Server series by setting up Hiera.
If you need to get caught up, please see Part 1 and Part 2
What is Hiera?⌗
Hiera is a key/value lookup tool for configuration data. There are 3 principal versions of Hiera used in modern Puppet:
- Hiera 3
- Hiera 4
- Hiera 5
If you’d like more information about the difference between the three versions, you can find it in the Hiera 5 Docs. For the purposes of our blog post, we’ll be using Hiera 5 as Hiera 3 will be depracated soon and Hiera 4 was a beta for Hiera 5.
Installing Hiera⌗
If using the Puppet Agent All-In-One Package provided by Puppet, Inc then Hiera 3 and Hiera 5 are both installed as part of the installation, no additional steps needed.
Configuring Hiera⌗
In Hiera 3, you had a single, global configuration file found at /etc/puppetlabs/puppet/hiera.yaml
In Hiera 5, there are now three potential configuration locations:
/etc/puppetlabs/puppet/hiera.yaml
– purely for backwards compatibility and migrating from Hiera 3 to Hiera 5+$ENVIRONMENT_PATH/hiera.yaml
– Environment Level Data – will override Module level data and defaults set in the code.$MODULE_ROOT/hiera.yaml
– Module Level Data – Primarily used to set sane defaults. Designed as a replacement forparams.pp
.
This tutorial only covers the initial setup of a Puppetserver and the Production Environment, so the Hiera 3 Global yaml and the Module data yaml will not be covered here.
Since the Evnironment Level Data is configured per environment and lives in the Environment directory, it will need to go into the puppet-control
repository if you are using r10k
. We will not be covering Module level data in this post. That will come in a later post dedicated to Hiera.
The first thing we need to do is configure the hiera.yaml
for our r10k
environment. The hiera.yaml
file simply exists in the root of your puppet-control
repo.
Create the hiera.yaml
file in the root of your puppet-control
repo that we’ve been using in these previous posts. It will look similar to this:
---
version: 5 # Required in Hiera 5
defaults: # Used for any hierarchy level that omits the below keys.
datadir: hieradata # The path, relative to the hiera.yaml"s directory, to use for lookups
data_hash: yaml_data # Use the YAML backend if no other backend is specified.
hierarchy:
- name: "Per-node data" # Human readable name
path: "nodes/%{trusted.certname}.yaml" # File path, relative to datadir. File extension is required!
- name: "Common Data"
path: "common.yaml"
The above is a simple hiera.yaml
configuration file. Note the comments in the code example for descriptions about each key.
The above config is telling Hiera the following facts about its lookup:
- Use Hiera version 5
- The default data directory is
<environment_root>/hieradata
- The default data backend is YAML
- There are 2 Hierarchies – Per-node data and Common data
- Per-node data is a hierarchy with a single path:
- Lookup data by node name in path –
<environment_root>/hieradata/nodes/<certname>.yaml
- Lookup data by node name in path –
- Common data is also a hierarchy with a single path:
- Lookup common data in path –
<environment_root>/hieradata/common.yaml
- Lookup common data in path –
- Lookup data in each hierarchy starting from top to bottom.
That’s it, Hiera is now configured. Granted this won’t be much use without hieradata.
Adding hieradata⌗
Now we need to add some data to hiera. We can add this directly to the puppet-control
repository, or create a separate repository to contain this data. For the sake of brevity, we will be adding the hieradata directly to the puppet-control
repository.
First thing we want to do is add a hieradata
directory to the root of the puppet-control
to match the datadir
value in the example above.
Next we need to create a nodes
directory in the hieradata
directory to match our “Per-node data” hierarchy path.
Ok, now before we can create any hieradata, we need to add some lookups to the code. So, open your site.pp
file in the puppet-control
repo and edit it to look like this:
node "puppetserver.local" {
class { "::puppetdb::master::config":
puppetdb_server => "puppetdb.local",
}
class { "::r10k":
sources => {
"r10k" => {
"remote" => lookup("r10k::remote"),
"basedir" => lookup("r10k::basedir", "/etc/puppetlabs/code/environments"),
},
},
}
class { "::r10k::webhook":
user => "root",
group => "root",
}
class { "::r10k::webhook::config":
use_mcollective => false,
public_key_path => "/etc/pki/tls/certs/puppetserver.local.public.pem",
private_key_path => "/etc/pki/tls/private/puppetserver.local.pem",
}
}
node "puppetdb.local" {
class { "::puppetdb":
ssl_listen_address => "puppetdb.local",
open_ssl_listen_port => true,
postgres_version => "9.6",
}
}
node default {}
We’ve replaced the r10k
remote and basedir attributes with the Puppet lookup()
function. This function simply looks up data based on the key name you pass it. So in this case, the code is telling puppet to do the following:
- Get the value of
remote
by looking up ther10k::remote
key in Hiera and fail if nothing is found. - Get the value of
basedir
by looking up ther10k::basedir
key in Hiera, but if nothing is found, set it to/etc/puppetlabs/code/environments
.
Of course, the lookup on remote
is going to fail because we don’t have any data in Hiera yet. So, let’s create that data.
create a new file in hieradata/nodes/
called puppetserver.local.yaml
and place the following content in there:
---
r10k::remote: "https://github.com/user/puppet-control"
Where the Github URL is the puppet-control
repo created for the previous posts.
Now run puppet agent -t
on the “puppetserver.local” VM. You should see a puppet run, but there shouldn’t be any changes as we didn’t actually change any data within the compiled puppet catalog.
Let’s do that now for fun. Open the site.pp
file back up one last time and add the following code to it in the puppetdb.local
node block:
...
node "puppetdb.local" {
class { "::puppetdb":
ssl_listen_address => "puppetdb.local",
open_ssl_listen_port => true,
postgres_version => "9.6",
}
file { "/tmp/test":
ensure => file,
user => lookup("file::user"),
group => lookup("file::group"),
mode => "0644",
content => lookup("file::content"),
}
}
...
Now create the common.yaml
file inside the hieradata/
directory with the following content:
---
file::user: root
file::group: root
file::content: "Hello world!"
Ok, now run puppet agent -t
on the “puppetdb.local” VM. The newly compiled catalog should create a new file at called test
in the /tmp
directory on the system that is owned by root
and grouped into root
. The file should contain Hello world!
as its only content.
That’s it. That’s all there is to Hiera.
Conclusion⌗
Hiera is an incredibly powerful tool for abstracting configuration and infrastructure data away from your Puppet code. This is incredibly useful when creating Modules, Roles, and/or Profiles that are designed to be reusable and dynamic.
Hiera comes with four built-in backends – YAML, JSON, HOCON, and EYAML – but you can extend that with your own custom backends written in Puppet or Ruby if necessary.
Hiera and the Lookup function have a wide array of options and uses. See the links below to learn more and feel free to reach out via E-Mail, Slack, or IRC with any questions you may have.
Resources⌗
Contact⌗
- Email: david.hollinger@moduletux.com
- Twitter: @moduletux
- IRC: dhollinger on Freenode
- Slack: dhollinger in the Puppet Community