icinga2/docs/icinga2-tutorial.md

28 KiB
Raw Blame History

Preface

This tutorial is a step-by-step introduction to installing Icinga 2 and setting up your first couple of service checks. It assumes some familiarity with Icinga 1.x.

Installation

In order to get started with Icinga 2 we will have to install it. The preferred way of doing this is to use the official Debian or RPM packages depending on which Linux distribution you are running.


Distribution Package URL

Debian [http://icingabuild.dus.dg-i.net:808 0/job/icinga2/](http://icingabuild.d us.dg-i.net:8080/job/icinga2/)

RHEL TBD


In case youre running a distribution for which Icinga 2 packages are not yet available you will have to check out the Icinga 2 Git repository from git://git.icinga.org/icinga2 and read the INSTALL file.

By default Icinga 2 uses the following files and directories:


Path Description

/etc/icinga2 Contains Icinga 2 configuration files.

/etc/init.d/icinga2 The Icinga 2 init script.

/usr/share/doc/icinga2 Documentation files that come with Icinga 2.

/usr/share/icinga2/itl The Icinga Template Library.

/var/run/icinga2 Command pipe and PID file.

/var/cache/icinga2 Performance data files and status.dat/objects.cache.

/var/lib/icinga2 The Icinga 2 state file.


Our First Service Check

The Icinga 2 package comes with a number of example configuration files. However, in order to explain some of the basics were going write our own configuration file from scratch.

Start by creating the file /etc/icinga2/icinga2.conf with the following content:

include <itl/itl.conf>
include <itl/standalone.conf>

object IcingaApplication "my-icinga" {
        macros["plugindir"] = "/usr/lib/nagios/plugins"
}

The configuration snippet includes the itl/itl.conf and itl/standalone.conf files which are distributed as part of Icinga 2. We will discuss the Icinga Template Library (ITL) in more detail later on.

The itl/standalone.conf configuration file takes care of configuring Icinga 2 for single-instance (i.e. non-clustered) mode.

Our configuration file also creates an object of type IcingaApplication with the name my-icinga. The IcingaApplication type can be used to define global macros and some other global settings.

For now were only defining the global macro plugindir which were going to use later on when referring to the path which contains our check plugins. Depending on where youve installed your check plugins you may need to update this path in your configuration file.

You can verify that your configuration file works by starting Icinga 2:

$ /usr/bin/icinga2 -c /etc/icinga2/icinga2.conf
[2013/04/23 13:36:20 +0200] <Main Thread> information/icinga-app: Icinga application loader (version: 0.0.1, git branch master, commit 0fcbfdb2)
[2013/04/23 13:36:20 +0200] <Main Thread> information/base: Adding library search dir: /usr/lib/icinga2
[2013/04/23 13:36:20 +0200] <Main Thread> information/base: Loading library 'libicinga.la'
[2013/04/23 13:36:20 +0200] <Main Thread> information/config: Adding include search dir: /usr/share/icinga2
[2013/04/23 13:36:20 +0200] <Main Thread> information/config: Compiling config file: /etc/icinga2/icinga2.conf
[2013/04/23 13:36:20 +0200] <Main Thread> information/config: Linking config items...
[2013/04/23 13:36:20 +0200] <Main Thread> information/config: Validating config items...
[2013/04/23 13:36:20 +0200] <Main Thread> information/config: Activating config items in compilation unit 'b2d21c28-a2e8-4fcb-ba00-45646bc1afb9'
[2013/04/23 13:36:20 +0200] <Main Thread> information/base: Restoring program state from file '/var/lib/icinga2/icinga2.state'
[2013/04/23 13:36:20 +0200] <Main Thread> information/base: Restored 0 objects

In case there are any configuration errors Icinga 2 should print error messages containing details about what went wrong.

You can stop Icinga 2 with Control-C:

^C
[2013/04/23 13:39:39 +0200] <TP 0x7f2e9070f500 Worker #0> information/base: Shutting down Icinga...
[2013/04/23 13:39:39 +0200] <TP 0x7f2e9070f500 Worker #0> information/base: Dumping program state to file '/var/lib/icinga2/icinga2.state'
[2013/04/23 13:39:39 +0200] <Main Thread> information/icinga: Icinga has shut down.
$

Icinga 2 automatically saves its current state every couple of minutes and when its being shut down.

So far our Icinga 2 setup doesnt do much. Lets change that by setting up a service check for localhost. Modify your icinga2.conf configuration file by adding the following lines:

object CheckCommand "my-ping" inherits "plugin-check-command" {
        command = [
                "$plugindir$/check_ping",
                "-H", "$address$",
                "-w", "10,5%",
                "-c", "25,10%"
        ]
}

template Service "my-ping" inherits "plugin-service" {
        check_command = "my-ping"
}

object Host "localhost" {
        display_name = "Home, sweet home!",

        services["ping"] = {
                templates = [ "my-ping" ]
        },

        macros = {
                address = "127.0.0.1"
        },

        check_interval = 10s,

        hostcheck = "ping"
}

Were defining a command object called "my-ping" which inherits from the plugin-check-command template. The plugin-check-command template is provided as part of the Icinga Template Library and describes how checks are performed. In the case of plugin-based services this means that the command specified by the command property is executed.

The command property is an array or command-line arguments for the check plugin. Alternatively you can specify the check command as a string.

The check command can make use of macros. Unlike in Icinga 1.x we have free-form macros which means that users can choose arbitrary names for their macros.

By convention the following macros are usually used:


Macro Description plugindir The path of your check plugins. address The IPv4 address of the host. address6 The IPv6 address of the host.


Note that the my-ping command object does not define a value for the address macro. This is perfectly fine as long as that macro is defined somewhere else (e.g. in the host).

Were also defining a service template called my-ping which uses the command object we just created.

Next were defining a Host object called localhost. Were setting an optional display_name which is used by the Icinga Classic UI when showing that host in the host overview.

The services dictionary defines which services belong to a host. Using the [] indexing operator we can manipulate individual items in this dictionary. In this case were creating a new service called ping.

The templates array inside the service definition lists all the templates we want to use for this particular service. For now were just listing our my-ping template.

Remember how we used the address macro in the command setting earlier? Now were defining a value for this macro which is used for all services and their commands which belong to the localhost Host object.

Were also setting the check_interval for all services belonging to this host to 10 seconds.

Note

When you dont specify an explicit time unit Icinga 2 automatically assumes that you meant seconds.

And finally were specifying which of the services weve created before is used to define the hosts state. Note that unlike in Icinga 1.x this just "clones" the services state and does not cause any additional checks to be performed.

Setting up the Icinga 1.x Classic UI

Icinga 2 can write status.dat and objects.cache files in the format that is supported by the Icinga 1.x Classic UI. External commands (a.k.a. the "command pipe") are also supported. If you require the icinga.log for history views and/or reporting in Classic UI, this can be added seperately to the CompatComponent object definition by adding a CompatLog object.

In order to enable this feature you will need to load the library compat by adding the following lines to your configuration file:

library "compat"

object CompatComponent "compat" { }
object CompatLog "my-log" { }

After restarting Icinga 2 you should be able to find the status.dat and objects.cache files in /var/cache/icinga2. The log files can be found in /var/log/icinga2/compat. The command pipe can be found in /var/run/icinga2.

You can install the Icinga 1.x Classic UI in standalone mode using the following commands:

$ wget http://downloads.sourceforge.net/project/icinga/icinga/1.9.0/icinga-1.9.0.tar.gz
$ tar xzf icinga-1.9.0.tar.gz ; cd icinga-1.9.0
$ ./configure --enable-classicui-standalone --prefix=/usr/local/icinga2-classicui
$ make classicui-standalone
$ sudo make install classicui-standalone install-webconf-auth
$ sudo service apache2 restart

Note

A detailed guide on installing Icinga 1.x Classic UI Standalone can be found on the Icinga Wiki here: https://wiki.icinga.org/display/howtos/Setting+up+Icinga+Classic+UI+Standalone

After installing the Classic UI you will need to update the following settings in your cgi.cfg configuration file at the bottom (section "STANDALONE (ICINGA 2) OPTIONS"):


Configuration Setting Value object_cache_file /var/cache/icinga2/objects.cache status_file /var/cache/icinga2/status.dat resource_file - command_file /var/run/icinga2/icinga2.cmd check_external_commands 1 interval_length 60 status_update_interval 10 log_file /var/log/icinga2/compat/icinga.log log_rotation_method h log_archive_path /var/log/icinga2/compat/archives date_format us


Depending on how you installed Icinga 2 some of those paths and options might be different.

Note

You need to grant permissions for the apache user manually after starting Icinga 2 for now.

# chmod o+rwx /var/run/icinga2/{icinga2.cmd,livestatus}

Verify that your Icinga 1.x Classic UI works by browsing to your Classic UI installation URL e.g. http://localhost/icinga

Some More Templates

Now that weve got our basic monitoring setup as well as the Icinga 1.x Classic UI to work we can define a second host. Add the following lines to your configuration file:

object Host "icinga.org" {
        display_name = "Icinga Website",

        services["ping"] = {
                templates = [ "my-ping" ]
        },

        macros = {
                address = "www.icinga.org"
        },

        check_interval = 10s,

        hostcheck = "ping"
}

Restart your Icinga 2 instance and check the Classic UI for your new services state. Unless you have a low-latency network connection you will note that the services state is CRITICAL. This is because in the my-ping command object we have hard-coded the timeout as 25 milliseconds.

Ideally wed be able to specify different timeouts for our new service. Using macros we can easily do this.

Note

If youve used Icinga 1.x before youre probably familiar with doing this by passing ARGx macros to your check commands.

Start by replacing your my-ping command object with this:

object CheckCommand "my-ping" inherits "plugin-check-command" {
        command = [
                "$plugindir$/check_ping",
                "-H", "$address$",
                "-w", "$wrta$,$wpl$%",
                "-c", "$crta$,$cpl$%"
        ],

        macros = {
                wrta = 10,
                wpl = 5,

                crta = 25,
                cpl = 10
        }
}

We have replaced our hard-coded timeout values with macros and were providing default values for these same macros right in the template definition. The object inherits the basic check command attributes from the ITL provided template plugin-check-command.

In order to oderride some of these macros for a specific host we need to update our icinga.org host definition like this:

object Host "icinga.org" {
        display_name = "Icinga Website",

        services["ping"] = {
                templates = [ "my-ping" ],

                macros += {
                        wrta = 100,
                        crta = 250
                }
        },

        macros = {
                address = "www.icinga.org"
        },

        check_interval = 10s,

        hostcheck = "ping"
}

The += operator allows us to selectively add new key-value pairs to an existing dictionary. If we were to use the = operator instead we would have to provide values for all the macros that are used in the my-ping template overriding all values there.

Icinga Template Library

The Icinga Template Library is a collection of configuration templates for commonly used services. By default it is installed in /usr/share/icinga2/itl and you can include it in your configuration files using the include directive:

include <itl/itl.conf>

Note

Ordinarily youd use double-quotes for the include path. This way only paths relative to the current configuration file are considered. The angle brackets tell Icinga 2 to search its list of global include directories.

One of the templates in the ITL is the ping4 service template which is quite similar to our example objects:

object CheckCommand "ping4" inherits "plugin-check-command" {
        command = [
                "$plugindir$/check_ping",
                "-4",
                "-H", "$address$",
                "-w", "$wrta$,$wpl$%",
                "-c", "$crta$,$cpl$%",
                "-p", "$packets$",
                "-t", "$timeout$"
        ],

        macros = {
                wrta = 100,
                wpl = 5,

                crta = 200,
                cpl = 15,

                packets = 5,
                timeout = 0
        }
}

template Service "ping4" {
        check_command = "ping4"
}

Lets simplify our configuration file by removing our custom my-ping template and updating our service definitions to use the ping4 template instead.

Include Files

So far weve been using just one configuration file. However, once youve created a few more host objects and service templates this can get rather confusing.

Icinga 2 lets you include other files from your configuration file. We can use this feature to make our configuration a bit more modular and easier to understand.

Lets start by moving our two Host objects to a separate configuration file: hosts.conf

We will also need to tell Icinga 2 that it should include our newly created configuration file when parsing the main configuration file. This can be done by adding the include directive to our icinga2.conf file:

include "hosts.conf"

Depending on the number of hosts you have it might be useful to split your configuration files based on other criteria (e.g. device type, location, etc.).

You can use wildcards in the include path in order to refer to multiple files. Assuming youre keeping your host configuration files in a directory called hosts you could include them like this:

include "hosts/*.conf"

Notifications

Icinga 2 can send you notifications when your services change state. In order to do this were going to write a shell script in /etc/icinga2/mail-notification.sh that sends e-mail based notifications:

#!/bin/sh

if [ -z "$1" ]; then
        echo "Syntax: $0 <e-mail>"
        echo
        echo "Sends a mail notification to the specified e-mail address."
        exit 1
fi

mail -s "** $NOTIFICATIONTYPE Service Alert: $HOSTALIAS/$SERVICEDESC is $SERVICESTATE **" $1 <<TEXT
***** Icinga *****

Notification Type: $NOTIFICATIONTYPE

Service: $SERVICEDESC
Host: $HOSTALIAS
Address: $address
State: $SERVICESTATE

Date/Time: $LONGDATETIME

Additional Info:

$SERVICEOUTPUT
TEXT

exit 0

Our shell script uses a couple of pre-defined macros (e.g. SERVICEDESC, HOSTALIAS, etc.) that are always available.

Next were going to create a Notification template which tells Icinga how to invoke the shell script:

object NotificationCommand "mail-notification" inherits "plugin-notification-command" {
        command = [
                "/etc/icinga2/mail-notification.sh",
                "$email$"
        ],

        export_macros = [
                "NOTIFICATIONTYPE",
                "HOSTALIAS",
                "SERVICEDESC",
                "SERVICESTATE",
                "SERVICEDESC",
                "address",
                "LONGDATETIME",
                "SERVICEOUTPUT"
        ]
}

template Notification "mail-notification" {
        notification_command = "mail-notification"
}

Note

Rather than adding these templates to your main configuration file you might want to create a separate file, e.g. notifications.conf and include it in icinga2.conf.

The export_macros property tells Icinga which macros to export into the environment for the notification script.

We also need to create a User object which Icinga can use to send notifications to specific people:

object User "tutorial-user" {
        display_name = "Some User",

        macros = {
                email = "tutorial@example.org"
        }
}

Each time a notification is sent for a service the users macros are used when resolving the macros we used in the Notification template.

In the next step were going to create a Service template which specifies who notifications should be sent to:

template Service "mail-notification-service" {
        notifications["mail"] = {
                templates = [ "mail-notification" ],

                users = [ "tutorial-user" ]
        },

        notification_interval = 1m
}

And finally we can assign this new service template to our services:

        ...
        services["ping"] = {
                templates = [ "ping4", "mail-notification-service" ]
        },
        ...

In addition to defining notifications for individual services it is also possible to assign notification templates to all services of a host. You can find more information about how to do that in the documentation.

Note

Escalations in Icinga 2 are just a notification, only added a defined begin and end time. Check the documentation for details.

Time Periods

Time periods allow you to specify when certain services should be checked and when notifications should be sent.

Here is an example time period definition:

object TimePeriod "work-hours" inherits "legacy-timeperiod" {
        ranges = {
                monday = "9:00-17:00",
                tuesday = "9:00-17:00",
                wednesday = "9:00-17:00",
                thursday = "9:00-17:00",
                friday = "9:00-17:00",
        }
}

The legacy-timeperiod template is defined in the Icinga Template Library and supports Icinga 1.x time periods. A complete definition of the time Icinga 1.x time period syntax can be found at http://docs.icinga.org/latest/en/objectdefinitions.html#timeperiod.

Using the check_period attribute you can define when services should be checked:

        ...
        services["ping"] = {
                templates = [ "ping4", "mail-notification-service" ],
                check_period = "work-hours"
        },
        ...

Also, using the notification_period attribute you can define when notifications should be sent:

template Service "mail-notification-service" {
        notifications["mail"] = {
                templates = [ "mail-notification" ],

                users = [ "tutorial-user" ]
        },

        notification_interval = 1m,
        notification_period = "work-hours"
}

The notification_period attribute is also valid in User and Notification objects.

Dependencies

If you are familiar with Icinga 1.x host/service dependencies and parent/child relations on hosts, you might want to look at the conversion script in order to convert your existing configuration. There are no separate dependency objects anymore, and no separate parent attribute either.

Using Icinga 2, we can directly define a dependency in the current host or service object to any other host or service object. If we want other objects to inherit those dependency attributes, we can also define them in a template.

In the following example weve added a cluster host with the service ping which we are going to define a dependency for in another host.

template Service "my-cluster-ping" {
        check_command = "my-ping",
}

object Host "my-cluster" {
        ...
        services["ping"] = {
                templates = [ "my-cluster-ping" ],
        }
        ...
}

We can now define a service dependency as new service template (or directly on the service definition):

template Service "my-cluster-dependency" {
        servicedependencies = [
                { host = "my-cluster", service = "ping" },
        ],
}

Now lets use that template for the ping service weve defined previously and assign the servicedependencies to that service.

        ...
        services["ping"] = {
                templates = [ "ping4", "mail-notification-service", "my-cluster-dependency" ],
        },
        ...

Performance Data

Because there are no host checks in Icinga 2, the PerfdataWriter object will only write service performance data files. Creating the object will allow you to set the perfdata_path, format_template and rotation_interval. The format template is similar to existing Icinga 1.x configuration for PNP or inGraph using macro formatted strings.

Details on the common Icinga 1.x macros can be found at http://docs.icinga.org/latest/en/macrolist.html

Note

You can define multiple PerfdataWriter objects with different configuration settings, i.e. one for PNP, one for inGraph or your preferred graphite collector.

Lets create a new PNP PerfdataWriter object:

object PerfdataWriter "pnp" {
        perfdata_path = "/var/lib/icinga2/service-perfdata",
        format_template = "DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$",
        rotation_interval = 15s,
}

You may need to reconfigure your NPCD daemon with the correct path for your performance data files. This can be done in the PNP configuration file npcd.cfg:

perfdata_spool_dir = /var/lib/icinga2/

Livestatus Component

The Livestatus component will provide access to Icinga 2 using the livestatus api. In addition to the unix socket Icinga 2 also service livestatus directly via tcp socket.

Note

Only config and status tables are available at this time. History tables such as log, statehist will follow.

Once Icinga 2 is started, configure your gui (e.g. Thruk) using the livestatus backend.

TCP Socket

library "livestatus"
object LivestatusComponent "livestatus-tcp" {
        socket_type = "tcp",
        host = "10.0.10.18",
        port = "6558"
}

Unix Socket

library "livestatus"
object LivestatusComponent "livestatus-unix" {
        socket_type = "unix",
        socket_path = "/var/run/icinga2/livestatus"
}

Note

You need to grant permissions for the apache user manually after starting Icinga 2 for now.

# chmod o+rwx /var/run/icinga2/{icinga2.cmd,livestatus}

IDO Database Component

The IDO component will write to the same database backend as known from Icinga 1.x IDOUtils. Therefore youll need to have your database schema and users already installed, like described in http://docs.icinga.org/latest/en/quickstart-idoutils.html#createidoutilsdatabase

Note

Currently theres only MySQL support in progress, Postgresql, Oracle tbd.

Configure the IDO MySQL component with the defined credentials and start Icinga 2.

Note

Make sure to define a unique instance_name. That way the Icinga 2 IDO component will not interfere with your Icinga 1.x setup, if existing.

library "ido_mysql"
object IdoMysqlDbConnection "my-ido-mysql" {
        host = "127.0.0.1",
        port = "3306",
        user = "icinga",
        password = "icinga",
        database = "icinga",
        table_prefix = "icinga_",
        instance_name = "icinga2",
        instance_description = "icinga2 instance"
}

Starting Icinga 2 in debug mode in foreground using -x will show all database queries.

Custom Attributes

In Icinga 1.x there were so-called "custom variables" available prefixed with an underscore, as well as plenty of other attributes such as action_url, notes_url, icon_image, etc. To overcome the limitations of hardcoded custom attributes, Icinga 2 ships with the custom attribute as dictionary.

For example, if you have PNP installed we could add a reference url to Icinga Classic UI by using the classic method of defining an action_url.

template Service "my-pnp-svc" {
        custom = {
                action_url = "/pnp4nagios/graph?host=$HOSTNAME$&srv=$SERVICEDESC$' class='tips' rel='/pnp4nagios/popup?host=$HOSTNAME$&srv=$SERVICEDESC$",
        }
}

And add that template again to our service definition:

        ...
        services["ping"] = {
                templates = [ "ping4", "mail-notification-service", "my-cluster-dependency", "my-pnp-svc" ],
        },
        ...

While at it, our configuration tool will add its LDAP DN and a snmp community to the service too, using += for additive attributes:

        ...
        services["ping"] = {
                templates = [ "ping4", "mail-notification-service", "my-cluster-dependency", "my-pnp-svc" ],
                custom += {
                        DN = "cn=icinga2-dev-svc,ou=icinga,ou=main,ou=IcingaConfig,ou=LConf,dc=icinga,dc=org",
                        SNMPCOMMUNITY = "public"
                }
        },
        ...

/* vim: set syntax=asciidoc filetype=asciidoc: */