Grafana Grafana

Alert-Regeln, Contact Points und Notification Policies provisionieren

Definiere die gesamte Alerting-Pipeline in YAML, damit sie wie Code geprüft und versioniert wird.

15 min Fortgeschritten

Grafana-Alerting hat vier bewegliche Teile: Alert-Regeln entscheiden, wann etwas falsch ist, Contact Points sagen, wohin eine Benachrichtigung geht, Notification Policies routen Alerts zu Contact Points, und Mute Timings und Templates formen, wann und wie Nachrichten rausgehen. Alle vier lassen sich aus YAML im Ordner provisioning/alerting provisionieren, was Alerting prüfbar macht statt zu einem Haufen UI-Einstellungen. Diese Anleitung baut eine kleine funktionierende Pipeline.

Provisionierte Alerting-Ressourcen lassen sich in der UI nicht bearbeiten, und der Import einer bereits vorhandenen Ressource führt zu einem Konflikt, entferne also zuerst handgemachte Duplikate. Jede Datei beginnt mit apiVersion: 1.

Contact Points

provisioning/alerting/contact-points.yaml:

apiVersion: 1

contactPoints:
  - orgId: 1
    name: team-slack
    receivers:
      - uid: team-slack-1
        type: slack
        disableResolveMessage: false
        settings:
          url: ${SLACK_WEBHOOK_URL}
          recipient: '#alerts'

  - orgId: 1
    name: oncall-email
    receivers:
      - uid: oncall-email-1
        type: email
        settings:
          addresses: oncall@example.com

Anmerkungen:

  • uid jedes Receivers muss eindeutig und stabil sein. Grafana nutzt sie, um den Receiver an Ort und Stelle zu aktualisieren.
  • type ist die Integration, etwa slack, email, webhook, pagerduty, opsgenie oder prometheus-alertmanager. Die Schlüssel unter settings hängen vom Typ ab, prüfe also die Dokumentation für deinen.
  • Secrets kommen mit $VAR oder ${VAR} aus Umgebungsvariablen, sodass die Webhook-URL nie in Git landet. Nutze $$, um ein literales Dollarzeichen zu behalten.
  • Zum Entfernen füge deleteContactPoints mit orgId und uid hinzu.

Notification Policies

Der Policy-Baum entscheidet, welcher Contact Point welchen Alert behandelt. Der gesamte Baum ist eine einzige Ressource, und sie zu provisionieren überschreibt alle bestehenden Policies.

provisioning/alerting/policies.yaml:

apiVersion: 1

policies:
  - orgId: 1
    receiver: team-slack            # Standard für alles, was unten nicht passt
    group_by: ['alertname', 'namespace']
    group_wait: 30s
    group_interval: 5m
    repeat_interval: 4h
    routes:
      - receiver: oncall-email
        object_matchers:
          - ['severity', '=', 'critical']
        repeat_interval: 1h
      - receiver: team-slack
        object_matchers:
          - ['team', '=', 'platform']
        mute_time_intervals:
          - weekends
  • receiver ganz oben ist der Fallback-Contact-Point.
  • group_by bündelt zusammengehörige Alerts zu einer Benachrichtigung.
  • group_wait, group_interval, repeat_interval steuern, wie schnell die erste Nachricht rausgeht, wie oft Updates für eine Gruppe gesendet werden und wie oft ein ungelöster Alert wiederholt wird.
  • routes sind Kind-Policies mit denselben Feldern. Die erste passende Route gewinnt, sofern du nicht continue: true setzt.
  • object_matchers sind [label, operator, value]-Tripel. Die Operatoren sind =, !=, =~ und !~.

Um den Baum auf Grafanas Standard zurückzusetzen, nutze resetPolicies: [1] mit der Organisations-ID.

Mute Timings

apiVersion: 1

muteTimes:
  - orgId: 1
    name: weekends
    time_intervals:
      - weekdays: ['saturday', 'sunday']
        location: 'UTC'

times (mit start_time und end_time), weekdays, months, years und days_of_month lassen sich kombinieren, und Bereiche nutzen Doppelpunkte, wie 'monday:friday'. Löschen geht mit deleteMuteTimes. Mute Timings können in ihren Namen oder Intervallen keine Variableninterpolation nutzen.

Benachrichtigungs-Templates

apiVersion: 1

templates:
  - orgId: 1
    name: slack_title
    template: |
      {{ define "slack_title" }}
        [{{ .Status | toUpper }}] {{ .CommonLabels.alertname }}
      {{ end }}

Referenziere ein Template aus den Einstellungen eines Contact Points (zum Beispiel dem Slack-Feld title) als {{ template "slack_title" . }}. Template-Namen und -Inhalte unterstützen keine Variableninterpolation, schreibe sie also wörtlich.

