Prometheus Alerting-Regeln schreiben 2026 – Praxis-Guide

Warum Alerting-Regeln 2026 anders gebaut werden

Zwischen 2019 und 2022 war Alerting in vielen Teams ein Sammelbecken für Schwellenwerte: CPU über 80 %, RAM über 90 %, irgendein HTTP-Statuscode ungleich 200. Das Ergebnis waren Alert-Fatigue, schlafende Bereitschaftsdienste und ein Monitoring, dem niemand mehr vertraute. 2026 hat sich der Konsens durchgesetzt: Alerts müssen Symptome beschreiben, nicht Ursachen. Ein Nutzer interessiert sich nicht für die CPU-Last eines Nodes, sondern dafür, ob seine Anfrage in unter 300 ms beantwortet wird.

Dieser Guide zeigt dir, wie du Prometheus-Alerting-Regeln baust, die tatsächlich handlungsrelevant sind. Wir gehen von Prometheus 3.x aus (aktuell 3.5 im Frühjahr 2026), dem Prometheus Operator 0.80+, Alertmanager 0.28+ und einer Umgebung mit mindestens 50 Targets. Alle Beispiele sind copy-paste-fähig und laufen gegen einen Standard-Node-Exporter plus kube-state-metrics.

Die zentrale Verschiebung: Statt Threshold-Alerting auf Einzelmetriken nutzen moderne Setups SLO-basiertes Alerting mit Multi-Window-Multi-Burn-Rate, ergänzt durch eine kleine Zahl technischer Grundwächter (Node down, Certificate expiry, Disk full). Faustregel für 2026: maximal 15 aktive Alert-Regeln pro Service. Wer 80 hat, hat keine Priorisierung.

Der Aufwand lohnt sich messbar. Teams, die von 120 auf 12 Regeln konsolidiert haben, berichten in Postmortems von 60–80 % weniger Page-Nachrichten pro Woche bei gleichzeitig höherer Erkennungsrate echter Incidents. Das ist der eigentliche Gewinn: Signal-to-Noise.

Die Anatomie einer Prometheus-Rule-Datei

Alerting-Regeln liegen in YAML-Dateien, die Prometheus über rule_files lädt oder die der Prometheus Operator aus PrometheusRule-CRDs generiert. Eine Regel hat immer dieselbe Struktur: alert, expr, for, labels, annotations. Fehlt for, feuert der Alert sofort – das ist in 90 % der Fälle ein Fehler.

groups:
  - name: api-slo.rules
    interval: 30s
    rules:
      - alert: ApiHighErrorRate
        expr: |
          sum(rate(http_requests_total{job="api",code=~"5.."}[5m]))
          /
          sum(rate(http_requests_total{job="api"}[5m])) > 0.05
        for: 10m
        keep_firing_for: 5m
        labels:
          severity: critical
          team: platform
          slo: availability
        annotations:
          summary: "API-Fehlerrate bei {{ $value | humanizePercentage }}"
          description: "Seit 10 Minuten über 5 % 5xx auf {{ $labels.job }}."
          runbook_url: "https://wiki.example.com/runbooks/api-5xx"

Das Feld interval auf Gruppenebene steuert, wie oft die Regel ausgewertet wird. Standard ist das globale evaluation_interval (meist 15s oder 30s). Für SLO-Regeln mit langen Lookback-Fenstern kannst du auf 60s erhöhen und sparst damit bei 500 Regeln rund 40 % CPU-Last auf dem Prometheus-Server.

keep_firing_for ist seit Prometheus 2.42 stabil und 2026 Standard: Der Alert bleibt nach Wegfall der Bedingung noch für die angegebene Dauer aktiv. Das verhindert das nervige An-Aus-Flackern bei Metriken, die um einen Schwellenwert pendeln – ohne dass du for künstlich hochsetzen musst.

Wichtig für die Wartbarkeit: Gruppiere Regeln nach Domäne (api-slo.rules, node-basics.rules, kubernetes.rules) und halte eine Datei unter 200 Zeilen. Bei Git-Merges mit 2000-Zeilen-Dateien verliert man garantiert den Überblick.

PromQL-Muster, die du wirklich brauchst

Die meisten produktiven Alerts lassen sich auf sechs PromQL-Muster zurückführen. Wer diese beherrscht, braucht kein weiteres Framework.

