Broker-Tests

Externes MQTT-Uptime-Monitoring und Alerting

MQTT-Broker-Uptime von außen überwachen: synthetische Publish/Subscribe-Probe, Zertifikatsablauf, Cron, Heartbeats, Slack- und PagerDuty-Alerts und SLO-Rechnung.

Aktualisiert · 9 Min. Lesezeit

Externes MQTT-Uptime-Monitoring und Alerting

Externes Uptime-Monitoring beantwortet eine einzige Frage: Könnte sich ein Gerät außerhalb deines Netzwerks gerade jetzt mit dem Broker verbinden und eine Nachricht austauschen? Interne Metriken können das nicht beantworten. Sie sehen keine DNS-Fehler, abgelaufenen Zertifikate, defekten Load Balancer oder Firewall-Änderungen. Das sieht nur eine Probe, die sich wie ein Client verhält und von außen läuft.

Dieser Guide baut diese Probe, plant ihre Ausführung, leitet Alerts an Slack oder PagerDuty weiter und zeigt die SLO-Rechnung, mit der du Prüfintervall und Alert-Schwelle festlegst.

Was "verfügbar" bei einem MQTT-Broker bedeutet

"Der Port ist offen" ist eine schwache Definition. Ein Broker ist nur nützlich, wenn alle diese Schichten funktionieren:

SchichtPrüfungTypischer Fehler, den sie findet
DNSHostname wird aufgelöstAbgelaufene Domain, falscher Eintrag nach einer Migration
TCPPort 8883 nimmt Verbindungen anFirewall, Security Group, Broker-Prozess gestoppt
TLSHandshake klappt, Zertifikat noch N Tage gültigAbgelaufenes oder unpassendes Zertifikat
MQTT CONNECTCONNACK mit ErfolgscodeAuth-Backend down, Zugangsdaten rotiert, Verbindungslimit erreicht
Round TripGepublishte Nachricht kommt innerhalb des Timeouts anRouting kaputt, Cluster gespalten, Überlast

Prüfe jede Schicht einzeln und melde, welche fehlgeschlagen ist. "TLS fehlgeschlagen, Zertifikat abgelaufen" behebst du in fünf Minuten. "Probe fehlgeschlagen" startet eine halbstündige Suche. Für einmalige manuelle Checks siehe MQTT-Broker-Status prüfen und testen, ob ein MQTT-Port offen ist.

Eine minimale Probe mit den Mosquitto-Clients

Wenn du mosquitto_pub und mosquitto_sub schon hast, passt eine Shell-Probe in ein Dutzend Zeilen:

mqtt-probe.sh
#!/usr/bin/env bash
set -u
HOST=broker.connectmq.com; PORT=8883
TOPIC="testmqtt/uptime/$(hostname)-$$"
MSG="ping-$(date +%s)"
OUT=$(mktemp)

mosquitto_sub -h "$HOST" -p "$PORT" --capath /etc/ssl/certs \
  -u "$MQTT_USER" -P "$MQTT_PASS" -t "$TOPIC" -q 1 -C 1 -W 10 > "$OUT" &
SUB=$!
sleep 1
mosquitto_pub -h "$HOST" -p "$PORT" --capath /etc/ssl/certs \
  -u "$MQTT_USER" -P "$MQTT_PASS" -t "$TOPIC" -q 1 -m "$MSG"
wait $SUB

if grep -qx "$MSG" "$OUT"; then echo "OK"; rm -f "$OUT"; exit 0
else echo "FAIL: no round trip within 10 s"; rm -f "$OUT"; exit 1; fi

-C 1 beendet den Subscriber nach einer Nachricht, und -W 10 lässt ihn nach zehn Sekunden aufgeben. Der Exit-Code ist alles, was ein Scheduler oder Heartbeat-Dienst braucht.

Eine Probe mit Schichten in Python

Diese Version (paho-mqtt 2.x) prüft jede Schicht, misst die Zeit, meldet die verbleibenden Tage bis zum Zertifikatsablauf und gibt eine JSON-Zeile aus, die sich leicht in Logs übernehmen lässt:

mqtt_uptime_probe.py
import json, os, socket, ssl, sys, threading, time, uuid
import paho.mqtt.client as mqtt

HOST, PORT, TIMEOUT = "broker.connectmq.com", 8883, 10
result = {"host": HOST, "ts": int(time.time())}

def fail(stage, detail):
    result.update(ok=False, stage=stage, detail=str(detail))
    print(json.dumps(result)); sys.exit(1)

t = time.perf_counter()
try:
    socket.getaddrinfo(HOST, PORT)
except OSError as e:
    fail("dns", e)
