From 73120869a7736a2e778089cec592bf95a37b1140 Mon Sep 17 00:00:00 2001 From: Micha Date: Sat, 30 May 2026 16:36:45 +0200 Subject: [PATCH] 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 --- docs/ALERTING_MAP.md | 3 + docs/ALERT_RULES.md | 151 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 docs/ALERT_RULES.md diff --git a/docs/ALERTING_MAP.md b/docs/ALERTING_MAP.md index b6b68b9..aa0f94c 100644 --- a/docs/ALERTING_MAP.md +++ b/docs/ALERTING_MAP.md @@ -4,6 +4,9 @@ Stand: 2026-05-23 Ziel: Alle problemrelevanten Homelab-Meldungen landen auf einem Handy-Topic. +> Die Prometheus-Alarmregeln im Detail (Trigger, Schwellen, Severity, +> Handlungshinweis, Luecken-Analyse) stehen in `docs/ALERT_RULES.md`. + ## ntfy Topics | Topic | Zweck | diff --git a/docs/ALERT_RULES.md b/docs/ALERT_RULES.md new file mode 100644 index 0000000..23a2347 --- /dev/null +++ b/docs/ALERT_RULES.md @@ -0,0 +1,151 @@ +# 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 7–21 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 3–4s-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: + + ```yaml + - 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): + + ```yaml + - 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 + +3. **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. +4. **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-Verschleiss** → `check_nvme_smart` im Posture-Check (ntfy direkt). +- **Compose-Runtime-Drift / Authelia-Drift** → Posture-Check (ntfy direkt). +- **Docker `oom`/`die`/`kill`** → `docker-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-Ablauf** → `cert-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.