Es ist schon ein paar Jahre her, als das Twitter-Hashtag “#monitoringsucks” aufkam und sich schnell großer Verbreitung erfreute, denn Überwachungssoftware war an ihre Grenzen gelangt und stagnierte. Unser Autor Jochen Lillich berichtet, wie er einen Ausweg aus dem Dilemma fand.
Vor einigen Jahren schien es, als würde sich im Bereich der freien Monitoring-Systeme nicht mehr sonderlich viel bewegen. Nagios behauptete sich trotz seiner vielen Schwächen unverdrossen als Platzhirsch und die alternativen Lösungen brachten kaum neue Ansätze ins Spiel. Auf der anderen Seite trieb das durch die Cloud beschleunigte Infrastruktur-Wachstum die meisten Monitoring-Systeme umso schneller an ihre Leistungsgrenzen. Die Hoffnung auf mehr Spaß bei der Serverüberwachung hielt sich in engen Grenzen.
Eher unerwartet tauchte dann ein Licht am Ende des Tunnels auf. Es war 2012 und ein schwedischer Systemadministrator namens Ulf Mansson war von einer neuen Monitoring-Software so begeistert, dass er das Hashtag »#monitoringlove« in Umlauf brachte. Während der Devops Days in Rom erzählte er ausführlich, wie der Wechsel auf diese neue Software seinem Ops-Team wieder Spaß an der Arbeit gebrach hatte. Begeisterung machte sich breit im Publikum. Und da unsere stetig wachsende Hosting-Infrastruktur gerade dabei war, Nagios (und unsere Nerven) zu überstrapazieren, war ich mehr als neugierig, was das für ein System war. Der Name des Projekts? Sensu.
Open Core
Es gibt eine ganze Reihe von Gründen, warum Sensu sich der Liebe vieler Ops-Teams weltweit erfreut:
- Geschrieben ist es in Ruby und seine Konfigurationsdateien verwenden das etablierte Json-Format.
- Seine Architektur ist sehr skalierbar, sodass Sensu auch noch funktioniert, wenn es Hunderte oder gar Tausende von Servern zu überwachen hat.
- Plugins, allen voran die eigentlichen Checks, können in jeder beliebigen Sprache programmiert werden.
- Für die Check-Ergebnisse verwendet Sensu das von Nagios bekannte Format, wodurch alle existierenden Nagios-Checks weiterverwendet werden können.
- Sensu sammelt sowohl Statusinformationen als auch Laufzeitmetriken.
- Es gibt eine große Anzahl von Schnittstellen zu externen Diensten.
- Die Sensu-Community ist sehr aktiv und hilfsbereit.
Sensu ist ein so genanntes Open-Core-Projekt, das die Kernsoftware unter einer freien Lizenz veröffentlicht, die zudem die Basis eines proprietären Produkts mit zusätzlichen Features bildet. Zu Beginn hatte Sean Porter Sensu als Teilzeit-Projekt bei der Firma Sonian entwickelt, inzwischen bezahlt ihn Heavy Water Operations dafür, sich zu 100 Prozent Sensu zu widmen. Frei vertrieben wird Sensu Core unter der MIT-Lizenz.
Das kommerzielle Produkt Sensu Enterprise baut auf dem Fundament von Sensu Core auf. Sensu Enterprise verwendet Jruby als Laufzeitumgebung, was eine höhere Verarbeitungsleistung verspricht. Weitere Vorteile der kostenpflichtigen Version sind Zusatzfunktionen, zum Beispiel die Konvertierung von Metriken, die einfache Integration externer Dienste sowie der direkte technische Support durch die Entwickler bei Heavy Water Operations.
Wer kostenlose Hilfe beim Betrieb von Sensu sucht, findet sie in der sehr hilfsbereiten Entwicklercommunity, die über Mailinglisten sowie im IRC-Channel http://#sensu auf Freenode zu erreichen ist.
Architektur
Sensu zeichnet sich durch erstaunlich hohe Leistung und Skalierbarkeit aus. Der Schlüsselfaktor dazu ist die Architektur, wie sie Abbildung 1 darstellt. Statt die verschiedenen Komponenten des Monitoring-Framework in eine monolithische Software zu packen, wobei ihre Schnittstellen schnell zum Flaschenhals werden können, setzt Sensu auf eine verteilte Architektur.
Wie jedes Monitoring-System muss auch Sensu die Durchführung von Monitoring-Checks auslösen, deren Ergebnisse verarbeiten und daraufhin Aktionen ausführen, zum Beispiel SMS-Nachrichten versenden oder Logeinträge vornehmen. Aufgrund der modularen Art und Weise, mit der das System diese Abläufe steuert, wird schnell verständlich, warum Sensu zuweilen auch als “Monitoring-Router” bezeichnet wird.
Im Zentrum der Sensu-Maschinerie läuft mit Rabbit MQ ein Message-Bus, der die asynchrone Kommunikation zwischen den Systemkomponenten erlaubt. Bei allen Abläufen in Sensu stellt Rabbit MQ stets das Bindeglied dar. So hat ein Bearbeitungsstau an einer Komponente nicht zwangsläufig zur Folge, dass er alle anderen Komponenten ausbremst.
Die Aufforderung an die Sensu-Clients, einen bestimmten Check auszuführen, legt der Sensu-Server einfach auf den Bus. Innerhalb kurzer Zeit wird jeder angesprochene Client dieser Aufforderung nachkommen und das Ergebnis des Checks seinerseits auf dem Bus platzieren. Nun ist erneut der Server an der Reihe, die Check-Ergebnisse zu verarbeiten und daraus Ereignisse abzuleiten. Diese Ereignisse setzen schließlich so genannte Eventhandler in Aktionen um, zum Beispiel in einen SMS-Alarm oder in eine Nachricht im Chatkanal des Ops-Teams. Auf jede dieser Phasen gehe ich später noch eingehend ein.
Eine weitere Systemkomponente ist das Sensu-API. Es stellt eine REST-artige Schnittstelle zur Verfügung, um von außen Informationen über alle überwachten Maschinen, deren Checks und Ereignisse abzufragen. Über das API lässt sich sowohl die Ausführung von Checks auslösen als auch die Verarbeitung bestimmter Checks verhindern. Zudem kann das API Alarme quittieren oder löschen.
Zumindest einen Dienst, der dieses API nutzt, wird wohl jeder Sensu-Anwender installieren, nämlich eine Website zur interaktiven Bedienung des Systems. Der modulare Aufbau von Sensu zeigt auch hier seine Vorteile, denn alternativ zum im Grundumfang enthaltenen Dashboard [1] können Sensu-Anwender auch andere Implementierungen wie [2] einsetzen.
Server-Installation
Sensu ist sehr einfach zu installieren. Damit seine Abhängigkeiten von der Ruby-Umgebung und zahlreichen externen Bibliotheken keinen Wartungsalbtraum verursachen, kommt Sensu in Form eines so genannten Omnibus-Pakets, das alle nötigen Komponenten enthält und diese an gesonderter Stelle im System installiert. Deshalb beschränkt sich eine minimale Sensu-Installation darauf, die Sensu-Paketquellen hinzuzufügen und danach ein »apt-get install sensu« beziehungsweise »yum install sensu« auszuführen. Lediglich Rabbit MQ und Redis sind nicht im Sensu-Omnibus enthalten, sie werden einfach aus den Paketen der Linux-Distribution installiert.
Im Sensu-Paket sind Startskripte für »/etc/init.d« enthalten, die auf die übliche Weise zu aktivieren sind. Skripte für Upstart und andere Supervisor-Alternativen finden sich in »/usr/share/sensu« . Listing 1 zeigt eine minimale Serverkonfiguration, die Sensu Zugriff auf die beteiligten Komponenten gibt.
Listing 1
Verknüpfung der Dienste
01 ```Json
02 {
03 "Rabbit MQ": {
04 "ssl": {
05 "private_key_file": "/etc/sensu/ssl/client_key.pem",
06 "cert_chain_file": "/etc/sensu/ssl/client_cert.pem"
07 },
08 "port": 5671,
09 "host": "localhost",
10 "user": "sensu",
11 "password": "mypass",
12 "vhost": "/sensu"
13 },
14 "redis": {
15 "host": "localhost",
16 "port": 6379
17 },
18 "api": {
19 "host": "localhost",
20 "port": 4567
21 },
22 "dashboard": {
23 "host": "localhost",
24 "port": 8080,
25 "user": "admin",
26 "password": "secret"
27 }
28 }
29 ```
Wer automatisiertes Konfigurationsmanagement betreibt, kann auf ein Chef-Cookbook [3] oder ein Puppet-Modul [4] zurückgreifen; beide werden direkt durch das Sensu-Team gepflegt. Diesen Ansatz kann ich nur wärmstens empfehlen, denn sauberes Configuration Management verhindert zum Beispiel, dass Maschinen in Betrieb gehen, ohne ins Monitoring aufgenommen zu werden.
Client-Installation
Da der Sensu-Client nur mit Rabbit MQ spricht, ist seine Installation auf jeder zu überwachenden Maschine noch einfacher. Wir verwenden das gleiche Sensu-Paket und die gleiche »config.json« wie auf dem Server, aktivieren aber lediglich den »sensu-client« -Service. Sobald dieser sich mit Rabbit MQ verbunden hat, ist er Teil des Monitoring-Verbunds.
Beim ersten Start registriert sich der Client automatisch beim Server, von diesem Moment an erwartet der Sensu-Server zumindest regelmäßige Lebenszeichen in Form von Keepalive-Nachrichten. In der Standardkonfiguration schlägt Sensu Alarm, sobald sich ein Client nicht mehr innerhalb der letzten 3 Minuten gemeldet hat.
Wie jedes Monitoring-System führt Sensu Checks aus, um den Zustand bestimmter Systemkomponenten zu prüfen. Anders als zum Beispiel Nagios kennt Sensu dabei keine Hostchecks. Checks werden grundsätzlich von einem Sensu-Client ausgeführt. Dieser nimmt dann die Ausgabe des Checks entgegen und legt sie zur Verarbeitung durch den Server auf den zentralen Message-Bus. Sensu-Checks lassen sich in jeder beliebigen Programmiersprache entwickeln, die Text auf Stdout ausgeben kann.
Wer mit Sensu startet, wird sich zunächst vor allem mit Statuschecks beschäftigen, die den aktuellen Systemzustand widerspiegeln. Dabei unterscheidet Sensu
- passive Checks, die der Sensu-Server anfordert,
- aktive Checks, die der Sensu-Client unaufgefordert ausführt, und
- externe Ereignisse, die separate Anwendungen dem Sensu-Client übermitteln.
Der Start mit Sensu wird enorm erleichtert durch die Tatsache, dass Sensu die Ergebnisse von Statuschecks im Nagios-Format erwartet. Nicht nur gestaltet dies die Entwicklung eigener Checks sehr einfach, es steht von Anfang an auch eine riesige Anzahl einsatzbereiter Checks zur Verfügung. Dank dieser Designentscheidung konnten wir schon wenige Stunden nach der Installation von Sensu unser überfordertes Nagios von allen wichtigen Checks entlasten und endlich wieder aktuelle Monitoring-Ergebnisse genießen. Ein »#monitoringlove« durchflutete unser Team.
Die meisten Checks löst der Sensu-Server aus. Er richtet die Aufforderung zur Ausführung eines Checks stets an eine Gruppe von Abonnenten (Subscribers). Listing 2 zeigt eine einfache Konfiguration, die den Client den Gruppen »all« und »test« anschließt. Dank dieses Publish/Subscribe genannten Verfahrens reicht eine einzige Anforderung des Servers, um von mehreren Hundert Clients zum Beispiel den freien Plattenplatz abzufragen. Die Konfiguration eines solchen Checks ist in Listing 3 dargestellt. Jeder Client, der Nachrichten der Gruppe »all« abonniert, wird auf Aufforderung des Servers (im Intervall von 60 Sekunden) den in »command« definierten Check ausführen und dessen Ausgabe via Rabbit MQ zum Server zurückliefern.
Listing 3
Disk-Check
01 ~~~Json
02 {
03 "checks": {
04 "disk_free": {
05 "type": "status",
06 "subscribers": [ "all" ],
07 "handlers": [ "default" ],
08 "command": "/usr/lib/nagios/plugins/check_disk
09 -w :::disk_warn::: -c :::disk_crit:::
10 -A -x /dev/shm -X nfs -i /boot",
11 "interval": 60
12 }
13 }
14 }
15 ~~~
Listing 2
/etc/sensu/conf.d/client.Json
01 ```Json
02 {
03 "client": {
04 "name": "client1.example.com",
05 "address": "10.0.10.1",
06 "subscriptions": [ "all", "test" ],
07 "disk_warn": "10%",
08 "disk_crit": "5%"
09 }
10 }
11 ```
Der Beispiel-Check arbeitet mit Variablen, die für den jeweiligen Client spezifische Werte haben dürfen. Als Platzhalter für eine Variable dient deren Name mit je drei Doppelpunkten links und rechts. Ihren lokalen Wert entnimmt der Sensu-Client der Datei »client.conf« .
Zusätzlich zu »interval« kennt Sensu noch weitere Optionen zur Steuerung von Checks. Manchmal ist es zum Beispiel sinnvoll, dass erst nach mehreren fehlgeschlagenen Checks (Occurences) in Folge ein Ereignis an den Server gesendet wird. Das ist mit Sensu ebenso möglich wie die Behandlung ständig hin und her wechselnder Zustände (Flapping).
Soll der Client einen Check aktiv, also unabhängig vom Server, auslösen, kommt der Stand-alone-Check zum Einsatz. Listing 4 zeigt das Beispiel eines lokal gesteuerten MySQL-Checks, den der Client alle 30 Sekunden ausführt. Aktive Checks sind einfacher als passive, weil sie keiner Konfiguration und Verwaltung auf dem Server bedürfen. Zu ihrer Aktivierung reicht schon eine manuell auf dem Client erstellte Json-Datei. Das ist nützlich, wenn es um kurzlebige Server geht, die den Konfigurationsaufwand an zentraler Stelle nicht rechtfertigen.
Listing 4
Aktiver Check
01 ```Json
02 {
03 "checks": {
04 "mysql_server": {
05 "standalone": true,
06 "interval": 30,
07 "handlers": [
08 "default"
09 ],
10 "command": "/usr/lib/nagios/plugins/check_mysql -u 'monitoring' -p
11 'db1ch3ck'"
12 }
13 }
14 }
15 ```
Solche Quick-and-dirty-Hacks widersprechen allerdings klar dem Automationsgedanken. Deshalb ist es gut, dass das Sensu-Cookbook zur Einrichtung aktiver Checks eine simple Chef-Ressource namens »sensu_check« definiert. Listing 5 enthält ein Recipe-Fragment, das obigen Check einrichtet. Doch aktive Checks sind auch dann sinnvoll, wenn ihre Ausführung zu festen Zeitpunkten erforderlich ist. Das Publish/Subscribe-Verfahren der passiven Checks kann dies nicht gewährleisten, das aktive Auslösen auf dem Client schon.
Listing 5
Chef-Ressource für aktive Checks
01 ~~~ruby
02 sensu_check 'mysql_server' do
03 command "/usr/lib/nagios/plugins/check_mysql " +
04 "-u 'monitoring' " +
05 "-p '#{node['mysql']['server_mon_password']}'"
06 handlers ['default']
07 standalone true
08 interval 30
09 end
10 ~~~
Wenn Sensu nicht nur Statusinformationen aus dem System, sondern auch Monitoring-Ereignisse einer externen Anwendung verarbeiten soll, muss der Admin dazu nicht mal spezielle Checks entwickeln. Sensu stellt dafür bereits eine Schnittstelle bereit: Die Anwendung kann ihre Daten dem lokalen Sensu-Client direkt über Port 3030 übergeben. Listing 6 zeigt am Beispiel eines Shellskripts, wie einfach das geht. Da Sensu externe Ereignisse im Json-Format erwartet, dessen Erzeugung mit Shellkommandos schnell aufwändig wird, hat sich in der Praxis der Einsatz des Sensu-Shell-Helper [5] bewährt.
Listing 6
Übergabe externer Ereignisse
01 ~~~bash
02 echo '{ "name": "my_check",
03 "output": "{ ... }",
04 "status": 0 }'
05 > /dev/tcp/localhost/3030
06 ~~~
Zusätzlich zu Statusinformationen kann der Sensu-Client auch Laufzeitmetriken sammeln. Listing 7 gibt die Definition eines solchen Checks wieder, der ein Ruby-Skript ausführt, um die Systemlast zu erheben. Wie bei den Statuschecks ist auch bei Laufzeitmetriken das Ausgabeformat bewusst einfach gehalten. Wie aus Listing 8 leicht zu erkennen ist, erwartet Sensu einen Messpunkt pro Zeile, der jeweils aus einer hierarchischen Metrik-ID, dem Messwert und einem Zeitstempel besteht.
Listing 8
Metrik-Check
01 ~~~ 02 $ ruby load-metrics.rb 03 srv3.local.load_avg.one 0.89 1365270842 04 srv3.local.load_avg.five 1.01 1365270842 05 srv3.local.load_avg.fifteen 1.06 1365270842 06 $ echo $? 07 0 08 ~~~
Listing 7
Check für Laufzeitmetriken
01 ~~~Json
02 {
03 "checks": {
04 "load_metrics": {
05 "type": "metric",
06 "command": "load-metrics.rb",
07 "subscribers": [
08 "production"
09 ],
10 "interval": 10
11 }
12 }
13 }
14 ~~~
Wenn der Sensu-Client nach der Ausführung eines Checks dessen Ergebnis zurück an den Message-Bus gegeben hat, folgt die Auswertung durch den Server. Das ist die Aufgabe der Eventhandler, deren Integration in Sensu ähnlich modular und einfach ist wie die der Checks. Sobald ein neues Ereignis über den Bus kommt, übergibt es Sensu (wie üblich im Json-Format) den zuständigen Eventhandlern und diese leiten daraus geeignete Aktionen ab. Das Spektrum möglicher Aktionen ist breit – das sind nur die naheliegendsten Beispiele:
- Benachrichtigung via E-Mail oder SMS,
- Meldungen in Chatkanälen,
- Alarmierung via Pager Duty,
- Weiterleitung von Laufzeitmetriken an Graphite,
- Erzeugen von Logeinträgen zur Auswertung in Logstash.
Sensu unterscheidet die folgenden Arten von Eventhandlern:
- Pipe: Diese Art von Routine führt ein Systemkommando aus und übergibt ihm die Ereignisdaten via Stdin.
- TCP, UDP: Die beiden Arten schreiben Ereignisdaten in einen TCP- beziehungsweise UDP-Socket.
- Transport: Dieser Typ veröffentlicht Ereignisdaten erneut auf einem Sensu-internen Transportkanal, in aller Regel also Rabbit MQ.
- Gruppe: Eine Eventhandler-Gruppe (englisch “Set”) sendet die Ereignisdaten an eine Reihe von Eventhandlern. Wer lediglich einen einzelnen Eventhandler in eine Gruppe aufnimmt, definiert damit im Endeffekt einen Aliasnamen.
Wie einfach es ist, ein Monitoring-Ereignis in einem Eventhandler zu verarbeiten, zeigt Listing 9. Dieses einfache Ruby-Skript wird in »/etc/sensu/handlers/file.rb« abgelegt und nimmt Ereignisse im Json-Format entgegen, die es lesbar formatiert in Dateien schreibt. Konfiguriert wird der neue Eventhandler in »/etc/sensu/conf.d/handlers/default.json« als Pipe-Plugin (Listing 10).
Listing 10
Einbindung des Eventhandlers
01 ~~~Json
02 {
03 "handlers": {
04 "file": {
05 "type": "pipe",
06 "command": "/etc/sensu/handlers/file.rb"
07 }
08 }
09 }
10 ~~~
Listing 9
Eventhandler
01 ~~~ruby
02 #!/usr/bin/env ruby
03
04 require 'rubygems'
05 require 'Json'
06
07 # Read event data
08 event = Json.parse(STDIN.read, :symbolize_names => true)
09 # Write the event data to a file
10 file_name = "/tmp/sensu_#{event[:client][:name]}_" +
11 "#{event[:check][:name]}"
12 File.open(file_name, 'w') do |file|
13 file.write(Json.pretty_generate(event))
14 end
15 ~~~
Es mag zwar einfach sein, einen eigenen Eventhandler zu bauen, aber selbst diese Mühe darf sich der Admin in den meisten Fällen sparen. Die Sensu-Community hat auf Github ein umfangreiches Repository einsatzbereiter Plugins [6] gesammelt. Mehr als 600 Checks, Eventhandler und andere Sensu-Erweiterungen stehen hier zur Auswahl.
Wäre es nicht cool, wenn das Monitoring Störungen nicht nur erkennen und melden, sondern auch gleich beheben könnte?
Selbstheilung
Dem steht nichts im Wege! Einen Eventhandler zu schreiben, der beim Eintreten bestimmter Ereignisse geeignete Maßnahmen einleitet, ist nicht allzu schwer. Da dieser auf dem Sensu-Server läuft, die Störung aber auf einem Client aufgetreten ist, brauchen wir aber einen Mechanismus, der diese Kluft überbrückt.
Bei Freistilbox.com haben wir zunächst mit dem Remote-Execution-Tool Serf experimentiert. Ein cleverer Sensu-Anwender erkannte jedoch, dass es gar nicht nötig ist, zwei verschiedene Anwendungen zu verwenden, die letztlich beide ein eigenes Message-Passing-System nutzen, um Aktionen und Ereignisse von hier nach da zu transportieren. Diese Erkenntnis führte zu dem Sensu-Plugin »remediator« .
Mit diesem Plugin konnten wir einem Check eine dreistufige Behebungs-Strategie zuordnen. In jeder Stufe wird auf dem Client ein geeignetes Kommando ausgeführt, das Plugin zweckentfremdet dazu schlauerweise die Sensu-Checks. Im Beispiel (Listing 11) löst das Remediator-Plugin beim Eintreten eines »WARNING« -Status zunächst einen Reload aus. Bleibt der Status dennoch unverändert, versucht es stattdessen Restarts. Tritt sogar ein »CRITICAL« -Status ein, reagiert das System mit einem Reboot.
Listing 11
Selbstheilende Infrastruktur
01 ```Json
02 {
03 "checks": {
04 "check_foo": {
05 "command": "check-procs.rb ...",
06 "interval": 30,
07 "subscribers": ["application_server"],
08 "handlers": ["debug", "slack", "remediator"],
09 "remediation": {
10 "light_remediation": {
11 "occurrences": [1, 2],
12 "severities": [1]
13 },
14 "medium_remediation": {
15 "occurrences": ["3-5"],
16 "severities": [1]
17 },
18 "heavy_remediation": {
19 "occurrences": ["1+"],
20 "severities": [2]
21 }
22 }
23 },
24 "light_remediation": {
25 "command": "service foo reload",
26 "subscribers": [],
27 "handlers": ["debug"],
28 "publish": false
29 },
30 "medium_remediation": {
31 "command": "service foo restart",
32 "subscribers": [],
33 "handlers": ["debug", "slack"],
34 "publish": false
35 },
36 "heavy_remediation": {
37 "command": "sudo reboot",
38 "subscribers": [],
39 "handlers": ["debug", "slack"],
40 "publish": false
41 }
42 }
43 }
44 ```
Die drei Behebungs-“Checks” sind mit Absicht ohne Abonnenten definiert; das Plugin fordert immer den betroffenen Client dazu auf, sie auszuführen. Damit dies funktioniert, muss dieser ein Abonnement auf seinen eigenen Hostnamen haben (Listing 12).
Listing 12
Selbst-Abonnement
01 ```Json
02 {
03 "client": {
04 "name":"client1.example.com",
05 "address":"10.0.10.1",
06 "subscriptions":[
07 "all",
08 "test",
09 "client1.example.com"
10 ]
11 }
12 }
13 ```
Im täglichen Betrieb gibt sich Sensu sehr unauffällig – jedenfalls solange keine Störungen auftreten. Vor allem wenn man für die Alarmierung externe Dienste wie Pager Duty nutzt, hat man als Sysadmin kaum direkt mit Sensu zu tun. Und falls der Bedarf dazu besteht, ist die Interaktion mit dem Monitoring-System über das Web-Dashboard einfach und effizient. Hier darf der Admin Alarme quittieren oder über die Silence-Funktion auch mal für eine Weile stilllegen.
Wer einen mauslosen Umgang mit Sensu bevorzugt, findet in Sensu-CLI [7] das richtige Werkzeug. Auch diese Kommandozeilen-Anwendung kann Alarme quittieren (»sensu-cli resolve server3 apache_http« ) oder vorübergehend unterbinden (»sensu-cli silence server3 –reason “Shut up already” –expire 3600« ).
Da ein neuer Sensu-Client sich beim Server registriert, muss diese Registrierung wieder gelöscht werden, wenn es den Client nicht mehr gibt. Das vermeidet unnötige Alarme und ist einfach zu erledigen: »sensu-cli client delete server3« .
Chatops
Viele Unternehmen, besonders wenn ihre Mitarbeiter geografisch verteilt sind, nutzen Chat zur Team-Kommunikation. Wenn man die Meldungen des Teams noch mit Systemnachrichten anreichert, wird das Chatsystem zur zentralen Informationsquelle. So erfahren alle ohne Verzögerung von neuen Git-Commits oder Änderungen im Wiki und können sich an Ort und Stelle darüber austauschen. Da es für Sensu Eventhandler für alle gängigen Chatsysteme (IRC, Slack, Campfire und so weiter) gibt, lassen die sich einfach integrieren.
Der Quantensprung von der zentralen Informationsquelle zu Chatops lässt sich durch die Implementierung eines Rückkanals in Form eines Chatbot erzielen. Dieser Bot hat die Aufgabe, Anweisungen aus dem Chat entgegenzunehmen und daraufhin mit verschiedenen Ops-Diensten zu interagieren.
Der Klassiker unter den Chatbots ist Githubs Hubot [8], bei Freistilbox haben wir viel Spaß mit Lita [9]. Nicht nur können wir mit einem einfachen »pagerbot ack 1234« einen Alarm quittieren oder mit »pagerbot put me on firstlevel for 1 hour« schnell mal für einen Kollegen die Bereitschaft übernehmen, sondern wir kommunizieren diese Handlungen auch im selben Abwasch an den Rest des Teams.
Wer monitort den Monitor?
Aus eigener Erfahrung kann ich sagen, dass es ein herber Rückschlag ist, wenn man nach einigen Monaten voll »#monitoringlove« feststellen muss, dass seit Stunden Störungen unerkannt bleiben, weil Sensu klemmt. Deshalb ist es wichtig, auch die Funktion von Sensu selbst zu überwachen. Ein Check, für den ein einfacher Supervisor wie Monit genügt, sollte zum Beispiel prüfen, ob der zentrale Sensu-Serverprozess läuft. Ein weiterer Check sollte die Ready Queue in Rabbit MQ prüfen, um Verarbeitungsstaus zu erkennen.
Skalierung
Wir betreiben Sensu jetzt seit mehr als einem Jahr auf einem dedizierten Server mit gängiger Hardware und sehen keinerlei Bedarf nach zusätzlicher Kapazität. Obwohl die Infrastruktur unserer Managed-Hosting-Plattform stetig wächst, sehen wir nicht einmal ansatzweise jene heftig verzögerten Checks, wie wir sie mit Nagios auf vergleichbarer Hardware erlebten.
Allerdings verfüttern wir Laufzeitmetriken auch nach wie vor direkt vom Client aus an Graphite; würden wir Sensu als zentrale Metrik-Verteilstelle nutzen, würde der Verkehr auf dem Message-Bus sich sicherlich um Größenordnungen erhöhen. Vermutlich müssten wir uns dann aktiv dem Thema Skalierung widmen. Glücklicherweise ist Sensu auch dafür bestens aufgestellt.
Bei einer steigenden Anzahl von Ereignissen wird irgendwann der Sensu-Server als zentraler Umschlagplatz zum Leistungsengpass. Dieses Problem könnte nicht einfacher zu lösen sein: Man bindet einfach weitere Sensu-Server an Rabbit MQ und Redis an – fertig. Die Sensu-Server bestimmen automatisch untereinander die führende Instanz und teilen sich die Bearbeitung der Ereignisse auf – »#monitoringlove« !
Wer das Sensu-API so intensiv nutzt, dass es unter der Last zu ächzen beginnt, kann dem mit herkömmlichen Load-Balancing-Strategien begegnen, denn es ist ein einfaches, zustandsloses HTTP-Frontend. Für den Message-Bus existieren bewährte Ansätze zur Skalierung, die in der Cluster-Dokumentation für Rabbit MQ [10] beschrieben sind.
Diese Ansätze haben alle das Ziel der Leistungssteigerung. Wer darüber hinaus das gesamte Sensu-System hochverfügbar machen will, muss jede einzelne Komponente gesondert betrachten. Jean-Francois Theroux beschreibt das Vorgehen in [11].
Etwas komplexer wird es, wenn Sensu große Infrastrukturen überwachen soll, die über mehrere Standorte verteilt sind. Zunächst liegt natürlich der zentralistische Ansatz nahe (Abbildung 2). Alle Sensu-Clients führen ihre Checks lokal aus und liefern deren Ergebnisse über das WAN an den entfernten Message-Bus aus. Vorteilhaft sind dabei die einfache Architektur, die keinerlei zusätzliche Infrastruktur an den entfernten Standorten erfordert, sowie die zentrale Verarbeitung der Ereignisse.
Die intensive Nutzung der WAN-Verbindungen hat aber auch eine Schattenseite, es entsteht viel zusätzlicher Traffic. Eine instabile Netzwerkverbindung kann unter diesen Umständen leicht zu einer Flut von Host-down-Alarmen führen.
Eine Architektur mit verteilten Rabbit-MQ-Instanzen wie in Abbildung 3 kann besser gewährleisten, dass keine Ereignisse auf der (WAN-)Strecke bleiben. Für die Umsetzung stehen das Federation-Plugin [12] sowie das Shovel-Plugin [13] für Rabbit MQ zur Wahl.
Dieser Ansatz gibt innerhalb des CAP-Theorems den Eigenschaften Availability und Partition Tolerance den Vorzug gegenüber Consistency. Er bringt aber ebenfalls die Schwäche mit sich, dass Verbindungsprobleme zu Keepalive-Alarmen führen können. Dem lässt sich durch die Einrichtung von Check-Abhängigkeiten begegnen.
Betreibt jemand schließlich nicht nur den Message-Bus, sondern ein komplettes Sensu-System lokal an jedem Standort, fällt die Abhängigkeit von einer stabilen WAN-Verbindung weg. Dank der Tatsache, dass das Sensu-Dashboard den Zustand mehrerer Sensu-Installationen darstellen kann, bleibt eine gemeinsame Sicht auf den Gesamtzustand unserer Infrastruktur erhalten.
Abbildung 4 stellt diesen Aggregations-Ansatz grafisch dar. Seine Redundanz wird zwar mit einem etwas höheren Installationsaufwand erkauft, den können die Admins jedoch getrost einem Configuration Management System wie zum Beispiel Chef aufbürden.
Fazit
Abschließend können wir also festhalten: Sensu ist hervorragend für den Einsatz als zentrale Schaltstelle eines umfangreichen Monitoring-Systems geeignet. Das rührt daher, dass es einfach in Betrieb zu nehmen ist und sich dank der Nagios-Plugin-Schnittstelle existierende Checks einfach wiederverwenden lassen. Sensu unterstützt außerdem die Anbindung einer stetig wachsenden Anzahl externer Dienste. Aufgrund seiner Skalierbarkeit ist es auch für die Zukunft bestens gerüstet. Mit einem Wort: Das Hashtag »#monitoringsucks« hat nun endgültig ausgedient.
Infos
- Uchiwa: http://sensuapp.org/docs/latest/dashboards_uchiwa
- Sensu-Admin: https://github.com/sensu/sensu-admin
- Chef-Cookbook: https://github.com/sensu/sensu-chef
- Puppet-Modul: https://github.com/sensu/sensu-puppet
- Sensu-Shell-Helper: https://github.com/solarkennedy/sensu-shell-helper
- Sensu-Plugins: https://github.com/sensu/sensu-community-plugins
- Sensu-CLI: https://github.com/agent462/sensu-cli
- Hubot: https://github.com/sensu/sensu-hubot
- Lita: https://www.lita.io
- Rabbit MQ, Cluster-Doku: https://www.RabbitMQ.com/clustering.html
- Jean-Francois Theroux, “High availability monitoring with Sensu”: http://failshell.io/sensu/high-availability-sensu/
- Federation-Plugin: https://www.RabbitMQ.com/federation.html
- Shovel-Plugin: https://www.RabbitMQ.com/shovel.html