try:
    ctx = ssl.create_default_context()
    with socket.create_connection((HOST, PORT), timeout=TIMEOUT) as raw:
        with ctx.wrap_socket(raw, server_hostname=HOST) as tls:
            not_after = ssl.cert_time_to_seconds(tls.getpeercert()["notAfter"])
except ssl.SSLError as e:
    fail("tls", e)
except OSError as e:
    fail("tcp", e)
result["cert_days_left"] = int((not_after - time.time()) // 86400)
result["tls_ms"] = round((time.perf_counter() - t) * 1000)

topic = f"testmqtt/uptime/{uuid.uuid4().hex[:8]}"
connack, got = {}, threading.Event()
c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"testmqtt-uptime-{uuid.uuid4().hex[:6]}")
c.username_pw_set(os.getenv("MQTT_USER"), os.getenv("MQTT_PASS"))
c.tls_set_context(ctx)
c.on_connect = lambda cl, ud, fl, rc, pr: (connack.update(rc=rc),
                                           None if rc.is_failure else cl.subscribe(topic, qos=1))
c.on_subscribe = lambda cl, ud, mid, rcs, pr: cl.publish(topic, "ping", qos=1)
c.on_message = lambda cl, ud, msg: got.set()

t = time.perf_counter()
try:
    c.connect(HOST, PORT, keepalive=15)
except OSError as e:
    fail("connect", e)
c.loop_start()
ok = got.wait(TIMEOUT)
c.disconnect(); c.loop_stop()
if "rc" not in connack:
    fail("connect", "no CONNACK")
if connack["rc"].is_failure:
    fail("connect", connack["rc"])
if not ok:
    fail("roundtrip", f"no message within {TIMEOUT} s")
result.update(ok=True, roundtrip_ms=round((time.perf_counter() - t) * 1000))
print(json.dumps(result))
sys.exit(2 if result["cert_days_left"] < 14 else 0)

Exit-Code 0 bedeutet gesund, 1 bedeutet ausgefallen (das Feld stage sagt, wo), und 2 bedeutet erreichbar, aber das Zertifikat läuft in weniger als zwei Wochen ab. Letzteres ist eine Warnung, kein Bereitschaftsalarm. Scheitert die Stufe connect, zeigt der Reason Code (zum Beispiel Not authorized), ob es an den Zugangsdaten oder an einer ACL liegt. Schlag ihn im Reason-Code-Tool oder unter MQTT-Verbindungsfehler nach.

Die Probe zeitgesteuert ausführen

  • cron oder ein systemd-Timer auf einer kleinen VM außerhalb des Broker-Netzwerks: * * * * * /opt/probe/mqtt_uptime_probe.py >> /var/log/mqtt-probe.log 2>&1. Das ist einfach und läuft jede Minute.
  • Mehrere Standorte. Lass dieselbe Probe aus zwei oder drei Regionen oder bei verschiedenen Anbietern laufen. Alarmiere, wenn die Mehrheit fehlschlägt. Fällt nur ein Standort aus, liegt es meist an dessen Netzwerk.
  • GitHub Actions schedule taugt für unkritische Checks, aber das Mindestintervall beträgt fünf Minuten, und Läufe können verspätet starten. Für Bereitschaftsalarme ist das nicht geeignet.
  • Uptime Kuma (selbst gehostet) bringt einen MQTT-Monitortyp mit und passt gut, wenn du eine Oberfläche bevorzugst.

Auch das, was die Probe ausführt, kann ausfallen. Nutze einen Heartbeat (Dead Man's Switch): Nach jedem erfolgreichen Lauf pingt die Probe eine URL bei einem Heartbeat-Dienst wie Healthchecks.io oder einem Push-Monitor von Uptime Kuma an. Bleiben die Pings aus, ist entweder der Broker oder der Probe-Host down, und in beiden Fällen bekommst du einen Alert:

Cron-Zeile mit Heartbeat
* * * * * /opt/probe/mqtt-probe.sh && curl -fsS -m 10 --retry 3 "$HEARTBEAT_URL" > /dev/null

Alert-Kanäle

Schick Alerts dorthin, wo sie tatsächlich jemand sieht, und erst bei ausreichender Evidenz. Eine gängige Regel lautet drei aufeinanderfolgende Fehlschläge von mindestens zwei Standorten, plus eine Entwarnung, sobald es wieder läuft.

Slack Incoming Webhook
curl -fsS -X POST -H 'Content-Type: application/json' \
  -d '{"text":":red_circle: MQTT probe failed at stage tls (broker.connectmq.com:8883)"}' \
  "$SLACK_WEBHOOK_URL"
PagerDuty Events API v2
curl -fsS -X POST https://events.pagerduty.com/v2/enqueue \
  -H 'Content-Type: application/json' \
  -d '{"routing_key":"'"$PD_ROUTING_KEY"'","event_action":"trigger",
       "dedup_key":"mqtt-probe-broker",
       "payload":{"summary":"MQTT round trip failing","source":"mqtt-probe","severity":"critical"}}'

