Files
homelab-infra/docs/ALERT_RULES.md
T
Micha 73120869a7 docs: zentrale ALERT_RULES.md + Luecken-Analyse
Nachschlagetabelle aller Prometheus-Alarmregeln (Trigger/Schwelle/Severity/
Aktion) plus Bewertung der Abdeckung. Identifiziert zwei echte blinde Flecke
(kein up==0 Target-Down, kein Disk-Critical-Tier) mit fertigem PromQL als
Empfehlung. Cross-Ref aus ALERTING_MAP.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 16:36:45 +02:00

7.9 KiB
Raw Blame History

Alert Rules

Stand: 2026-05-30

Zentrale Nachschlagetabelle aller Prometheus-Alarmregeln plus Bewertung, ob die Abdeckung sinnvoll und vollstaendig ist.

  • Authoritative Quelle der Regeln: monitoring/prometheus/alerts.yml
  • Topic-/Sender-Konvention: docs/ALERTING_MAP.md
  • Alle Prometheus-Alarme laufen ueber Alertmanager → monitoring/alertmanager-ntfy-bridge/bridge.py → ntfy-Topic homelab-alerts.

Diese Datei ist Doku, nicht die Konfiguration. Wer eine Regel aendert, aendert monitoring/prometheus/alerts.yml, pusht nach Gitea und laesst Komodo deployen bzw. Prometheus neu laden. Danach diese Tabelle nachziehen.

Zwei Alarm-Pfade nebeneinander

Nicht jeder Homelab-Alarm kommt aus Prometheus. Wer "fehlt da was?" beantworten will, muss beide Pfade zusammen lesen:

