Prometheus Alertmanager Telefonanrufe: nur beim Kritischen klingeln

Alertmanager hat keinen Voice-Receiver. So wird aus einem Prometheus-Alert nur bei Severity critical ein Anruf: Webhook-Config, Bedingungen und die Watchdog-Falle.

Aktualisiert

Inhaltsverzeichnis

Alertmanager hat keinen Voice-Receiver. Um bei einem Prometheus-Alert angerufen zu werden, fügen Sie einen webhook_configs-Receiver hinzu, der auf einen Echobell-Kanal mit dem Abo-Typ Anruf zeigt. Dieser Leitfaden zeigt das exakte YAML, die Bedingung, die aufgelöste Alerts vom Anrufen abhält, das Routing nach Severity — und den Watchdog-Alert, der Ihr Telefon andernfalls alle vier Stunden für immer klingeln lässt.

Prometheus ist der Standard-Metrik-Stack für fast jede Infrastruktur des letzten Jahrzehnts, und Alertmanager ist wirklich gut in den schwierigen Teilen: Alerts deduplizieren, gruppieren, während Wartungsfenstern stummschalten und nachgelagertes Rauschen unterdrücken, wenn eine vorgelagerte Abhängigkeit ausfällt.

Was er nicht tut, ist jemanden aufwecken.

Warum Alertmanager Ihr Telefon nicht klingeln lassen kann

Alertmanager bringt Receiver für E-Mail, Slack, PagerDuty, OpsGenie, Discord, Telegram, Pushover, Webex, MS Teams und ein Dutzend weitere mit. Jeder davon liefert eine Nachricht, und Nachrichten unterliegen dem Stummschalter, „Nicht stören" und den iOS-Fokus-Modi. Um 03:00 Uhr heißt das: Der Alert kommt an, und nichts passiert.

Es gibt kein voice_configs. Die Optionen, bei denen die meisten landen:

  • PagerDuty / OpsGenie / Splunk On-Call — die rufen tatsächlich an, sind aber vollwertige Incident-Management-Plattformen mit entsprechender Preisgestaltung pro Sitz. Die richtige Antwort, wenn Sie Rotationen und Eskalationsbäume brauchen; überdimensioniert, wenn ein Telefon nur klingeln soll. (OpsGenie wird zudem eingestellt — deshalb bewerten gerade so viele Teams diese Schicht neu.)
  • SMS-Brücken wie Sachet — Sie betreiben einen weiteren Dienst, zahlen ein Gateway pro Nachricht, und eine SMS landet trotzdem als Nachricht. Unter iOS durchbricht eine SMS den Fokus-Modus nur, wenn der Absender auf Ihrer Zulassungsliste steht.
  • Twilio-Bastellösungen — einen kleinen Webhook-Receiver schreiben, eine Nummer kaufen, pro Anruf zahlen, und schon besitzen Sie ein Stück Produktionsinfrastruktur, dessen einzige Aufgabe es ist, ein Telefon klingeln zu lassen.

Der generische Webhook-Receiver ist der Ausweg. Er postet ein dokumentiertes JSON an eine beliebige URL — mehr brauchen Sie nicht.

Was Sie brauchen

  • Ein laufendes Prometheus + Alertmanager und Zugriff auf alertmanager.yml
  • Echobell installiert (App Store / Google Play)
  • Zehn Minuten

Dieser Leitfaden wurde gegen Alertmanager 0.31 geschrieben. Das Webhook-Payload steht seit Jahren auf version: "4", 0.2x-Releases verhalten sich also identisch.

Ihr Alertmanager braucht ausgehendes HTTPS zu hook.echobell.one. Er muss nicht aus dem Internet erreichbar sein — ein Alertmanager im Cluster, in einer VPC oder im Homelab funktioniert einwandfrei.

Schritt 1 — Einen Kanal anlegen, der Sie anruft

Legen Sie in Echobell einen Kanal an, etwa Prometheus Critical. Setzen Sie den Benachrichtigungstyp des Abos auf Anruf. Das ist die entscheidende Einstellung: Alerts vom Typ Anruf erscheinen als eingehender Anruf und klingeln durch iOS-Fokus und „Nicht stören" hindurch — eine Push-Benachrichtigung tut das nicht.