Ein häufiger Fehler: rate() über ein Fenster, das kürzer als 2× das Scrape-Intervall ist. Bei 30s-Scrape brauchst du mindestens [1m], besser [5m]. Sonst produziert Prometheus Lücken und dein Alert flappt.

Für Sättigungs-Alerts gilt: Nutze immer predict_linear statt eines fixen Prozent-Schwellwerts. „Disk 85 % voll" ist kein Incident, wenn die Disk seit drei Monaten bei 85 % liegt. „Disk voll in 4 Stunden" ist einer.

- alert: DiskWillFillIn4Hours
  expr: |
    predict_linear(node_filesystem_avail_bytes{
      fstype!~"tmpfs|overlay", mountpoint!~"/run/.*"
    }[6h], 4 * 3600) < 0
  for: 15m
  labels:
    severity: warning
  annotations:
    summary: "Disk {{ $labels.device }} auf {{ $labels.instance }} voll in <4h"

for-Dauern richtig wählen

Die for-Dauer ist der wichtigste Hebel gegen Alert-Fatigue – und der, den Teams am häufigsten falsch setzen. Sie sollte mindestens so lang sein wie die typische Dauer eines harmlosen Spikes, aber kürzer als dein SLO-Budget es erlaubt.

Alert-TypEmpfohlenes forBegründung
Node down / up == 02mSchnelle Erkennung, selten False Positives
5xx-Rate > 5 %10mDeployments brauchen ~5 min zum Einpendeln
p99-Latenz > SLO15mCache-Warmup, GC-Pausen
Disk voll in 4h30mVorhersage ist verrauscht
Zertifikat läuft ab1hReaktion hat Tage Zeit
Queue-Backlog20mBatch-Jobs erzeugen kurze Spitzen

Ein oft übersehener Punkt: for zählt ab dem Zeitpunkt, an dem die Bedingung durchgehend wahr war. Ein einzelner Ausreißer-Scrape setzt den Timer zurück. Deshalb ist for allein kein Schutz gegen Rauschen – dafür brauchst du stabile PromQL-Ausdrücke mit ausreichend langen Rate-Fenstern.

Kombiniere beides: rate(...[5m]) glättet das Signal, for: 10m filtert kurze echte Incidents aus, keep_firing_for: 5m verhindert Flapping beim Recovery. Diese Dreier-Kombination deckt 80 % aller Fälle ab.

Recording Rules als Fundament

Alerting-Regeln sollten niemals komplexe PromQL direkt ausführen. Der Grund: Bei 200 Regeln mit je 30s-Intervall und 5-Minuten-Rate-Fenstern rechnet Prometheus dieselben Aggregationen dutzendfach. Recording Rules berechnen sie einmal und speichern das Ergebnis als neue Zeitreihe.

groups:
  - name: slo-recording.rules
    interval: 30s
    rules:
      - record: job:http_requests:rate5m
        expr: sum by (job) (rate(http_requests_total[5m]))
      - record: job:http_errors:rate5m
        expr: sum by (job) (rate(http_requests_total{code=~"5.."}[5m]))
      - record: job:http_error_ratio:rate5m
        expr: job:http_errors:rate5m / job:http_requests:rate5m

Die Namenskonvention level:metric:operation ist 2026 De-facto-Standard (ursprünglich von Google SRE geprägt). job:http_error_ratio:rate5m liest sich als „auf Job-Ebene, Metrik http_error_ratio, Operation rate über 5 Minuten". Das macht Dashboards und Alerts sofort verständlich.

Der Performance-Effekt ist erheblich. In einem Setup mit 1,2 Mio. aktiven Series sank die Prometheus-CPU-Last nach Einführung von Recording Rules für alle SLO-Berechnungen um 35 %, und die Abfragezeit im Grafana-Dashboard fiel von 2,4 s auf 180 ms. Der Preis: zusätzliche Series im TSDB. Rechne mit 5–15 % mehr Series – bei 1,2 Mio. also 60.000–180.000 zusätzliche Zeitreihen.

Für die Speicherplanung: Prometheus braucht grob 1,5–2 Bytes pro Sample. Bei 1,4 Mio. Series und 30s-Scrape sind das rund 4 GB pro Tag, mit 15 Tagen Retention also ~60 GB. Auf einem Hetzner CPX31 (4 vCPU, 8 GB RAM, 160 GB NVMe, ca. 15,60 €/Monat) passt das komfortabel.

