Linuxfabrik Monitoring Plugins: Behind the Scenes

icinga monitoring-plugins

Wer Infrastruktur- oder Application-Monitoring betreibt, will im Kern drei Dinge: einen schnellen, skalierbaren Core, der Checks ausführt, Statuswechsel verarbeitet und Notifications verschickt. Eine Sammlung von Check-Plugins. Ein Werkzeug zur Visualisierung der Performance-Daten. Dieser Beitrag handelt vom mittleren Stück und davon, warum und wie wir die Linuxfabrik Monitoring Plugins gebaut haben.

Den ersten Punkt löst Icinga. Den dritten typischerweise Grafana auf einer Zeitreihen-Datenbank wie InfluxDB oder Prometheus.

Der mittlere Punkt ist in der Praxis schwierig und aufwändig. Das Icinga-Projekt liefert ab Werk keine Check-Plugins mit, daher greifen viele zur klassischen Sammlung Monitoring Plugins (früher Nagios Plugins). Das hat Konsequenzen.

Was sollte man eigentlich überwachen?

Wenn man sich einen minimalen Linux-Server vorstellt, sind das die Metriken, die für höhere Uptime und einfacheres Troubleshooting wirklich helfen:

  • CPU-Stats: user, system, iowait, idle (Prozentwerte).
  • Memory: used, buffered, cached, free (Prozentwerte).
  • Disk-I/O: Operationen und Bytes pro Zeiteinheit.
  • Freier Speicher auf den lokalen Mounts.
  • File-Descriptors gegen das System-Limit.
  • TCP-Verbindungen pro Status (ESTABLISHED, CLOSE_WAIT, TIME_WAIT, ...).
  • Netzwerk-I/O: empfangene und gesendete Bytes.
  • Netzwerk-Latenz.

Schwächen der klassischen Monitoring Plugins

Von den oben genannten Metriken bekommt man ab Werk vielleicht zwei: freien Speicher auf Mounts und irgendeine Form von Netzwerk-Latenz. Daneben jede Menge Plugins für Nischen wie Signal-Stärke spezieller WLAN-Geräte, Game-Server oder Novell NetWare.

Wer genauer hinschaut, sieht: Die Plugins sind in drei verschiedenen Sprachen geschrieben (C, Shell, Perl), unterschiedlich alt, unterschiedlich gepflegt, und sie unterscheiden sich in Parametern, Verhalten und Output. Die Abhängigkeiten der vollständigen Sammlung sind nicht trivial: auf einer schlanken Basis-Installation kann das Plugin-Paket umfangreicher sein als der Icinga-Core selbst.

Die Suche nach einem Ersatz

Ausserhalb der klassischen Sammlung wird's nicht besser. Im Datacenter-Umfeld gibt es Tausende One-Shot-Plugins, die vor Jahren mit sehr spezifischen Feature-Sets veröffentlicht wurden, oft ohne sauberes Error-Handling, dazu in noch mehr Sprachen (Ruby, Go), was wiederum zusätzliche Abhängigkeiten bedeutet.

Die Konsequenz: eine eigene Sammlung

Nach Jahren mit Patches und selbstgeschriebenen Plugins haben wir eine neue Sammlung von Grund auf gebaut, mit ein paar Grundregeln:

  • Sammle alle Metriken, die beim Troubleshooting helfen.
  • Alarmiere nur dort, wo eine Aktion wirklich nötig ist.
    • WARN: etwas muss getan werden, kein Grund für einen Herzinfarkt.
    • CRIT: nur dort, wo jemand nachts aufstehen und sofort reagieren muss.
  • Konfigurations-Aufwand minimieren.

Was wir von jedem Plugin verlangen

Bevor wir das Projekt gestartet haben, haben wir die Design-Regeln festgehalten:

  • Fokus auf Icinga und Nagios.
  • Fokus auf das Red Hat-Ökosystem (Perspektive "minimaler Server"), aber offen für Debian, Ubuntu und andere.
  • Sprache: Python.
  • Schnelle und zuverlässige Ausführung.
  • Einheitliches Verhalten: ein "used"-Wert bedeutet in jedem Plugin dasselbe, der Output ist knapp und präzise.
  • Wo immer möglich self-configuring oder mit Auto-Detection und sinnvollen Defaults, sodass der Standardaufruf ohne Parameter funktioniert.
  • Genug Metriken, um Troubleshooting zu unterstützen, nicht nur "OK / NOT OK".
  • Drittabhängigkeiten vermeiden, wenn möglich, weil exotische Libraries in einem heterogenen Datacenter Aufwand bedeuten.
  • Public Domain (UNLICENSE).

Gemeinsame Funktionen liegen in unserer eigenen Python-Library, die von den Plugins benutzt wird.

Einige Konzepte aus der Sammlung

Host Aliveness

Oft wird noch das alte check_ping zur Lebenszeichen-Prüfung von Hosts benutzt. Das Plugin ist jedoch stark limitiert. Weil andere Services und nachgelagerte Hosts vom Host-Status abhängen, muss ein Ping-Plugin zuverlässig und tolerant sein. Unser ping ist genau das:

  • Wenn 4 von 5 Paketen verloren gehen (oder 99 von 100), ist der Host immer noch erreichbar. Solange ein einziges Paket durchkommt: OK.
  • Warn-Schwellen auf Paket-Verlustraten ergeben für reine Aliveness-Prüfung keinen Sinn.