Setzen Sie die Vorlagen so, dass sie das Alertmanager-Payload direkt lesen:

Title: 🔴 {{commonLabels.alertname}} on {{commonLabels.instance}}
Body: {{commonAnnotations.summary}}
{{commonAnnotations.description}}

Und in den erweiterten Einstellungen eine Link-Vorlage, damit der Benachrichtigungseintrag direkt zum Graphen springt:

{{alerts[0].generatorURL}}

Kopieren Sie dann die Webhook-URL des Kanals:

https://hook.echobell.one/t/<channel-token>

Behandeln Sie diese URL als Geheimnis — wer sie hat, kann Ihr Telefon klingeln lassen.

Schritt 2 — Webhook-Receiver hinzufügen

In alertmanager.yml:

route:
  group_by: ["alertname", "cluster", "service"]
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: echobell-critical

receivers:
  - name: echobell-critical
    webhook_configs:
      - url: "https://hook.echobell.one/t/<channel-token>"
        send_resolved: false

Neu laden mit curl -X POST http://localhost:9093/-/reload oder SIGHUP.

Beachten Sie send_resolved: false. Der Standardwert für einen Webhook-Receiver ist true — anders als bei den meisten anderen Alertmanager-Receivern. Lässt man die Zeile weg, klingelt Ihr Telefon, wenn der Dienst kaputtgeht, und klingelt erneut, wenn er sich selbst repariert. Genau dieser zweite Anruf bringt Leuten bei, den ersten zu ignorieren. Schritt 4 zeigt, wie Sie die Entwarnung ohne Klingeln zurückbekommen.

Schritt 3 — Verstehen, was tatsächlich ankommt

Alertmanager gruppiert Alerts und postet dann ein Payload pro Gruppe:

{
  "version": "4",
  "groupKey": "{}:{alertname=\"HighErrorRate\"}",
  "truncatedAlerts": 0,
  "status": "firing",
  "receiver": "echobell-critical",
  "groupLabels": { "alertname": "HighErrorRate" },
  "commonLabels": { "alertname": "HighErrorRate", "severity": "critical" },
  "commonAnnotations": { "summary": "Error rate above 5% for 10m" },
  "externalURL": "http://alertmanager.internal:9093",
  "alerts": [
    {
      "status": "firing",
      "labels": { "alertname": "HighErrorRate", "instance": "api-7d9f:8080" },
      "annotations": { "summary": "Error rate above 5% for 10m" },
      "startsAt": "2026-09-04T02:41:07.351Z",
      "endsAt": "0001-01-01T00:00:00Z",
      "generatorURL": "http://prometheus:9090/graph?g0.expr=...",
      "fingerprint": "a1b2c3d4e5f60718"
    }
  ]
}

Echobell liest den JSON-Body unverändert, also steht jedes dieser Felder in Vorlagen und Bedingungen zur Verfügung. Verschachtelter Zugriff funktioniert in beiden Schreibweisen — {{commonLabels.severity}} oder {{alerts[0].labels["instance"]}}.

Zwei Eigenschaften dieses Payloads bestimmen alles Weitere:

Das status-Feld der obersten Ebene ist firing, sobald irgendein Alert der Gruppe feuert. Es wird erst dann resolved, wenn jeder Alert der Gruppe aufgelöst ist. Das macht es zu einem sauberen Filterkriterium.

commonLabels enthält nur die Labels, die alle Alerts der Gruppe teilen. Das ist die häufigste Überraschung. Ist group_by breit genug, dass ein Webhook HighErrorRate von drei verschiedenen Instanzen trägt, fehlt commonLabels.instance und {{commonLabels.instance}} rendert als leerer String. Weiter unten steht, wie Sie damit umgehen.

Schritt 4 — Entwarnungen als leisen Push schicken

Sie wollen weiterhin wissen, wann sich etwas erholt — Sie wollen nur nicht deswegen angerufen werden. Legen Sie einen zweiten Echobell-Kanal Prometheus Recovered an, Typ Normal, mit diesen Vorlagen:

Title: ✅ {{commonLabels.alertname}} resolved
Body: {{commonAnnotations.summary}}

und in den erweiterten Einstellungen dieser Bedingung:

status == "resolved"

Bedingungen sind Ausdrücke, die ausgewertet werden, bevor irgendetwas zugestellt wird. Ist der Ausdruck falsch, nimmt Echobell die Anfrage an und sendet nichts.

Richten Sie dann denselben Receiver auf beide Kanäle — ein Receiver kann mehrere webhook_configs enthalten:

receivers:
  - name: echobell-critical
    webhook_configs:
      # Lässt das Telefon klingeln. Nur bei firing.
      - url: "https://hook.echobell.one/t/<calling-channel-token>"
        send_resolved: false
      # Leiser Push. Die Kanalbedingung verwirft die firing-Hälfte.
      - url: "https://hook.echobell.one/t/<recovery-channel-token>"
        send_resolved: true

Der Recovery-Kanal empfängt sowohl firing- als auch resolved-Payloads und verwirft die firing-Hälfte. Ergebnis: Der Ausfall klingelt, die Erholung kommt als Push, den Sie morgens lesen.

Schritt 5 — Nach Severity routen, nicht alles schicken

Eine Catch-all-Route, die jeden Alert an einen Anrufkanal schickt, ist eine Maschine zur Herstellung ignorierter Anrufe. Trennen Sie nach Severity im Alertmanager, wo der Routing-Baum hingehört:

route:
  group_by: ["alertname", "cluster", "service"]
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: echobell-warning

  routes:
    # Watchdog erreicht nie einen Menschen. Siehe Schritt 6.
    - matchers:
        - alertname = "Watchdog"
      receiver: "null"

    - matchers:
        - severity = "critical"
      receiver: echobell-critical
      group_wait: 10s
      repeat_interval: 1h

receivers:
  - name: "null"

  - name: echobell-critical
    webhook_configs:
      - url: "https://hook.echobell.one/t/<calling-channel-token>"
        send_resolved: false

  - name: echobell-warning
    webhook_configs:
      - url: "https://hook.echobell.one/t/<normal-channel-token>"
        send_resolved: true

Routen werden von oben nach unten ausgewertet, und die erste Übereinstimmung gewinntcontinue ist standardmäßig false. Die Reihenfolge zählt also: Die Watchdog-Route muss über allem stehen, was sie sonst verschlucken würde.

Wenn Sie lieber einen Kanal behalten und auf der Echobell-Seite filtern, lautet die äquivalente Bedingung:

status == "firing" && commonLabels.severity == "critical"

Im Alertmanager ist es meist besser, weil severity dort auch group_wait und repeat_interval steuert. In Echobell ist es besser, wenn Sie heute keine Config-Änderung durchbekommen.

Schritt 6 — Die Watchdog-Falle

Wenn Sie kube-prometheus-stack betreiben, haben Sie einen Alert namens Watchdog mit dem Ausdruck vector(1). Er ist dafür gebaut, permanent zu feuern — er existiert, damit ein externes System merken kann, dass Prometheus selbst stehengeblieben ist. Die Standardkonfiguration routet ihn auf einen null-Receiver.

Richten Sie eine Catch-all-Route auf einen Anrufkanal, ohne ihn auszuschließen, und Watchdog ruft Ihr Telefon bei jedem repeat_interval an — für immer, ab sofort. Das ist der häufigste Grund, warum Leute schlussfolgern, Telefon-Alerts „funktionieren nicht".

Behalten Sie die null-Route aus Schritt 5. Und machen Sie dann optional etwas Nützliches daraus: Verwandeln Sie Watchdog in einen echten Totmannschalter.

    - matchers:
        - alertname = "Watchdog"
      receiver: deadmansswitch
      group_wait: 0s
      group_interval: 1m
      repeat_interval: 50s

receivers:
  - name: deadmansswitch
    webhook_configs:
      - url: "https://hc-ping.com/<your-check-uuid>"
        send_resolved: false