SLO-Alerting mit Multi-Window-Multi-Burn-Rate

Das wichtigste Alerting-Muster 2026 ist Multi-Window-Multi-Burn-Rate (MWMBR). Statt „Fehlerrate über 1 %" alarmierst du auf den Verbrauch deines Fehlerbudgets. Ein 99,9 %-SLO erlaubt 43,2 Minuten Ausfall pro Monat. Ein Burn-Rate-Alert feuert, wenn du dieses Budget ungewöhnlich schnell aufbrauchst.

Die Mathematik: Burn Rate 1 = Budget wird exakt über den SLO-Zeitraum verbraucht. Burn Rate 14,4 = Budget ist in 2 Tagen weg (bei 30-Tage-Fenster). Die klassische Tabelle:

SeverityLong WindowShort WindowBurn RateBudget verbraucht
critical (page)1h5m14,42 % in 1h
critical (page)6h30m65 % in 6h
warning (ticket)1d2h310 % in 1d
warning (ticket)3d6h110 % in 3d

Der Trick: Beide Fenster müssen gleichzeitig die Burn Rate überschreiten. Das lange Fenster verhindert Fehlalarme bei kurzen Spitzen, das kurze Fenster sorgt für schnelle Reaktion und schnelles Zurücksetzen. Ohne das kurze Fenster bleibt ein Alert nach Recovery noch eine Stunde aktiv.

- alert: SLOAvailabilityBurnRateCritical
  expr: |
    (
      job:slo_availability:error_ratio_rate1h{job="api"} > (14.4 * 0.001)
      and
      job:slo_availability:error_ratio_rate5m{job="api"} > (14.4 * 0.001)
    )
  for: 2m
  labels:
    severity: critical
    slo: availability
    team: platform
  annotations:
    summary: "API verbrennt Fehlerbudget 14,4x schneller als erlaubt"
    description: "2 % des 30-Tage-Budgets in der letzten Stunde verbraucht."

Für die Recording Rules brauchst du je SLO vier Zeitreihen (1h, 5m, 6h, 30m) plus die langen Fenster für Tickets. Das sind bei 20 Services etwa 200 zusätzliche Series – vernachlässigbar. Der Gewinn: Dein Pager bleibt still, solange du innerhalb des Budgets bist, auch wenn die Fehlerrate kurzzeitig über einem willkürlichen Schwellwert liegt.

Labels, Annotations und Alert-Qualität

Ein Alert ohne Kontext ist eine Zumutung für den Bereitschaftsdienst um 3 Uhr nachts. Die Annotations sollten in 10 Sekunden beantworten: Was ist kaputt, wie schlimm, was ist der erste Schritt?

Bei Labels gilt: sparsam sein. Jedes Label wird zu einem Routing-Kriterium und zu einem Gruppierungsschlüssel im Alertmanager. Zu viele Labels führen zu Alert-Stürmen, weil nichts mehr gruppiert wird. Bewährte Minimalmenge: severity, team, service oder job, optional slo. Finger weg von instance als Routing-Label – das erzeugt bei 100 Nodes 100 separate Alerts.

Ein Anti-Pattern, das 2026 immer noch häufig ist: severity: warning für alles, was nicht sofort weh tut. Besser ist eine Dreiteilung: critical (weckt jemanden auf), warning (Ticket am nächsten Morgen), info (nur Dashboard/Slack, kein Routing). Ohne diese Disziplin wird dein #alerts-Kanal zur Rauschquelle und die Leute muten ihn – was schlimmer ist als kein Alerting.

Alertmanager: Routing, Grouping, Inhibition

Der Alertmanager entscheidet, wer wann wie oft benachrichtigt wird. Drei Konzepte sind entscheidend.

Grouping fasst Alerts mit gleichen Labels zu einer Nachricht zusammen. Typische Konfiguration: group_by: [alertname, cluster, service] mit group_wait: 30s, group_interval: 5m, repeat_interval: 4h. Ein repeat_interval von 15 Minuten – in vielen Alt-Setups Standard – ist Folter für den Bereitschaftsdienst.

Routing verteilt Alerts anhand von Labels auf Receiver. Ein Routing-Baum mit drei Ebenen (severity → team → service) reicht fast immer. Nutze continue: false explizit, damit klar ist, dass der erste Match gewinnt.

