Was ist Icinga?
Icinga ist ein Open-Source-Überwachungssystem, das die Verfügbarkeit von Netzwerkressourcen überprüft, Benutzer über auftretende Probleme benachrichtigt und Daten für eine effektive Berichterstattung zusammenfasst. Icinga ist eine skalierbare und erweiterbare Software und kann große, komplexe Umgebungen über mehrere Standorte hinweg überwachen. Icinga bedeutet auf Zulu so viel wie "es sucht" oder "es untersucht".
Welche Vorteile bietet die Verwendung des Icinga Monitoring Tools?
- Identifizierung von Problemen überall im Netz
Die Überwachung einer Umgebung mit Icinga hilft bei der schnellen Identifizierung von Problemen. Wenn Sie eine gesamte Umgebung überwachen, können Sie schnell Daten von mehreren Servern sehen und die Grundursache eines Problems identifizieren. Darüber hinaus sind Sie oft in der Lage, ein Problem, das zwangsläufig auftreten wird, anhand von historischen Daten vorherzusagen. Wenn Sie zum Beispiel sehen, dass die Last einer Webanwendung allmählich ansteigt, können Sie feststellen, wie viel Zeit Sie haben, bevor Sie ihr mehr Ressourcen zur Verfügung stellen oder sie optimieren müssen.
- Bessere Nutzung der IT-Ressourcen
Überwachungs-Tools wie Icinga sparen Zeit, indem sie Sie benachrichtigen , wenn irgendwelche Metriken außerhalb der erwarteten Bereiche liegen, während sich Ihre Spezialisten auf höherwertige Aufgaben konzentrieren können. Es kann sogar einige der einfacheren Probleme automatisch beheben , wenn es so konfiguriert ist. Dies hilft Ihnen, sich zu konzentrieren, die Effizienz zu steigern und die Arbeit im Team besser zu verteilen.
- Historische und grundlegende Daten
Icinga2 speichert eine Menge von zeitbasierten Daten. Es ist in zwei Hauptzweige unterteilt - Historie und Leistungsdaten. Die Historie in Icinga2 speichert die Zustandsänderungen aller Hosts und Services und alle für sie ausgelösten Benachrichtigungen oder Ausfallzeiten. Sie wird in der relationalen Datenbank des Icinga2-Masters gespeichert. Die Performance-Daten sind normalerweise Daten, die von den Befehlen gesammelt werden, die zu Überwachungszwecken ausgeführt werden. Diese Daten werden in einer Zeitreihen-Datenbank gespeichert und können mit einem Tool wie Grafana einfach visualisiert werden. Es ist wichtig, einen guten Überblick darüber zu haben, wie die Ressourcen im Laufe der Zeit genutzt werden, wie sich Anwendungen oder Hardware verhalten, und um Probleme vorherzusagen, bevor sie auftreten.
Wie funktioniert Icinga?

Jeder Knoten im Icinga-Szenario hat eine von drei Rollen: Master, Satellit oder Agent. Der Hauptrechner, der die Metriken sammelt, wird als Master registriert.
Wenn wir viele Server zu überwachen haben (Rechner in verschiedenen privaten Teilnetzen ohne direkte Verbindung zu ihnen), können wir sogenannte Satelliteninstanzen hinzufügen, die als Proxy für den Zugriff auf die privaten Teilnetze dienen. So kann beispielsweise für jeden Client ein Satellit vorhanden sein, der die Ausführung der Prüfung vom Master an jede der Instanzen im privaten Teilnetz weiterleitet.
Die zu überwachenden Maschinen - die sogenannten Endpunkte - werden als Agenten registriert. Icinga-Agenten führen Überwachungsskripte aus, die den Status der Skriptausführung sowie optionale Leistungsdaten an den Master zurückmelden.
Für mehr Zuverlässigkeit können wir zwei Instanzen mit Icinga2 erstellen, die als Master registriert sind und sich in einer Zone befinden, so dass, wenn ein Problem mit einer von ihnen auftritt, die andere übernehmen kann. Das Gleiche gilt für Satelliteninstanzen. In einem hochverfügbaren Setup können wir zwei Satelliten für jede Zone haben. Der Master nutzt sie im Round-Robin-Verfahren, um seine Befehlsausführungen zu planen. Dadurch wird sichergestellt, dass die Verbindung zwischen dem Master und den Endhosts auch dann nicht unterbrochen wird, wenn einer der Satelliten ausfällt.
Konfiguration
Sobald wir alle Maschinen als Master, Satellit oder Agent registriert haben und sobald wir eine Web-Schnittstelle (Icinga Web 2) haben, müssen wir die Hosts und Metriken hinzufügen. Der Dateiladeprozess für Icinga2 beginnt mit der Datei icinga2.conf. Normalerweise werden alle Dateien mit der Endung .conf rekursiv aus dem Verzeichnis conf.d über die folgende Definition geladen:
include_recursive "conf.d".
Hierarchie
Die Hierarchie in Icinga2 besteht aus Objekten vom Typ Zone. Zonen hängen von der Eltern-Kind-Beziehung ab, um sich gegenseitig vertrauen zu können. Ein Server aus einer übergeordneten Zone kann seine Konfigurationsinformationen an seine untergeordneten Server weitergeben, aber Hosts, die tiefer in der Hierarchie stehen, können keine Konfigurationsdaten an die übergeordnete Zone weitergeben. Dies gilt für die Top-Down-Konfiguration, die am häufigsten vorkommt.
Server-Agenten haben auch ihre eigene Zone. Als Standardverfahren verwenden wir FQDN (Fully Qualified Domain Name), um diese Zone zu benennen.
Objekte, Vorlagen und Anwendungsregeln