Echobell selbst kann nicht der Totmannschalter sein — es alarmiert, wenn eine Anfrage ankommt, nicht wenn sie ausbleibt. Schicken Sie den Watchdog-Ping also an einen Dienst, der auf Stille-Erkennung ausgelegt ist (Healthchecks.io, Cronitor, Dead Man's Snitch), und richten Sie dann den „Check ausgefallen"-Webhook dieses Dienstes auf Ihren Echobell-Anrufkanal. Jetzt bedeutet ein Anruf: „Die Überwachung selbst ist tot" — genau der Alert, für den Sie am ehesten geweckt werden wollen, und den niemand konfiguriert.

So wird daraus kein Hirtenjunge, der „Wolf" ruft

Drei Alertmanager-Einstellungen erledigen den Großteil der Arbeit, dazu eine in Prometheus:

EinstellungWoWas sie tut
for:Alert-RegelWie lange die Bedingung halten muss, bevor überhaupt gefeuert wird. Ihre erste Verteidigungslinie gegen einen Zwei-Sekunden-Aussetzer.
group_waitRouteWie lange auf weitere Alerts gewartet wird, bevor die erste Benachrichtigung rausgeht. Standard 30s; für kritisch auf 10s senken.
group_intervalRouteMindestabstand, bevor über neue Alerts einer bestehenden Gruppe benachrichtigt wird. Standard 5m.
repeat_intervalRouteWie oft ein ungelöster Alert erneut benachrichtigt. Standard 4h — ein nächtlicher Ausfall ruft Sie also um 03:00 und noch einmal um 07:00 an.

Über repeat_interval lohnt es sich nachzudenken. Vier Stunden sind lang, um etwas kaputt zu lassen; zwanzig Minuten sind eine Maschine, die Sie dazu bringt, den Kanal abzuschalten. Eine Stunde für kritisch ist ein vernünftiger Startpunkt.

Wenn ein unbeantworteter Anruf sofort erneut versucht werden soll, statt auf das nächste repeat_interval zu warten, aktivieren Sie Fehlgeschlagenen Anruf wiederholen in den App-Einstellungen von Echobell.

Nur außerhalb der Arbeitszeit klingeln

Tagsüber schauen Sie vermutlich ohnehin auf ein Dashboard. Echobells Systemzeit-Variablen (alle in UTC) lassen einen Kanal je nach Stunde unterschiedlich reagieren, ganz ohne zweite Route im Alertmanager:

status == "firing" && (hour >= 17 || hour < 9)

Das ruft Sie nur außerhalb von 09:00–17:00 UTC an. Richten Sie einen zweiten Kanal vom Typ Normal auf das umgekehrte Fenster für Pushes am Tag:

status == "firing" && hour >= 9 && hour < 17

Mit dayOfWeek >= 1 && dayOfWeek <= 5 gilt auch das Wochenende als außerhalb der Arbeitszeit. Denken Sie daran, dass immer in UTC gerechnet wird — versetzen Sie die Werte für Ihre Zeitzone. Ausführlicher steht das in Zeitfenster-Benachrichtigungen mit UTC-Bedingungen.

Das Problem mit leerem commonLabels

Enthält eine Gruppe Alerts von mehreren Instanzen, verschwindet commonLabels.instance und Ihr Titel lautet 🔴 HighErrorRate on .

Drei Auswege, nach Präferenz geordnet:

  1. Das Label in group_by aufnehmen. Enthält group_by das Label instance, teilen alle Alerts einer Gruppe es, und commonLabels.instance ist immer vorhanden. Der Preis sind mehr Benachrichtigungen — eine pro Instanz statt einer pro Alert-Name.
  2. Stattdessen den ersten Alert lesen. {{alerts[0].labels.instance}} ist immer gefüllt. Es ist nur einer von möglicherweise vielen, also kombinieren Sie ihn mit einer Zählung: {{alerts[0].labels.instance}} (+{{alerts.length}} Alerts).
  3. Das Label so gestalten, dass leer trotzdem lesbar ist. Echobell hat keinen Standardwert-Operator — {{a || "unknown"}} rendert den Literaltext true, keinen Fallback — schreiben Sie also Instance: {{commonLabels.instance}} in eine eigene Zeile, wo ein leerer Wert offensichtlich leer ist statt einen Satz zu zerbrechen.

Das Payload klein halten

Eine Gruppe über hundert Pods erzeugt einen großen JSON-Body, und Echobell weist Trigger-Bodys über 1 MiB mit HTTP 413 ab. Deckeln Sie das im Alertmanager:

      - url: "https://hook.echobell.one/t/<channel-token>"
        send_resolved: false
        max_alerts: 20

Alertmanager sendet dann höchstens zwanzig Alerts und setzt truncatedAlerts auf die Zahl der verworfenen — die Sie im Body anzeigen können:

Body: {{commonAnnotations.summary}}
Alerts: {{alerts.length}} (+{{truncatedAlerts}} abgeschnitten)

Den Alert mit dem Team teilen

Ein Echobell-Kanal lässt sich über einen Abo-Link teilen, und jeder Abonnent wählt seinen eigenen Benachrichtigungstyp. Dieselbe Route kann also das Telefon der Person in Rufbereitschaft klingeln lassen und bei allen anderen als normaler Push landen — ohne Preis pro Sitz und ohne zusätzliche Routing-Regeln im Alertmanager.

Das passt auch zu dem Grund, aus dem viele Teams Prometheus überhaupt selbst hosten: Ihre Metriken und Alert-Regeln bleiben auf Ihrer Infrastruktur, und Echobell hält Benachrichtigungsinhalte und -verlauf auf dem Gerät statt auf seinen Servern.

Was dieses Setup nicht liefert

Ehrlichkeit über die Grenze erspart Ihnen später eine schlechte Migration. Echobell ist eine Zustellschicht, keine Incident-Management-Plattform. Es hat kein:

  • Rufbereitschaftspläne oder Follow-the-Sun-Übergaben
  • Eskalationsbäume, die eine zweite Person anrufen, wenn die erste nicht abnimmt
  • Incident-Zeitleisten, Acknowledgement-Tracking oder Postmortem-Werkzeuge

Braucht Ihr Team das, brauchen Sie PagerDuty, Grafana Cloud IRM oder Vergleichbares. Was hier abgedeckt wird, ist die konkrete Lücke, die Alertmanager offenlässt: aus einem feuernden Alert ein Telefon zu machen, das wirklich klingelt. Für Einzelbetreiber, kleine Teams und Homelabs ist das üblicherweise die gesamte Anforderung.

Fehlersuche

Es kommt überhaupt nichts an. Schauen Sie zuerst in die Logs des Alertmanagers selbst (level=error component=dispatcher), und prüfen Sie dann, ob die Route wirklich zu Ihrem Receiver auflöst: amtool config routes test severity=critical alertname=HighErrorRate sagt Ihnen, in welchem Receiver ein Alert landen würde, ohne dass Sie auf einen echten warten müssen.

Echobell antwortet mit HTTP 404. Der Kanal-Token ist falsch oder der Kanal wurde gelöscht. Ein unbekannter Token ergibt einen 404, keinen stillen Erfolg.

Echobell antwortet mit 200 und "notificationTriggered": false. Ihre Bedingung war falsch. Der Antwort-Body trägt zusätzlich "conditionsMet": false — der schnellste Weg, „meine Bedingung stimmt nicht" von „mein Webhook kam nie an" zu unterscheiden. Prüfen Sie status == "firing" gegen das, was Alertmanager tatsächlich gesendet hat — den Status der obersten Ebene, nicht alerts[0].status.

HTTP 413. Das Payload überschritt 1 MiB. Setzen Sie max_alerts wie oben.

HTTP 405. Der Kanal hat POST Only aktiviert und etwas hat ein GET geschickt. Alertmanager postet, also heißt das meistens, dass Sie die URL im Browser getestet haben.

Der Titel hat eine Lücke. commonLabels enthielt dieses Label für diese Gruppe nicht. Siehe den Abschnitt oben.

Es klingelt nicht, aber die Benachrichtigung kommt an. Der Benachrichtigungstyp des Abos ist Normal oder Zeitkritisch, nicht Anruf. Der Typ wird pro Abonnent gewählt — prüfen Sie ihn auf dem Gerät, das nicht klingelt.

Testen, ohne die Produktion zu stören. Fügen Sie eine Regel mit expr: vector(1), einem eindeutigen alertname und severity: critical hinzu, lassen Sie sie einmal feuern und löschen Sie sie wieder. Oder feuern Sie eine von Hand:

curl -X POST http://localhost:9093/api/v2/alerts -H 'Content-Type: application/json' -d '[
  {"labels":{"alertname":"EchobellTest","severity":"critical"},
   "annotations":{"summary":"Testing the phone call path"}}
]'