Inhibition unterdrückt abhängige Alerts. Wenn ein Node down ist, brauchst du nicht zusätzlich 40 Pod-NotReady-Alerts. Eine Inhibitionsregel mit equal: [node, cluster] und source_matchers: [alertname="NodeDown"] erledigt das.

inhibit_rules:
  - source_matchers: [severity="critical"]
    target_matchers: [severity=~"warning|info"]
    equal: [alertname, cluster, service]
  - source_matchers: [alertname="NodeDown"]
    target_matchers: [alertname=~"KubePodNotReady|TargetDown"]
    equal: [node, cluster]

Für die Zustellung: E-Mail hat 2026 in den meisten Teams ausgedient. Slack oder Mattermost für warning, PagerDuty oder Opsgenie für critical. PagerDuty kostet ab 21 $ pro Nutzer/Monat (Professional), Opsgenie ab 9 $ – bei 8 Bereitschaftlern sind das 72–168 $ monatlich. Open-Source-Alternativen wie Grafana OnCall (self-hosted auf einem 4-€-VPS) sind für kleinere Teams völlig ausreichend.

Tests mit promtool und CI/CD

Alerting-Regeln sind Code und gehören getestet. promtool liefert zwei Werkzeuge: Syntaxprüfung und Unit-Tests mit simulierten Zeitreihen.