Alert-Regeln

Regeln sind in Gruppen organisiert, die ein Auswertungsintervall teilen und in einem Ordner liegen. Jede Regel hat eine Liste von Query- und Ausdrucksschritten und eine condition, die den Schritt benennt, der entscheidet, ob sie feuert.

provisioning/alerting/rules.yaml:

apiVersion: 1

groups:
  - orgId: 1
    name: webapp
    folder: Applications
    interval: 1m
    rules:
      - uid: webapp-down
        title: Webapp targets down
        condition: C
        for: 5m
        noDataState: NoData
        execErrState: Error
        labels:
          severity: critical
          team: platform
        annotations:
          summary: 'No healthy webapp targets for 5 minutes'
          runbook_url: https://runbooks.example.com/webapp-down
        data:
          - refId: A
            relativeTimeRange:
              from: 600
              to: 0
            datasourceUid: prometheus
            model:
              refId: A
              expr: sum(up{job="webapp"})
              instant: true
          - refId: B
            datasourceUid: __expr__
            model:
              refId: B
              type: reduce
              expression: A
              reducer: last
              datasource:
                type: __expr__
                uid: __expr__
          - refId: C
            datasourceUid: __expr__
            model:
              refId: C
              type: threshold
              expression: B
              conditions:
                - evaluator:
                    type: lt
                    params: [1]
              datasource:
                type: __expr__
                uid: __expr__

So liest du es:

  • Schritt A fragt Prometheus (über die uid der von dir provisionierten Datenquelle) nach der Anzahl gesunder Targets in den letzten zehn Minuten. relativeTimeRange ist in Sekunden.
  • Schritt B reduziert das Ergebnis auf einen einzelnen Wert. Ausdrücke nutzen die spezielle Datenquellen-UID __expr__.
  • Schritt C ist ein Threshold: Er feuert, wenn der Wert kleiner als 1 ist. condition: C markiert ihn als entscheidenden Schritt.
  • for: 5m verlangt, dass die Bedingung fünf Minuten gilt, bevor der Alert feuert, was Flattern vermeidet.
  • noDataState und execErrState sagen, was zu tun ist, wenn die Query nichts liefert oder fehlschlägt: NoData, Alerting oder OK für Ersteres, und Error, Alerting oder OK für Letzteres.
  • labels speisen den Notification-Policy-Baum, sodass severity: critical diesen Alert auf die Route oncall-email oben geschickt hat.
  • uid (bis zu 40 Zeichen aus Buchstaben, Ziffern, - und _) muss eindeutig und stabil sein. Optional füge dashboardUid und panelId hinzu, um eine Regel mit einem Panel zu verknüpfen.
  • Ordner: Nutze einen Ordner, der existiert. Am einfachsten verwendest du den Titel eines Ordners wieder, den dein Dashboard-Provider erstellt.

Variableninterpolation funktioniert nicht in Regel-Annotationen, relativeTimeRange, dem Query-model oder Template-Inhalten, schreibe diese Werte also aus.

Um eine Regel zu löschen, füge deleteRules mit orgId und uid hinzu:

apiVersion: 1

deleteRules:
  - orgId: 1
    uid: webapp-down

Anwenden und prüfen

Alerting-Ressourcen werden beim Start gelesen, starte Grafana also nach Änderungen an den Dateien neu:

docker compose restart grafana

curl -s -u admin:$GRAFANA_ADMIN_PASSWORD \
  http://localhost:3000/api/v1/provisioning/alert-rules | jq '.[] | {uid, title, folderUID}'
curl -s -u admin:$GRAFANA_ADMIN_PASSWORD \
  http://localhost:3000/api/v1/provisioning/contact-points | jq '.[].name'
curl -s -u admin:$GRAFANA_ADMIN_PASSWORD \
  http://localhost:3000/api/v1/provisioning/policies | jq .receiver

Teste dann die Zustellung, indem du vorübergehend einen Threshold senkst oder über die API eine Testbenachrichtigung vom Contact Point sendest.

Regeln schneller schreiben

Regel-YAML ist ausführlich. Baue eine Regel einmal in einer Scratch-Instanz, exportiere sie dann im Provisioning-Format über die Alerting-Provisioning-API (die export-Routen unter /api/v1/provisioning/, mit ?format=yaml) und committe das Ergebnis mit einer stabilen uid. Für viele ähnliche Regeln erzeuge das YAML aus einem Template in CI oder verwalte sie mit Terraform oder dem Grafana Operator, die beide Ressourcen für Alert-Regeln haben.

Beliebte Anleitungen