Häufige Fragen

Kann Prometheus Alertmanager von sich aus anrufen?

Nein. Alertmanager hat Receiver für E-Mail, Slack, PagerDuty, OpsGenie und viele weitere, aber keinen Voice- oder SMS-Receiver. Anrufe erfordern, den generischen Webhook-Receiver an einen Dienst zu routen, der anrufen kann — etwa Echobell — oder eine Incident-Management-Plattform zu bezahlen.

Durchbricht der Anruf „Nicht stören"?

Ja. Echobells Benachrichtigungstyp Anruf erscheint als eingehender Anruf und klingelt durch iOS-Fokus und „Nicht stören" hindurch. Details und die beteiligten Einstellungen stehen in Wie man kritische Alerts trotz iOS Focus Mode erhält.

Funktioniert das mit Alertmanager hinter einer Firewall oder in Kubernetes?

Ja. Der Webhook ist eine ausgehende HTTPS-Anfrage vom Alertmanager, er muss also nur hook.echobell.one erreichen. Ihr Alertmanager braucht weder eine öffentliche Adresse noch einen Ingress.

Wie stoppe ich Anrufe, wenn ein Alert sich auflöst?

Setzen Sie send_resolved: false in der Webhook-Config, die auf Ihren Anrufkanal zeigt. Der Webhook-Receiver steht standardmäßig auf true — anders als die meisten anderen Alertmanager-Receiver — es ist also Opt-out statt Opt-in. Um Entwarnungen weiterhin leise zu erhalten, legen Sie einen zweiten Kanal mit der Bedingung status == "resolved" an.