# Syntax + Semantik prüfen
promtool check rules /etc/prometheus/rules/*.yaml

# Unit-Tests ausführen
promtool test rules tests/api-slo_test.yaml

Ein Unit-Test definiert Eingabe-Series, einen Zeitverlauf und die erwarteten Alerts. Damit kannst du reproduzieren: „Fehlerrate steigt für 12 Minuten auf 8 % → ApiHighErrorRate feuert nach 10 Minuten."

rule_files:
  - ../rules/api-slo.yaml
evaluation_interval: 1m
tests:
  - interval: 1m
    input_series:
      - series: 'http_requests_total{job="api",code="200"}'
        values: '0+600x20'
      - series: 'http_requests_total{job="api",code="500"}'
        values: '0+60x20'
    alert_rule_test:
      - eval_time: 15m
        alertname: ApiHighErrorRate
        exp_alerts:
          - exp_labels:
              severity: critical
              team: platform
            exp_annotations:
              summary: "API-Fehlerrate bei 9.09%"

Der Test läuft in unter 200 ms und gehört in jede CI-Pipeline. Ein GitHub-Actions-Workflow mit promtool check rules plus promtool test rules kostet nichts und fängt Tippfehler, falsche Label-Matcher und kaputte PromQL ab, bevor sie den Produktiv-Prometheus erreichen.

Ergänzend lohnt sich pint (Prometheus Linter von Cloudflare) für Stilprüfungen: Es erkennt zu kurze for-Dauern, fehlende severity-Labels, unnötig teure PromQL-Konstrukte und Alert-Namen, die nicht der Konvention PascalCase folgen. In einem Testlauf über 340 Regeln fand pint typischerweise 20–40 Verbesserungen.

Deployment: GitOps mit dem Prometheus Operator

Regeln gehören ins Git, nicht per SSH auf den Server. Der Prometheus Operator liest PrometheusRule-CRDs und lädt sie automatisch neu – ohne reload-Endpoint und ohne SIGHUP.

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: api-slo
  namespace: monitoring
  labels:
    prometheus: k8s
    role: alert-rules
spec:
  groups:
    - name: api-slo.rules
      interval: 30s
      rules:
        - alert: ApiHighErrorRate
          expr: job:http_error_ratio:rate5m{job="api"} > 0.05
          for: 10m
          labels:
            severity: critical

Wichtig: Das Label prometheus: k8s muss zum ruleSelector deiner Prometheus-Instanz passen, sonst wird die Regel ignoriert – ein Klassiker unter den Debugging-Sessions. Prüfe nach dem Deployment mit kubectl -n monitoring get prometheusrule und im Prometheus-UI unter Status → Rules, ob die Regel wirklich geladen wurde.

Für Argo CD oder Flux ergänzt du einen Sync-Hook, der nach dem Rollout promtool check rules gegen den generierten ConfigMap-Inhalt ausführt. So kann eine fehlerhafte Regel nie in den Cluster gelangen. Bei Flux reicht ein postBuild.substitute-Block, um Umgebungsvariablen wie Cluster-Namen in die Regeln zu injizieren – damit lässt sich dieselbe Regelbasis für Staging und Produktion nutzen.

Kosten, Skalierung und Hosting-Empfehlungen

Für die Dimensionierung gilt eine einfache Formel: RAM in GB ≈ aktive Series / 300.000. Bei 1,2 Mio. Series brauchst du also mindestens 4 GB nur für den TSDB-Head, plus 30 % Puffer für Queries und Recording Rules. In der Praxis: 8 GB für 1 Mio. Series, 16 GB für 2 Mio., 32 GB für 4 Mio.

SetupSeriesHardwareKosten/Monat
Homelab / Dev50kHetzner CX22 (2 vCPU, 4 GB)3,79 €
Kleines Startup300kHetzner CPX31 (4 vCPU, 8 GB)15,60 €
Mittelstand1,5 Mio.Hetzner CCX23 (4 ded. vCPU, 16 GB)26,90 €
Enterprise HA5 Mio.2× CCX33 + Thanos S3~130 € + 15 € Storage
Managed1,5 Mio.Grafana Cloud Pro~290 €

Der Kostenunterschied ist deutlich: Self-hosted Prometheus auf Hetzner kostet bei 1,5 Mio. Series rund 27 € plus Arbeitszeit, Grafana Cloud Pro liegt bei etwa 8 $ pro 1.000 Series über dem Free-Tier (10.000 Series gratis). Bei 1,5 Mio. Series sind das schnell 290 € monatlich. Dafür entfällt Betriebsaufwand – bei einem Team ohne dedizierte SRE-Kapazität ist das oft die bessere Rechnung.

Für hohe Verfügbarkeit: Zwei Prometheus-Instanzen mit identischer Config, beide scrapen dieselben Targets, Alertmanager im Cluster-Modus mit --cluster.peer. Deduplizierung passiert automatisch. Thanos oder Mimir obendrauf für langfristige Speicherung und globale Query-Sicht – S3-kompatibler Object Storage bei Hetzner kostet 5,99 €/TB/Monat, bei Backblaze B2 6 $/TB.

FAQ

Wie viele Alert-Regeln sollte ein Team haben?

Als Orientierung: 10–15 Regeln pro Service, davon höchstens 3 mit severity: critical. Ein Team mit 20 Services landet also bei 200–300 Regeln, von denen nur 40–60 jemals pagieren. Wenn mehr als 10 % deiner Alerts pro Woche außerhalb der Geschäftszeiten feuern, ist dein Setup zu empfindlich.

Warum feuert mein Alert nicht, obwohl die Metrik den Schwellwert überschreitet?

Prüfe in dieser Reihenfolge: (1) Ist die Regel geladen? Status → Rules im Prometheus-UI. (2) Passt der ruleSelector des Operators zum Label der PrometheusRule? (3) Ist die Bedingung durchgehend für die for-Dauer wahr – ein einzelner Ausreißer setzt den Timer zurück. (4) Ist die Metrik überhaupt vorhanden? count(metric_name) im Query-Browser.

Sollte ich for oder keep_firing_for verwenden?

Beides, für unterschiedliche Zwecke. for verzögert das Auslösen und filtert kurze Spitzen. keep_firing_for verzögert das Zurücksetzen und verhindert Flapping beim Recovery. Die Kombination for: 10m plus keep_firing_for: 5m ist ein guter Standard für die meisten Service-Alerts.

Was kostet Prometheus-Alerting im Vergleich zu Datadog oder New Relic?

Self-hosted Prometheus auf einem 16-GB-Hetzner-Server kostet rund 27 €/Monat unabhängig von der Series-Zahl. Datadog berechnet 15 $ pro Host/Monat plus 5 $ pro 100 Custom Metrics – bei 50 Hosts und 500 Custom Metrics sind das schnell 1.000 € monatlich. Grafana Cloud Pro liegt bei etwa 290 € für 1,5 Mio. Series. Die Rechnung kippt zugunsten Managed erst, wenn du keine Zeit für Betrieb hast.

Wie teste ich Alerting-Regeln ohne Produktionsdaten?

Mit promtool test rules und synthetischen Zeitreihen im YAML-Format. Definiere Eingabe-Series mit values: '0+600x20' (Startwert, Inkrement, Anzahl Schritte), setze einen eval_time und prüfe mit exp_alerts, welche Alerts mit welchen Labels feuern. Der Test läuft offline, deterministisch und in Millisekunden – ideal für die CI-Pipeline.