Sende dieselbe Anfrage mit "event_action":"resolve" und derselben dedup_key, um den Incident automatisch zu schließen. Warnungen zum Zertifikatsablauf gehören in Slack oder in die E-Mail. Darum muss sich jemand diese Woche kümmern, nicht um 3 Uhr nachts. Wenn du Prometheus schon betreibst, exportiere die Probe als Metriken und alarmiere dort. Siehe MQTT mit Prometheus und Grafana überwachen.

SLO-Rechnung

Ein Verfügbarkeitsziel ergibt nur zusammen mit seinem Ausfallbudget Sinn:

VerfügbarkeitAusfallzeit pro 30 TageAusfallzeit pro Jahr
99 %7 h 12 min3,65 Tage
99,5 %3 h 36 min1,83 Tage
99,9 %43,2 min8 h 46 min
99,95 %21,6 min4 h 23 min
99,99 %4,3 min52,6 min

Miss sie als erfolgreiche Probes ÷ alle Probes. Eine Probe pro Minute ergibt in 30 Tagen 43.200 Messwerte, 99,9 % erlauben also 43 fehlgeschlagene Probes. Daraus folgen drei Dinge:

  • Das Intervall begrenzt die Genauigkeit. Bei einer Probe pro Minute kann ein 20-Sekunden-Ausfall unbemerkt bleiben oder als ganze Minute zählen. Willst du 99,99 % messen, prüfe alle 10–15 Sekunden.
  • Die Erkennungszeit frisst das Budget. Drei Fehlschläge im Minutentakt bedeuten rund drei Minuten, bis jemand alarmiert wird. Bei 99,9 % (43 Minuten) ist das in Ordnung, bei 99,99 % ist es fast das ganze Budget.
  • Dein SLO ist nicht das SLA des Anbieters. Das SLA deckt den Broker ab. Deine Probe misst den gesamten Pfad, inklusive deines DNS, deiner Zertifikate und deines Netzwerks. Lies SLAs und Uptime von MQTT-Brokern, bevor du beides vergleichst.

Behalte das Error Budget im Blick: Sind zur Monatsmitte schon 30 deiner 43 Minuten verbraucht, friere riskante Änderungen am Broker ein, bis es sich erholt hat.

Den Alert-Pfad testen

Eine Probe, die nie fehlgeschlagen ist, ist nicht getestet. Bevor du dich auf sie verlässt:

  1. Setze ein falsches Passwort und prüfe, dass die Stufe connect fehlschlägt und der Alert in Slack oder PagerDuty ankommt.
  2. Richte HOST auf einen Namen, der sich nicht auflösen lässt, und prüfe auf stage: dns.
  3. Stoppe den Cron-Job und prüfe, dass der Heartbeat-Dienst dich alarmiert.
  4. Prüfe von Hand, ob die Sicht der Probe der Realität entspricht: Verbinde dich mit dem Online-MQTT-Client und publishe auf das Probe-Topic, während die Probe läuft.

Externes Uptime-Monitoring besteht aus einem kleinen Skript, einem Scheduler und einem Heartbeat. Prüfe jede Schicht einzeln, alarmiere nur bei wiederholten Fehlschlägen von mehr als einem Standort, leite das Probe-Intervall aus deinem SLO ab und mach das Setup einmal absichtlich kaputt, um zu beweisen, dass die Alerts ankommen.

Häufig gestellte Fragen

Reicht es, zu prüfen, ob Port 1883 offen ist, um die MQTT-Uptime zu überwachen?

Nein. Ein Broker kann TCP-Verbindungen annehmen und trotzdem Logins ablehnen, an TLS scheitern oder keine Nachrichten routen. Ein echter Uptime-Check verbindet sich mit Zugangsdaten, abonniert, publisht eine Nachricht und bestätigt, dass sie innerhalb eines Timeouts ankommt.

Wie oft sollte eine MQTT-Uptime-Probe laufen?

Jede Minute ist ein guter Standard. Das Intervall begrenzt, wie genau du Verfügbarkeit messen kannst: Bei einem Check pro Minute bleiben Ausfälle unter einer Minute eventuell unbemerkt, und ein monatliches 99,99-%-Budget von rund vier Minuten ist aufgebraucht, bevor ein Alert nach drei Fehlschlägen auslöst.

Wie viel Ausfallzeit erlaubt 99,9 %?

Etwa 43 Minuten pro 30-Tage-Monat oder rund 8 Stunden 46 Minuten pro Jahr. 99,95 % erlauben etwa 22 Minuten pro Monat, 99,99 % etwa 4,3 Minuten.