Unser ping-Plugin ist zudem schnell: es schickt im Default fünf Pings innerhalb einer Sekunde, was zu der kürzesten Laufzeit unter den von uns gemessenen Ping-Checks führt.

Zeitperioden statt Flapping

Stellt man sich einen CPU-Usage-Check vor, der 100 % meldet (CRIT), dann 20 % (OK), dann 90 % (CRIT), bekommt man ohne Zeit-Fenster permanentes Flapping, und niemand vertraut den Status-Wechseln mehr. Besser: erst alarmieren, wenn die Schwelle eine konfigurierbare Zeit lang überschritten war, vergleichbar mit Prometheus' for: 5m. Umgesetzt beispielsweise in cpu-usage, disk-io, network-io, procs, docker-stats, podman-stats, php-fpm-status sowie in plattformspezifischen Varianten wie fortios-cpu-usage, fortios-network-io, fortios-ha-stats und qts-cpu-usage.

Bestehendes nicht neu erfinden, sondern portieren

Bevor wir ein neues Plugin schreiben, schauen wir auf die bestehenden Monitoring Plugins, auf existierende Tools, die den Job heute schon machen, oder direkt auf den Linux-Kernel, und übertragen die Ideen in das Monitoring-Plugins-Projekt. Beispiele:

Mit Icinga kommunizieren (Acknowledgement als Bestätigung)

Manchmal will man über etwas informiert werden, ohne dass es ein echter Fehler ist, etwa über ein neues GitHub-Release oder einen Security-Hinweis. Nagios und Icinga kennen keinen NOTICE-State, also simulieren wir ihn:

  1. Neues Ereignis: das Plugin liefert WARN.
  2. Der Operator acknowledged das Warning ("Verstanden").
  3. Beim nächsten Lauf fragt das Plugin den Acknowledgement-Status über die Icinga-API ab.
  4. Bei acknowledged liefert das Plugin wieder OK, bis sich der Befund ändert.

Umgesetzt beispielsweise in feed, journald-query, logfile und librenms-alerts.

Application-Updates prüfen

Wenn man lokal installierte Software gegen externe Quellen vergleicht (GitHub-Releases, Hersteller-Channels), gehört es zum guten Ton, diese Quellen nicht jede Minute abzufragen. Selbst wenn der Check minütlich läuft, muss er einen lokalen Cache nutzen, um den externen Traffic zu minimieren. Umgesetzt beispielsweise in matomo-version, nextcloud-version (verwendet die offiziellen Nextcloud-Update-Channels statt GitHub) und rocketchat-version.

systemd-unit als Schweizer Taschenmesser

Das Plugin systemd-unit ersetzt eine Reihe von Legacy-Plugins für Services, Sockets, Mounts, Geräte, Timer und Scopes. Einige der Fragen, die das Plugin beantwortet:

  • Existiert die Unit?
  • Läuft der Service?
  • Ist der Service gestoppt und disabled?
  • Ist die Service-Instanz mit dem speziellen Namen aktiv?
  • Ist die Unit maskiert?
  • Lauscht ein Socket?
  • Ist ein Pfad gemountet?
  • Ist ein Gerät eingesteckt?
  • Was ist der aktuelle Status eines Timers?
  • Was ist der Status eines Services, der von einem Timer abhängt?
  • Läuft die Unit in einem lokalen Container (--machine)?
  • Läuft die Unit auf User-Ebene (--user)?

Debugging und Troubleshooting

Plugins, die helfen, die Quelle zu finden, statt nur zu signalisieren, dass es ein Problem gibt:

  • about-me: Sammel-Übersicht zu Host, Distribution, Uptime, Load und vielem mehr.
  • procs: filtert Prozesse per Regex (Name, Argument, Benutzer) und liefert mit --top die n grössten nach CPU-Zeit oder Memory; --lengthy ergänzt die Tabelle um alle plattformspezifischen memory_info()-Felder.
  • dmesg: meldet Kernel-Ring-Buffer-Einträge ab Severity err und filtert bekannte Hardware-Geräusche heraus.

Plattformen und Bezug

Die Plugins laufen auf jeder Plattform mit Python 3.9+ (Linux, Windows, macOS, FreeBSD). Für Windows liefern wir zusätzlich vorkompilierte Binaries aus, sodass auf dem Zielsystem keine Python-Installation nötig ist.

Beim Update immer ein offizielles Release verwenden.

Entwicklungs-Standards

Ein paar Konventionen halten die Plugins konsistent:

  • EAFP: easier to ask for forgiveness than permission.
  • PEP 8 als Coding-Style, durchgesetzt von ruff format.
  • Docstrings auf den Library-Funktionen.
  • pylint läuft ohne --disable-Flags: der Code soll den vollständigen Linter erfüllen, nicht nur eine kuratierte Teilmenge.
  • Unit-Tests für jedes Plugin, soweit möglich.

Die Details stehen in den Contributing Guidelines.

Wir helfen dir

Brauchst du Unterstützung beim Aufbau oder Betrieb deines Icinga-Monitorings? Schau dir doch mal unsere Icinga Subscriptions und Service & Support-Modelle an und melde dich bei uns.

Nächster Beitrag

DE · EN