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.
Hi there,
It’s an excellent article, could you publish your nagios::server class too?
Hi Thomas,
I did not have a nagios::server class. The nagios::install takes care of installing it, if you have packages. You may need to fine tune it, depending on how you’re installing it.
I am getting this error as well:
Error: Could not retrieve catalog from remote server: Error 400 on SERVER: Invalid relationship: Service[nagios] { require => Class[Nagios::Server] }, because Class[Nagios::Server] doesn’t seem to be in the catalog
I do not see a class nagios::server defined anywhere.
-Dave
Hi Dave,
Apologies, I have corrected the code, it should require the install class and not server class.
Hello,
Very good article 😉 . I’ve one question, the template create for the nodes based on export.pp include standar checks (cpu, ping, ssh, etc) but ¿is possible add other checks for a specific node (example nfs) but this checks no apply all nodes? .
Regards.
Hi Miguel,
Yes, absolutely. You can add checks for certain hostnames by using a case statement. Or use if conditions based on facts.
If we are using Hiera to store the facts..is the puppetdb necessary for this?
I’m also curious if puppetdb is required.
Exported resources are stored in PuppetDB so naturally you need it.
Hi,
Nice writeup, I’m not sure if its the same in Nagios 4 but in 3 I had to make sure that nrpe was allowed to be contacted by the nagios server. I did this by adding the following into the nrpe config file
file_line { “allowed_hosts”:
line => “allowed_hosts = 127.0.0.1,192.168.1.29”,
path => “/etc/nagios/nrpe.cfg”,
match => “allowed_hosts”,
ensure => present,
notify => Service[“nrpe”],
}
where 192.168.1.29 is my nagios server.
Can I ask how would I work if the client is not Linux and rather a hardware device like a vpn Router? In that case we can’t use NRPE but snmp for it.
Hi Tom,
I had a query with regards to using hostgroups. You used hostgroups in @@nagios_host but that doesn’t create a hostgroups.cfg. It gives me this error.
Error: Could not find any hostgroup matching ‘Mgmt Servers’ (config file ‘/usr/local/nagios/etc/objects/dev-local_hosts.cfg’, starting on line 66)
My target.pp
============
class nagios::target {
@@nagios_host { $fqdn:
ensure => present,
target => “/usr/local/nagios/etc/objects/${hostname}.cfg”,
alias => $hostname,
address => $ipaddress,
hostgroups => “Mgmt Servers”,
use => “linux-server”,
}
monitor.pp
===========
Nagios_host <> {
target => “/usr/local/nagios/etc/objects/dev-local_hosts.cfg”,
}
Nagios_service <> {
target => “/usr/local/nagios/etc/objects/dev-local_service.cfg”,
}
Can you tell me what am i missing??
Regards,
Farooq Ahmed
My example snippet is assuming you already have a hostgroup called “Mgmt Servers”, you can change it to whatever yours is called or create one in Puppet with the nagios_hostgroup resource: https://docs.puppet.com/puppet/latest/type.html#nagioshostgroup
It’s remarkable for me to have a web page, which is useful in support of my knowledge.
thanks admin
Ιt’s an remarkable piece of wriuting desіgned for
all the web people; they will take advantage from it
I am sure. https://lineslillestoreverden.blogspot.com/