Ein einfacher Event Handler in Icinga 2

Diesen Beitrag schrieb ich 6 Jahre und 4 Monate zuvor; die nachfolgenden Ausführungen müssen heute nicht unbedingt noch genau so funktionieren. Behalte das beim Lesen (und vor allem: beim Nachmachen!) bitte stets im Hinterkopf.

Geschätzte Lesezeit: 2 Minuten

Die Aufgabe

Ich möchte auf meinem Host webserver mit IP 192.168.3.3 nicht nur überwachen, ob der Dienst memcached läuft – ich möchte ihn auch starten, falls er es mal nicht tut. Natürlich ist das exemplarisch – grundsätzlich lässt sich die Logik auf beliebige Dienste anwenden. Und ausweiten, wie ihr feststellen werdet…

event_restart_by_ssh

Ein Rückgabewert von 0 bedeutet, unser Check liefert OK, und im Umkehrschluss bedeutet das: bei jedem Rückgabewert > 0 schicken wir unseren event handler auf die Reise. Wir können uns diesen Rückgabewert greifen ($service.state_id$) und prüfen, ob er größer als (_greater than_ → -gt) 0 ist (test $service.state_id$ -gt 0); ist er größer als 0 (sprich die Überprüfung liefert ein true zurück), so wird der Restart des Dienstes angetriggert – und nur dann (&& sudo service $event_restart_by_ssh_daemon$ restart).

object EventCommand "event_restart_by_ssh" {
  import "plugin-event-command"
  command = [ PluginDir + "/check_by_ssh" ]
  arguments = {
    "-H" = {
                value = "$event_restart_by_ssh_address$"
                description = "Host address."
        }
    "-C" = {
                value = "test $service.state_id$ -gt 0 && sudo service $event_restart_by_ssh_daemon$ restart"
                description = "Test and command for daemon to restart."
        }
    }
  vars.event_restart_by_ssh_address = "$address$"
}

Der Service

In meinem Beispiel definiere ich für meinen Host webserver einen Service, der per nrpe die Verfügbarkeit von memcached abprüft; welches Plugin ihr hierfür zum Einsatz bringt sei euch überlassen, wichtig ist nur, dass es konforme Rückgabewerte liefert. Mit vars.event_restart_by_ssh_daemon gebe ich mit, wie der Daemon heißt, der im Bedarfsfalle restartet werden muss.

object Service "NRPE service memcached" {
  import "generic-service"
  hostname = "webserver"
  check_command = "nrpe"
  vars.nrpe_command = "check_memcached"
  event_command = "event_restart_by_ssh"
  vars.event_restart_by_ssh_daemon = "memcached"
}

Icinga2 Event Handler

Der User

Okay. Wir bekommen mit, wenn der Dienst absemmelt. Wir haben ein Event definiert, das in dem Falle greifen und den Dienst neu starten soll. Wir werden feststellen, dass das allein jedoch nicht reicht: der User, unter dem Icinga2 läuft – auf meinem System heißt er nagios – muss sich per SSH vom Monitoring-Server aus auf webserver ohne Passwort einloggen und $DINGE tun dürfen. Grundsätzlich regeln wir das so, indem für User nagios ein SSH-Key erstellt, der öffentliche Schlüssel auf webserver in authorized_keys hinterlegt und der sshd auf webserver entsprechend konfiguriert wird – kurz: die übliche SSH Key-Based Authentication (hierzu hatte ich vor einiger Zeit einen ausführlicheren Artikel, der auch heute noch Gültigkeit hat).

Zusätzliche Sicherheit bringe ich hinein, indem ich in der authorized_keys festhalte, dass User nagios sich ausschließlich von meinem Monitoring-Server aus einloggen darf; das ist zu erreichen, indem dem Key ein from="..." voran gestellt wird. Und je nach Anwendungsfall kann man den Zugriff weiter beschränken, indem auch noch mit command="..." festgehalten wird, was genau der User ausführen darf.

from="192.168.3.1" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABA[...]

Auf webserver halten wir fest, dass der User nagios den memcached restarten darf – üblicherweise darf das nämlich nur root.

$ visudo
[...]
nagios	ALL = (ALL) NOPASSWD: /usr/sbin/service memcached *

Fazit: User nagios darf sich nun vom Monitoring-Server – und nur von dort! – auf webserver einloggen und den Service memcached – und nur den! – neu starten.

Der Test

Zeit für den ersten Testlauf! Hierzu schalten wir das debuglog von Icinga2 ein:

$ icinga2 feature enable debuglog
Enabling feature debuglog. Make sure to restart Icinga 2 for these changes to take effect.
$ service icinga2 restart
$ tail -f /var/log/icinga2/debug.log | grep memached

Und nun kann auf webserver der memached abgeschaltet werden:

$ service memcached stop

Im Output des debug.log können wir nun live beobachten, was geschieht:

[2016-01-05 13:14:39 +0100] debug/CheckerComponent: Executing check for 'webserver!NRPE service memcached'
[2016-01-05 13:14:39 +0100] notice/Process: Running command '/usr/lib/nagios/plugins/check_nrpe' '-H' '192.168.3.3' '-c' 'check_memcached': PID 26610
[2016-01-05 13:14:39 +0100] notice/Process: PID 26610 ('/usr/lib/nagios/plugins/check_nrpe' '-H' '192.168.3.3' '-c' 'check_memcached') terminated with exit code 2
[2016-01-05 13:14:39 +0100] notice/Checkable: State Change: Checkable webserver!NRPE service memcached soft state change from OK to CRITICAL detected.
[2016-01-05 13:14:39 +0100] notice/Checkable: Executing event handler 'event_by_ssh_restart_service' for service 'webserver!NRPE service memcached'
[2016-01-05 13:14:39 +0100] notice/Process: Running command '/usr/lib/nagios/plugins/check_by_ssh' '-C' 'test 2 -gt 0 && sudo service memcached restart' '-H' '192.168.3.3': PID 26617
[2016-01-05 13:14:41 +0100] notice/Process: PID 26617 ('/usr/lib/nagios/plugins/check_by_ssh' '-C' 'test 2 -gt 0 && sudo service memcached restart' '-H' '192.168.3.3') terminated with exit code 0

Vergesst nicht, für den produktiven Betrieb das Debuglog wieder abzuschalten – das müllt euch sonst fröhlich die Platte voll ;-)

Nur der Anfang…

Wie ihr schnell sehen werdet: das ist nur der Anfang, denn auf diese Art kann man den User nagios alle möglichen Wartungsarbeiten auf den Maschinen ausführen lassen. An dieser Stelle findet ihr eine ausführlichere Version, bei der das Restarten eines Dienstes nur eine Möglichkeit darstellt und von der ihr euch prima inspirieren lassen könnt.