- Overview
- Module Description - What the module does and why it is useful
- Setup - The basics of getting started with icinga2
- Usage - Configuration options and additional functionality
- How Configuration is parsed
- Reference
- Release Notes
Icinga 2 is a widely used open source monitoring software. This Puppet module helps with installing and managing configuration of Icinga 2 on multiple operating systems.
This module installs and configures Icinga 2 on your Linux or Windows hosts.
By default it uses packages provided by your distribution's repository or Chocolatey on Windows.
The module can also be configured to use packages.icinga.com as the primary repository, which enables you to install Icinga 2 versions that are newer than the ones provided by your distribution's vendor. All features and objects available in Icinga 2 can be enabled and configured with this module.
- Installation of packages
- Configuration of features
- Configuration of objects (also apply rules)
- Service
- MySQL / PostgreSQL Database Schema Import
- Repository Management
- Certification Authority
This module supports:
- [puppet] >= 4.10 < 7.0.0
And depends on:
- puppetlabs/stdlib >= 4.16.0 < 7.0.0
- If Puppet 6 is used a stdlib 5.1 or higher is required, see voxpupuli#505
- puppetlabs/concat >= 2.1.0 < 7.0.0
Depending on your setup following modules may also be required:
- puppetlabs/apt >= 6.0.0
- puppetlabs/chocolatey >= 3.1.0
- puppet/zypprepo >= 2.2.1
- [puppetlabs/yumrepo_core] >= 1.0.0
- If Puppet 6 is used
This module has been tested on:
- Ruby >= 1.9
- Debian 9, 10
- Ubuntu 16.04, 18.04
- CentOS/RHEL 6, 7, 8
- Fedora 31
- FreeBSD 10, 11
- SLES 12
- Windows Server 2012 R2, 2016
Other operating systems or versions may work but have not been tested.
The default class icinga2
installs and configures a basic installation of Icinga 2. The features checker
, mainlog
and notification
are enabled by default.
By default, your distribution's packages are used to install Icinga 2. On Windows systems we use the Chocolatey package manager.
Use the manage_repo
parameter to configure the official packages.icinga.com repositories.
class { '::icinga2':
manage_repo => true,
}
Notice: Since Icinga v2.11.0 on RedHat the EPEL-Repository is required to install the Boost libraries. EPEL is NOT managed by this module so you have to do this on your own in front of icinga2 class, e.g. as yum_repo
or if you've an internet connection as a simple package resource like:
package { 'epel-release': }
class { '::icinga2':
manage_repo => true,
}
Notice: The same holds on Debian with the backports repository.
include ::apt, ::apt::backports
class { '::icinga2':
manage_repo => true,
}
Info: If you are using the Icinga Web 2 Puppet module on the same server, make sure to disable the repository management for one of the modules!
Since version 2.0.0 you're able via hiera to overload which repository will be used for installation, e.g. for icinga on YUM based operating systems:
---
icinga2::repo:
baseurl: 'http://myhost.example.org/epel/%{facts.os.release.major}/release/'
proxy: http://proxy.example.org:3128
Notice: If you wanna setup Icinga on Debian 8 the required backports repository (Icinga 2 v2.11.0 or higher) changed its location! You have to use hiera to configure the location used by the class apt::backports or disable manage_repo
by setting to false
to manage the required repos by yourself.
---
apt::backports::location: http://archive.debian.org/debian
You can also change or set every other parameter of the underlying resources, supported for operating system families:
- RedHat, resource type: yumrepo
- Debian, define resource: apt::source
- SuSE, resource type: zypprepo
- a workaround is implemented to use a parameter proxy also to download the gpg key thru a proxy, see voxpupuli#397.
If you want to manage the version of Icinga 2, you have to disable the package management of this module and handle packages in your own Puppet code. The attribute manage_repo is disabled by default and you have to manage a repository within icinga in front of the package resource. You can combine this one with the section before about repositories.
include ::icinga2::repo
package { 'icinga2':
ensure => latest,
notify => Class['icinga2'],
}
class { '::icinga2':
manage_package => false,
}
Note: Be careful with this option: Setting manage_package
to false means that this module will not install any package at
all, including IDO packages!
Icinga 2 can run in three different roles:
- in a master zone which is on top of the hierarchy
- in a satellite zone which is a child of a satellite or master zone
- a standalone client node/zone which works as an agent connected to master and/or satellite zones
To learn more about Icinga 2 Clustering, follow the official docs on distributed monitoring. The following examples show how these roles can be configured using this Puppet module.
A Master zone has no parent and is usually also the place where you enable the IDO and notification features. A master sends configurations over the Icinga 2 protocol to satellites and/or clients.
More detailed examples can be found in the [examples] directory.
This example creates the configuration for a master that has one satellite connected. A global zone is created for templates, and all features of a typical master are enabled.
class { '::icinga2':
confd => false,
constants => {
'ZoneName' => 'master',
'TicketSalt' => '5a3d695b8aef8f18452fc494593056a4',
},
}
class { '::icinga2::feature::api':
pki => 'none'
accept_commands => true,
# when having multiple masters, you have to enable:
accept_config => true,
endpoints => {
'master.example.org' => {},
'satellite.example.org' => {
'host' => '172.16.2.11'
},
},
zones => {
'master' => {
'endpoints' => ['master.example.org'],
},
'dmz' => {
'endpoints' => ['satellite.example.org'],
'parent' => 'master',
},
}
}
# to enable a CA on this instance you have to declare. Only one instance is allowed to be a CA:
include ::icinga2::pki::ca
icinga2::object::zone { 'global-templates':
global => true,
}
A satellite has a parent zone and one or multiple child zones. Satellites are usually created to distribute the monitoring load or to reach delimited zones in the network. A satellite either executes checks itself or delegates them to a client.
The satellite has fewer features enabled, but executes checks similar to a master. It connects to a master zone, and to a satellite or client below in the hierarchy. As parent acts either the master zone, or another satellite zone.
class { '::icinga2':
confd => false,
# setting dedicated feature list to disable notification
features => ['checker','mainlog'],
constants => {
'ZoneName' => 'dmz',
},
}
class { '::icinga2::feature::api':
accept_config => true,
accept_commands => true,
ca_host => '172.16.1.11',
ticket_salt => '5a3d695b8aef8f18452fc494593056a4',
# to increase your security set fingerprint to validate the certificate of ca_host
# fingerprint => 'D8:98:82:1B:14:8A:6A:89:4B:7A:40:32:50:68:01:99:3D:96:72:72',
endpoints => {
'satellite.example.org' => {},
'master.example.org' => {
'host' => '172.16.1.11',
},
},
zones => {
'master' => {
'endpoints' => ['master.example.org'],
},
'dmz' => {
'endpoints' => ['satellite.example.org'],
'parent' => 'master',
},
}
}
icinga2::object::zone { 'global-templates':
global => true,
}
Icinga 2 runs as a client usually on each of your servers. It receives config or commands from a satellite or master zones and runs the checks that have to be executed locally.
The client is connected to the satellite, which is the direct parent zone.
class { '::icinga2':
confd => false,
features => ['mainlog'],
}
class { '::icinga2::feature::api':
accept_config => true,
accept_commands => true,
ticket_salt => '5a3d695b8aef8f18452fc494593056a4',
# to increase your security set fingerprint to validate the certificate of ca_host
# fingerprint => 'D8:98:82:1B:14:8A:6A:89:4B:7A:40:32:50:68:01:99:3D:96:72:72',
endpoints => {
'NodeName' => {},
'satellite.example.org' => {
'host' => '172.16.2.11',
},
},
zones => {
'ZoneName' => {
'endpoints' => ['NodeName'],
'parent' => 'dmz',
},
'dmz' => {
'endpoints' => ['satellite.example.org'],
},
}
}
icinga2::object::zone { 'global-templates':
global => true,
}
The parameter fingerprint
is optional and new since v2.1.0. It's used to validate the certificate of the CA host.
A fingerprint can be got by openssl x509 -noout -fingerprint -sha1 -inform pem -in master.crt
on the master host.
With this module you can create almost every object that Icinga 2 knows about. When creating objects some parameters are required. This module sets the same requirements as Icinga 2 does. When creating an object you must set a target for the configuration.
Here are some examples for some object types:
icinga2::object::host { 'srv-web1.fqdn.com':
display_name => 'srv-web1.fqdn.com',
address => '127.0.0.1',
address6 => '::1',
check_command => 'hostalive',
target => '/etc/icinga2/conf.d/srv-web1.fqdn.com.conf',
}
icinga2::object::service { 'uptime':
host_name => 'srv-web1.fqdn.com',
display_name => 'Uptime',
check_command => 'check_uptime',
check_interval => '600m',
groups => ['uptime', 'linux'],
target => '/etc/icinga2/conf.d/uptime.conf',
}
icinga2::object::hostgroup { 'monitoring-hosts':
display_name => 'Linux Servers',
groups => [ 'linux-servers' ],
target => '/etc/icinga2/conf.d/groups2.conf',
assign => [ 'host.vars.os == linux' ],
}
The following example shows how icinga2 objects can be read from a hiera datastore. See also examples/objects_from_hiera.pp.
class { 'icinga2':
manage_repo => true,
}
$defaults = lookup('monitoring::defaults', undef, undef, {})
lookup('monitoring::objects').each |String $object_type, Hash $content| {
$content.each |String $object_name, Hash $object_config| {
ensure_resource(
$object_type,
$object_name,
deep_merge($defaults[$object_type], $object_config))
}
}
The datastore could be like:
---
monitoring::objects:
'icinga2::object::host':
centos7.localdomain:
address: 127.0.0.1
vars:
os: Linux
'icinga2::object::service':
ping4:
check_command: ping4
apply: true
assign:
- host.address
ssh:
check_command: ssh
apply: true
assign:
- host.address && host.vars.os == Linux
monitoring::defaults:
'icinga2::object::host':
import:
- generic-host
target: /etc/icinga2/conf.d/hosts.conf
'icinga2::object::service':
import:
- generic-service
target: /etc/icinga2/conf.d/services.conf
Some objects can be applied to other objects. To create a simple apply rule you
must set the apply
parameter to true
. If this parameter is set to a string,
this string will be used to build an apply for
loop. A service object always
targets a host object. All other objects need to explicitly set an
apply_target
Apply a SSH service to all Linux hosts:
icinga2::object::service { 'SSH':
target => '/etc/icinga2/conf.d/test.conf',
apply => true,
assign => [ 'host.vars.os == Linux' ],
ignore => [ 'host.vars.os == Windows' ],
display_name => 'Test Service',
check_command => 'ssh',
}
Apply notifications to services:
icinga2::object::notification { 'testnotification':
target => '/etc/icinga2/conf.d/test.conf',
apply => true,
apply_target => 'Service',
assign => [ 'host.vars.os == Linux' ],
ignore => [ 'host.vars.os == Windows' ],
user_groups => ['icingaadmins']
}
Assign all Linux hosts to a hostgroup:
icinga2::object::hostgroup { 'monitoring-hosts':
display_name => 'Linux Servers',
groups => [ 'linux-servers' ],
target => '/etc/icinga2/conf.d/groups2.conf',
assign => [ 'host.vars.os == linux' ],
}
A loop to create HTTP services for all vHosts of a host object:
icinga2::object::service { 'HTTP':
target => '/etc/icinga2/conf.d/http.conf',
apply => 'http_vhost => config in host.vars_http_vhost',
assign => [ 'host.vars.os == Linux' ],
display_name => 'HTTP Service',
check_command => 'http',
}
Sometimes it's necessary to cover very special configurations, that you cannot handle with this module. In this case you can use the icinga2::config::file
tag on your file resource. The module collects all file resource types with this tag and triggers a reload of Icinga 2 on a file change.
include ::icinga2
file { '/etc/icinga2/conf.d/for-loop.conf':
ensure => file,
source => '...',
tag => 'icinga2::config::file',
}
To generate a valid Icinga 2 configuration all object attributes are parsed. This simple parsing algorithm takes a decision for each attribute, whether part of the string is to be quoted or not, and how an array or dictionary is to be formatted.
Parsing of a single attribute can be disabled by tagging it with -: at the front of the string.
attr => '-:"unparsed string with quotes"'
An array, a hash or a string can be assigned to an object attribute. True and false are also valid values.
Hashes and arrays are created recursively, and all parts – such as single items of an array, keys and its values are parsed separately as strings.
Strings are parsed in chunks, by splitting the original string into separate substrings at specific keywords (operators)
such as +
, -
, in
, &&
, ||
, etc.
NOTICE: This splitting only works for keywords that are surrounded by whitespace, e.g.:
attr => 'string1 + string2 - string3'
The algorithm will loop over the parameter and start by splitting it into 'string1' and 'string2 - string3'. 'string1' will be passed to the sub function 'value_types' and then the algorithm will continue parsing the rest of the string ('string2 - string3'), splitting it, passing it to value_types, etc.
Brackets are parsed for expressions:
attr => '3 * (value1 - value2) / 2'
The parser also detects function calls and will parse all parameters separately.
attr => 'function(param1, param2, ...)'
True and false can be used as either booleans or strings.
attrs => true or attr => 'true'
In Icinga you can write your own lambda functions with {{ ... }}. For Puppet use:
attrs => '{{ ... }}'
The parser analyzes which parts of the string have to be quoted and which do not.
As a general rule, all fragments are quoted except for the following:
- Boolean:
true
,false
- Numbers:
3
or2.5
- Time Intervals:
3m
or2.5h
(s = seconds, m = minutes, h = hours, d = days) - Functions:
{{ ... }}
or function()
{}
- All constants, which are declared in the constants parameter in main class
icinga2
NodeName
- Names of attributes that belong to the same type of object:
- e.g.
name
andcheck_command
for a host object
- e.g.
- All attributes or variables (custom attributes) from the host, service or user contexts:
host.name
,service.check_command
,user.groups
, ...
Assignment with += and -=:
Now it's possible to build an Icinga DSL code snippet like
vars += config
simply use a string with the prefix '+ ', e.g.
vars => '+ config',
The blank between + and the proper string 'config' is imported for the parser because numbers
attr => '+ -14',
are also possible now. For numbers -= can be built, too:
attr => '- -14',
Arrays can also be marked to merge with '+' or reduce by '-' as the first item of the array:
attr => [ '+', item1, item2, ... ]
Result: attr += [ item1, item2, ... ]
attr => [ '-', item1, item2, ... ]
Result: attr -= [ item1, item2, ... ]
That all works for attributes and custom attributes!
Finally dictionaries can be merged when a key '+' is set:
attr => {
'+' => true,
'key1' => 'val1',
}
Result:
attr += {
"key1" = "val1"
}
If 'attr' is a custom attribute this just works since level 3 of the dictionary:
vars => {
'level1' => {
'level2' => {
'level3' => {
'+' => true,
...
},
},
},
},
Parsed to:
vars.level1["level2"] += level3
Now it's also possible to add multiple custom attributes:
vars => [
{
'a' => '1',
'b' => '2',
},
'config',
{
'c' => {
'd' => {
'+' => true,
'e' => '5',
},
},
},
],
And you'll get:
vars.a = "1"
vars.b = "2"
vars += config
vars.c["d"] += {
"e" = "5"
}
Note: Using an Array always means merge '+=' all items to vars.
It's not currently possible to use dictionaries in a string WITH nested array or hash, like
attr1 => 'hash1 + { item1 => value1, item2 => [ value1, value2 ], ... ]'
attr2 => 'hash2 + { item1 => value1, item2 => { ... },... }'
See REFERENCE.md
When releasing new versions we refer to SemVer 1.0.0 for version numbers. All steps required when creating a new release are described in RELEASE.md
See also CHANGELOG.md