One of the coolest things Puppet can do is create exported resources. In plain words it means that you can include a manifest on all your nodes which then gets customised and applied for each node thanks to the node facts.
A popular usage of exported resources is automating Nagios monitoring. Instead of manually creating a Nagios configuration with the basic checks such as load, disk usage etc… then duplicating it for each server and changing the hostname, an exported resource can do it all for you by including a single manifest.
PuppetDB configuration
Exported resources requires storing facts for the Puppet nodes so we need PuppetDB installed on the PuppetMaster.
1 2 |
sudo puppet resource package puppetdb ensure=latest sudo puppet resource package puppetdb-terminus ensure=latest |
Create /etc/puppet/puppetdb.conf
1 2 3 4 |
[main] server = puppet.bluemalkin.net port = 8081 soft_write_failure = false |
Add to /etc/puppet/puppet.conf under [main]
1 2 3 |
[main] storeconfigs = true storeconfigs_backend = puppetdb |
Create /etc/puppet/routes.yaml
1 2 3 4 5 |
--- master: facts: terminus: puppetdb cache: yaml |
Start PuppetDB and restart the PuppetMaster:
1 2 |
sudo service puppetdb start sudo service puppetmaster restart |
Nagios Server Configuration
Create a Nagios module with the following manifests:
nagios/manifests/init.pp
1 2 3 4 5 |
class nagios { include nagios::install include nagios::service include nagios::import } |
nagios/manifests/install.pp
1 2 3 4 5 |
class nagios::install { package { [ 'nagios4', 'nagios-plugins', 'nagios-nrpe-plugin' ]: ensure => present, } } |
Note that at the time of writing, Nagios 4 isn’t available as a package for Ubuntu 12.04 LTS so we’re assuming you built your own one which installs it under /etc/nagios4
nagios/manifests/service.pp
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class nagios::service { exec { 'fix-permissions': command => "find /etc/nagios4/conf.d -type f -name '*cfg' | xargs chmod +r", refreshonly => true, } -> service { 'nagios': ensure => running, enable => true, require => Class[ 'nagios::install' ], } } |
There is a bug in Puppet when the exported resources are created, they do not have the correct permissions to allow the nagios user on the server to read them so declare a fix-permissions exec resource.
nagios/manifests/import.pp
1 2 3 4 5 6 7 8 9 10 11 12 |
class nagios::import { Nagios_host <<||>> { require => Class[ 'nagios::install' ], notify => Class[ 'nagios::service' ] } Nagios_service <<||>> { require => Class[ 'nagios::install' ], notify => Class[ 'nagios::service' ] } } |
The exported resource operator <<||>> (not to be confused with the spaceship <||> operator) is the resource which will realize all @@ virtual exported resources. How it works is described further down.
Nagios NRPE nodes
For all nodes which you want to monitor with nagios, we need the Nagios NRPE server installed
nagios/manifests/nrpe.pp
1 2 3 4 5 6 7 8 9 10 11 12 |
class nagios::nrpe { package { [ 'nagios-nrpe-server', 'nagios-plugins' ]: ensure => present, } service { 'nagios-nrpe-server': ensure => running, enable => true, require => Package[ 'nagios-nrpe-server', 'nagios-plugins' ] ], } } |
Then the export manifest where the @@nagios virtual resources are declared
nagios/manifests/export.pp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
class nagios::export { @@nagios_host { $::hostname : ensure => present, address => $::ipaddress, use => 'generic-host', check_command => 'check-host-alive', hostgroups => 'all-servers', target => "/etc/nagios4/conf.d/${::hostname}.cfg", } @@nagios_service { "${::hostname}_check-load": ensure => present, use => 'generic-service', host_name => $::hostname, service_description => 'Current Load', check_command => 'check_nrpe!check_load', target => "/etc/nagios4/conf.d/${::hostname}.cfg", } @@nagios_service { "${::hostname}_check-disk": ensure => present, use => 'generic-service', host_name => $::hostname, service_description => 'hda1 disk usage', check_command => 'check_nrpe!check_hda1', target => "/etc/nagios4/conf.d/${::hostname}.cfg", } } |
To include Nagios on all nodes to monitor, just add to the default node on manifests/nodes.pp
1 2 3 4 |
node default { include nagios::nrpe include nagios::export } |
How it works
When you declare an exported virtual resource on the node, after the puppet agent run, the exported configurations are stored into PuppetDB. Then when you run the puppet agent on the Nagios server, it collects all the nodes exported resources from PuppetDB and subsequently creates the Nagios .cfg files. Beware that if you have a lot of nodes that use exported resources, it can create a long catalogue compilation time, so consider extending the run interval of the puppet agent.
Therefore all nodes must trigger a puppet run before the server can import the configurations.
Note that if you remove nagios::export class from a node, it will not remove the exported configurations in PuppetDB, the resources will still be created on export. You need to keep the virtual exported resources and set ensure to absent. Or if you’re completely removing the node, on the PuppetMaster you can deactivate it with
1 |
puppet node deactivate <node-fqdn> |
Exported resources can have many other uses such as managing sshkey know_hosts resources or for dynamically adding/removing load balancer members to Apache for example.