Pfad Quelle Beispiele
Prometheus / Alertmanager monitoring/prometheus/alerts.yml Erreichbarkeit, Zertifikate, Disk/RAM, Borg-Metriken, Critical-Container
Posture-Check / ntfy-direkt services/posture-check/* NVMe-SMART, Cert/Token-Check, Compose-Runtime-Drift, Docker die/oom/kill, Authelia-Drift, Borg-Pre-Hook, Restore-Jobs

Beide enden auf homelab-alerts. Der Posture-Pfad ist in docs/ALERTING_MAP.md tabelliert; er wird hier nur referenziert, nicht dupliziert.

Prometheus-Regeltabelle

Severity-Routing der Bridge: critical und warning gehen beide auf homelab-alerts (kein eigenes Topic je Severity).

Gruppe homelab-availability

Alarm Trigger (PromQL, gekuerzt) Schwelle / for Severity Was tun
HomelabExternalConnectivityDown sum(probe_success{blackbox-http}==0) >= 5 ≥5 Endpunkte / 8m warning WAN/DNS/Provider pruefen, nicht pro Domain jagen — Sammelausfall
HomelabEndpointDown probe_success==0 (einzeln, nicht im Sammelausfall) 1 Endpunkt / 8m critical Betroffenen Dienst/Traefik-Route pruefen
HomelabEndpointSlow probe_duration_seconds > 5 >5s / 5m warning Dienst-/Backend-Last pruefen, oft transient
HomelabCertificateExpiresSoon Restlaufzeit 721 Tage <21d & >7d / 30m warning ACME/Traefik-Renewal beobachten
HomelabCertificateExpiresCritical Restlaufzeit ≤7 Tage (oder abgelaufen) ≤7d / 15m critical Renewal sofort erzwingen/pruefen

Gruppe homelab-host

Alarm Trigger (PromQL, gekuerzt) Schwelle / for Severity Was tun
HomelabDiskAlmostFull 100*(1-avail/size) > 85 (ohne tmpfs/overlay) >85% / 10m warning Mountpoint aufraeumen / erweitern
HomelabHighMemoryUsage 100*(1-MemAvailable/MemTotal) > 90 >90% / 10m warning Speicherfresser identifizieren, ggf. Container-Limit (F-19)
HomelabTraefik5xx increase(traefik_service_requests_total{5..}[5m]) >= 5 je Service ≥5 / 2m warning Backend des betroffenen Service pruefen

Gruppe homelab-backup-and-containers

Alarm Trigger (PromQL, gekuerzt) Schwelle / for Severity Was tun
HomelabTextfileExporterStale time()-last_run > 2h >2h / 15m warning export-prometheus-textfile.sh-Cron auf Host pruefen
HomelabBorgMetricsMissing absent(borg_last_completed_ts) fehlt / 15m critical Textfile-Export oder borg-ui pruefen
HomelabBorgBackupStale time()-borg_last_completed_ts > 30h >30h / 15m warning Letztes Borg-Backup nachholen/pruefen
HomelabBorgLastJobFailed borg_last_success != 1 ≠1 / 15m critical Borg-UI-Job-Log pruefen, Backup wiederholen
HomelabBorgLastJobCompletedWithWarnings borg_last_job_warning == 1 =1 / 15m warning Warnung im Borg-UI-Job lesen
HomelabCriticalContainerDown homelab_critical_container_running == 0 =0 / 5m critical Container neu starten / Komodo-Stack pruefen (name-Label)

Die Liste der ueberwachten Critical-Container steht in services/posture-check/export-prometheus-textfile.sh (CRITICAL_CONTAINERS).

Bewertung: Sind die Alarme sinnvoll?

Insgesamt solide. Die Erreichbarkeits-Gruppe ist gut entworfen — der Sammelausfall-Trick (>=5 Endpunkte als ein Warning, Einzelausfall als Critical) verhindert eine ntfy-Flut bei kurzen DSL-Reconnects. Borg ist mit vier Regeln (fehlende Metrik, veraltet, fehlgeschlagen, mit Warnungen) gut abgedeckt.

Anmerkungen / Feinschliff (kein Handlungsdruck):

  • HomelabDiskAlmostFull ohne Array-Filter. Der fstype!~"tmpfs|overlay"- Filter schliesst keine bewusst vollen Unraid-Array-Disks aus. Eine Datengrab-Disk, die dauerhaft bei 90 % liegt, erzeugt einen Dauer-Warning. Bei Bedarf per mountpoint-Filter auf die wirklich kritischen Pfade (/, appdata-/services-Cache) eingrenzen.
  • HomelabEndpointSlow >5s ist grosszuegig und damit eher ruhig — okay als bewusste Wahl, faengt aber keine schleichende 34s-Degradierung.
  • HomelabHighMemoryUsage 90 % ist auf einem Host mit ZFS/Unraid-Cache schnell erreicht (Cache zaehlt nicht als „available" je nach Messung); die Verwendung von MemAvailable ist hier korrekt und mildert das.

Bewertung: Fehlt etwas? (Luecken, priorisiert)

Hoch — echter blinder Fleck

  1. Kein up == 0 auf Scrape-Targets. Faellt node-exporter, cadvisor, blackbox-exporter oder traefik als Scrape-Ziel aus, verschwinden die zugehoerigen Metriken still — und mit ihnen die darauf gebauten Alarme. Nur der Textfile-Pfad ist ueber BorgMetricsMissing / TextfileExporterStale abgesichert, der Rest nicht. Empfohlen:

    - alert: HomelabPrometheusTargetDown
      expr: up == 0
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "Prometheus target down: {{ $labels.job }} / {{ $labels.instance }}"
        description: "Scrape target {{ $labels.instance }} (job {{ $labels.job }}) is unreachable."
    
  2. Kein Disk-Critical-Tier. Nur ein Warning bei 85 %, kein Critical bei ~95 %. Eine volllaufende Cache-/appdata-Disk blockiert Schreibzugriffe und damit DB-Writes — fuer Familien-Nutzung teurer als nur Operator-Zeit. Empfohlen (eng auf kritische Pfade gefiltert):

    - alert: HomelabDiskCritical
      expr: 100 * (1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) > 95
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "Disk critically full on {{ $labels.mountpoint }}"
        description: "{{ $labels.mountpoint }} is above 95% used."
    

Mittel — sinnvoll, aber kein Notstand

  1. Dead-Man's-Switch. Faellt Prometheus oder die ntfy-Bridge selbst aus, feuert gar kein Alarm — strukturell blind. Eine immer feuernde Watchdog-Regel plus externer „Heartbeat fehlt"-Waechter (z. B. Uptime-Kuma Push-Monitor oder Healthchecks.io) schliesst die Luecke. Bewusst leichtes Gewicht, weil Posture-Check/Borg-Pre-Hook teilweise unabhaengig laufen.
  2. Inode-Erschoepfung. Paperless/Immich erzeugen viele kleine Dateien; node_filesystem_files_free kann vor dem Byte-Limit knapp werden. Niedrige Wahrscheinlichkeit, billiger Alarm.

Bewusst nicht in Prometheus (anderer Pfad deckt ab)

  • NVMe-SMART-Verschleisscheck_nvme_smart im Posture-Check (ntfy direkt).
  • Compose-Runtime-Drift / Authelia-Drift → Posture-Check (ntfy direkt).
  • Docker oom/die/killdocker-critical-events.sh (ntfy direkt) — dies ist auch der Detektionspfad fuer den ersten echten OOM-Vorfall, der F-19 (Container-Memory-Limits) ausloesen wuerde.
  • Cert/Token-Health jenseits TLS-Ablaufcert-token-check.sh.

Empfehlung

Die zwei Hoch-Luecken (up == 0 Target-Down und Disk-Critical) sind der lohnendste naechste Schritt: wenige Zeilen, schliessen einen echten blinden Fleck und kosten keine Laufzeit. Umsetzung bewusst als eigener Aenderungsblock, weil sie monitoring/prometheus/alerts.yml aendert und damit einen Prometheus-Reload/Komodo-Deploy nach sich zieht.