In den Konfigurationsdateien beschreiben wir alle Elemente, die wir im Abschnitt Übersicht sehen, sowie andere Vorlagen und Befehle, und wenden Regeln und Konfigurationen an, die für eine gute Beschreibung und Struktur in Icinga erforderlich sind.
Jede Prüfung, die wir auf einem von uns überwachten Server durchführen, ist nichts anderes als ein Skript, das auf diesem Server ausgeführt wird. Es ist eine gute Idee, den absoluten Pfad zu allen Standard-Skripten von Nagios sowie zu allen Skripten, die wir zusätzlich herunterladen oder schreiben, in einer konstanten Variablen zu speichern. Die Standardkonstanten sind definiert in der Datei constants.conf im Icinga-Hauptverzeichnis (normalerweise /etc/icinga2). Im Falle eines verteilten Setups wie dem, das wir hier beschreiben, ist es am besten, die Konstanten in einer globalen Zone zu halten, z.B. in globalen Templates, um sicherzustellen, dass Sie sie nicht in der constants.conf jedes einzelnen Satelliten oder Agenten definieren müssen.
object CheckCommand "SYSTEM.cpu" {
timeout="60"
command = CustomPluginDir + "/check_cpu_stats.sh -w $cpu_warn$ -c $cpu_crit$"
vars.cpu_warn = "20"
vars.cpu_crit = "30"
}
Um diese Skripte zu verwenden, müssen wir sie als Objekte des Typs CheckCommand.
Das Wichtigste an der Definition des CheckCommand-Objekts ist, dass wir den Pfad zu dem auszuführenden Skript und die Parameter, die wir ihm übergeben möchten, angeben. In diesem Fall, CustomPluginDir eine Konstante. Anschließend wird sie mit dem restlichen Pfad zum benötigten Skript und den Parametern, die an das Skript übergeben werden können, verkettet. Die Parameter werden am besten als Variablen gespeichert, die später in der Dienstdefinition überschrieben werden können. Wir können dann eine apply Service rule erstellen, um genau festzulegen, welches CheckCommand-Objekt mit welchen Hosts verbunden werden soll. Zum Beispiel:
apply Service "SYSTEM.cpuStats." for (cpu_load => config in host.vars.cpu_stats) {
import "generic-service"
check_command = "SYSTEM.cpu"
command_endpoint = host.vars.client_endpoint
max_check_attempts = 10
vars += config
assign where host.vars.client_endpoint && host.vars.cpu_stats
}
(Der Operator += fügt den Inhalt einer Dictionary-Host-Variable "vars.cpu_stats" als Variablen für den Dienst hinzu. Er überschreibt alle Standardvariablen, die in der CheckCommand-Definition festgelegt wurden oder die vor der Dienstdefinition geschrieben wurden.)
Mit der assign where-Klausel beschreiben wir, auf welche Hosts dieser Dienst angewendet werden soll. In unserem Beispiel gilt er für diejenigen Hosts, die den vars.client_endpoint und vars.cpu_stats-Variablen definiert sind, unabhängig davon, welchen Wert sie haben. Wir können den Dienst auch auf genau die Hosts anwenden, die einen bestimmten Wert einer bestimmten Variable haben, z. B. zuweisen, wenn host.vars.os = "Linux".
If we don’t have an assign where <condition> line in the apply rule, Icinga will give an error (of type Critical) that the corresponding service is not connected to any host. If we have defined an assign rule, but it doesn’t match any host, then Icinga will throw a Warning error. The corresponding service will exist in the configuration, but will not be attached to any instance.
template Service "generic-service" {
max_check_attempts = 5
check_interval = 2m
retry_interval = 1m
}
Icinga erlaubt uns, Service-Vorlagen zu erstellen. Darin geben wir an, wie oft die Prüfung maximal durchgeführt werden soll, bevor wir uns vergewissern, dass der Status des Dienstes auf Warnung, kritisch oder unbekannt geändert hat, und eine Benachrichtigung senden. In der Vorlage legen wir auch check_interval fest, d. h. in welchem Intervall die angegebene Prüfung durchgeführt werden soll, sowie retry_interval, d. h. wie lange gewartet werden soll, bevor eine Prüfung erneut durchgeführt wird, wenn sie nicht erfolgreich war. Die Werte des Vorlagendienstes können immer in jedem Dienst einzeln überschrieben werden, und zwar nach der Zeile, in der sie importiert werden. Sie können auch Variablen oder andere Metadaten enthalten, je nach der Struktur der Konfiguration.
Natürlich müssen wir auch einen bestimmten Host haben, um einen bestimmten Dienst anzuwenden.
object Host "hostname1" {
import "generic-host"
address = "10.1.1.1"
vars.client_endpoint = "hostname1"
//...
vars.cpu_stats.dft = {
cpu_warn = "50"
cpu_crit = "70"
}
}
In Icinga haben wir auch die Möglichkeit, Host-Vorlagen zu erstellen. In diesen können wir wiederum die maximale Anzahl von Prüfungen festlegen, die durchgeführt werden sollen, bevor der Servicezustand in einen harten Zustand übergeht. Beim harten Zustand mit optionalen EventCommands oder Benachrichtigungen auf dem Weg dorthin. Sie enthält auch Informationen darüber, wie oft die Prüfung durchgeführt werden soll und wie oft sie wiederholt werden soll, wenn sie fehlschlägt. Außerdem wird in der Host-Vorlage können wir auch den CheckCommand definieren.
template Host "generic-host" {
max_check_attempts = 3
check_interval = 1m
retry_interval = 30s
check_command = "custom_health"
}
object CheckCommand "custom_health" {
command = CustomPluginDir + "/hostalive.py -H $address$ -n $host.display_name$ -s -e $extra_port_check$"
}
In unserem Beispiel importieren wir in das Objekt Host "hostname1" die Vorlage "generic-host", die den Befehl "custom_health" ausführt
In einem verteilten System wie diesem wird die gesamte Konfiguration auf dem Hauptserver definiert und über die API-Verbindung, die bei der Serverregistrierung hergestellt wird, an die nachfolgenden Server (Satelliten und Agenten) verteilt. Alle Server müssen die Befehls- und Dienstdefinitionen kennen, um ein Skript ausführen zu können, und dafür wird die Zone global-templates verwendet. Sie wird an alle Server im Überwachungsnetz verteilt. Die übrigen Zonen sind in der Regel Satellitenzonen und werden entsprechend verteilt. So wird beispielsweise die Satellitenzone site1 an die Satelliteninstanzen in der Zone site1 übertragen, damit diese wissen, welche Agenten in ihrer Zone vorhanden sind.
Benachrichtigungen
Um unsere Infrastruktur effektiv zu verwalten und auf kritische Alarme schnell reagieren zu können, müssen wir in der Lage sein, benachrichtigt zu werden, wenn ein Problem auftritt. Zu diesem Zweck können wir in Icinga das NotificationCommand-Objekt konfigurieren, in dem wir den Befehl selbst angeben.
object NotificationCommand "service-notification-itop-p1" {
command = [ CustomPluginDir + "/icinga2-cli/icinga2_cli.py", "notify" ]
arguments = {
"-m" = "itop"
"-f" = NotifPluginDir + "/notify-itop-service.txt"
}
env = {
SERVICENAME = "$service.name$"
//...
}
}
Wir können auch eine Benachrichtigungsvorlage definieren, in der wir angeben, welcher Benachrichtigungsbefehl verwendet werden soll.
Hier legen wir fest, welcher Befehl ausgeführt werden soll, für welche Zustände und Arten von Meldungen er ausgeführt werden soll und in welchem Zeitraum.
template Notification "service-notification-itop_24x7_p1" {
command = "service-notification-itop-p1"
states = [ OK, Warning, Critical, Unknown ]
types = [ Problem, Custom ]
vars += {
notification_logtosyslog = true
}
period = "24x7"
}
object TimePeriod "24x7" {
display_name = "Icinga 2 24x7 TimePeriod"
ranges = {
"monday" = "00:00-24:00"
"tuesday" = "00:00-24:00"
"wednesday" = "00:00-24:00"
"thursday" = "00:00-24:00"
"friday" = "00:00-24:00"
"saturday" = "00:00-24:00"
"sunday" = "00:00-24:00"
}
}
Damit die Benachrichtigung für den Dienst oder den Host gilt, müssen wir wie bei einem Dienst definieren, wie dies geschehen soll. Hier haben wir die Möglichkeit festzulegen, welche Benutzer oder Gruppen benachrichtigt werden sollen, was in der Regel aus der Hostkonfiguration übernommen wird. Wir können ein "Intervall" für die erneute Benachrichtigung festlegen, wenn das Problem weiterhin besteht, und natürlich die bekannte "assign where"-Anweisung, die wir auch aus der Service-Definition kennen.
apply Notification "icingaadmin-itop_24x7_p1" to Service {
import "service-notification-itop_24x7_p1"
user_groups = host.vars.notification.api_itop_24x7_p1.groups
users = host.vars.notification.api_itop_24x7_p1.users
interval = 30m
vars.notification_logtosyslog = true
assign where service.vars.eoc_prio == "p1" && host.vars.notification.api_itop_24x7_p1
}
Darin geben wir auch an, an welche Benutzer die Benachrichtigung gesendet werden soll. Um dies zu erreichen, müssen wir ein Objekt Benutzer oder ein Objekt UserGrouphaben, in dem die Benutzer definiert und eine E-Mail-Adresse oder eine andere Art der Zustellung der Benachrichtigung angegeben werden kann.
object Host "some-host"{
vars.notification["api_itop_24x7_p1"] = {
users = [ "clientname-p1" ]
}
//...
}
Hier sehen wir, dass in der obigen Regel "Benachrichtigung anwenden" der Ausdruck host.vars.notification.api_itop_24x7_p1.users einen Wert von kundenname-p1. Auf dem spezifischen Host haben wir jedoch keinen Wert für vars.notification.api_itop_24x7_p1.groupsso dass eine Benachrichtigung nur an den angegebenen Benutzer gesendet wird.
object User "clientname-p1" {
import "generic-user"
display_name = "ClientName HighPriority User"
email = "clientname_p1@companyname.com"
//...
}
Das häufigste, was ein Benutzerobjekt in seiner Definition haben kann, ist die E-Mail, an die die Benachrichtigung gesendet werden soll. Wir können auch eine Benutzer-Vorlage mit zusätzlichen Merkmalen für den Import in das Benutzerobjekt "Kundenname-p1". Benutzerobjekte können auch Variablen haben, um komplexere Lieferprozesse zu ermöglichen.
template User "generic-user" {
//...
}
Wir können all diese Konfigurationen in eine einzige Datei mit der Erweiterung .conf schreiben, die sich im Hauptverzeichnis von Icinga befinden sollte. Der Einfachheit halber können wir sie auch in separate Konfigurationsdateien in verschiedenen Verzeichnissen aufteilen.
Schlussfolgerung
Icinga ist eine Open-Source-Überwachungssoftware, die viele Konfigurationsmechanismen bietet, damit wir die Überwachung der Umgebung so effizient wie möglich organisieren können. Dank dieser Mechanismen können wir unsere eigenen Entscheidungen darüber treffen, welche die kritischsten Metriken sind, die überwacht werden sollen, wann Benachrichtigungen gesendet werden sollen, in welchem Intervall, usw. Icinga kann für alle Arten von Cloud-Umgebungen verwendet werden (öffentliche, private und hybride Clouds). Auch wenn Icinga2 keine Out-of-the-Box-Unterstützung für moderne Lösungen wie Kubernetes bietet, bemühen sich viele Open-Source-Projekte wie Signalilo darum, die Lücke zwischen eher containerorientierten Lösungen wie Prometheus und Icinga2 zu schließen.
Weitere Ressourcen und Experten-Tutorials zu Icinga finden Sie in "Icinga 2 Fine Tuning" sowie in "Icinga 2: API and Passive Checks".