Warum klingelt mein Telefon alle vier Stunden wegen desselben Alerts?

Das ist repeat_interval, Standardwert 4h. Alertmanager benachrichtigt in diesem Takt erneut über einen weiterhin feuernden Alert. Setzen Sie den Wert pro Route — 1h für kritisch ist eine gängige Wahl. Begannen die Anrufe direkt nach dem Hinzufügen einer Catch-all-Route, ist eher der dauerhaft feuernde Watchdog-Alert schuld; siehe Schritt 6.

Können mehrere Personen für denselben Alert angerufen werden?

Ja. Teilen Sie den Kanal mit Ihren Kolleginnen und Kollegen; jeder Abonnent wählt seinen Benachrichtigungstyp. Alle, die den Anrufkanal abonniert haben, werden angerufen — ohne Kosten pro Sitz.

Severity im Alertmanager oder in Echobell-Bedingungen filtern?

Bevorzugt im Alertmanager: Dort können Sie zusätzlich group_wait und repeat_interval pro Severity setzen, und der Routing-Baum bleibt mit dem Rest der Konfiguration versioniert. Echobell-Bedingungen sind richtig, wenn Sie die Alertmanager-Config nicht ändern können oder für Filter, die Alertmanager gar nicht kennt — etwa die Tageszeit.

Fazit

Das Setup besteht aus einem Receiver, einem send_resolved: false und einem Routing-Baum, der alles außer severity: critical vom Anrufkanal fernhält. Ihre Alert-Regeln, Gruppierungen, Silences und Inhibitions bleiben exakt wie sie sind — und die Lücke zwischen „Prometheus hat es bemerkt" und „ein Mensch hat es bemerkt" ist geschlossen.

Laden Sie Echobell fürs iPhone oder holen Sie es bei Google Play, und feuern Sie den EchobellTest-Alert von oben ab, bevor Sie sich für etwas Echtes auf diesen Weg verlassen.


Verwandte Beiträge