sequenceDiagram
participant K as Client
participant G as Gateway
participant O as Order Service
participant P as Payment Service
K->>G: Anfrage
Note over G: neue Trace-ID t1
G->>O: Anfrage mit Header t1
O->>P: Anfrage mit Header t1
P-->>O: Antwort nach 480 ms
O-->>G: Antwort
G-->>K: Antwort
Skalierung und Betrieb Teil 2: Observability, SLO und Incident-Kultur
Track Konzepte · Verteilte Systeme und Betrieb · ca. 45 Min.
Worum es geht
Dein System läuft in mehreren Instanzen und bekommt neuen Code stufenweise. Jetzt brauchst du die Antwort auf die Frage, die Kunden und Teams wirklich interessiert: Geht es den Nutzern gut? Dafür gibt es Observability (Logs, Metriken, Traces), SLI, SLO und Error Budget und eine Kultur, die aus Vorfällen lernt (blameless Postmortem, Chaos Engineering, Game Day).
Am Ende rechnest du Error Budget und Burn Rate selbst, siehst, warum ein Label mit hoher Kardinalität das Monitoring lahmlegt, und schreibst ein Postmortem ohne Schuldigen. Alles ist Simulation oder Rechnung, die Zahlen stammen aus ausgeführtem Code.
Was du aus Teil 1 brauchst: dass mehrere Instanzen hinter einem Load Balancer laufen und dass neuer Code stufenweise ausgerollt wird (Canary). Daran messen SLO und Alarme, ob ein Rollout den Nutzern schadet.
Plane ehrlich 45 Minuten ein: etwa 12 Minuten Lesen, etwa 33 Minuten für zwei Übungen und eine Schreibaufgabe.
Von JS/TS her gedacht
Du kennst console.log und vielleicht performance.now() aus dem Browser, und im Backend sind es Logger wie pino oder winston (bitte prüfen). Neu ist hier, dass ein einzelner Request durch mehrere Services läuft und du ihn über die Grenzen hinweg verfolgen willst, und dass du Gesundheit als Zahl über die Zeit misst, nicht als einzelne Logzeile.
| Konzept | JS/TS | Python (hier) |
|---|---|---|
| Log | console.log(...) |
logging, im Beispiel print |
| Metrik | Zähler oder Histogramm (z. B. prom-client, bitte prüfen) | Zähler als Dictionary mit Labels |
| Trace-ID | Header x-request-id, weitergereicht |
ein Feld, das jeder Aufruf weitergibt |
| Fehlerrate | fehler / gesamt |
dieselbe Rechnung mit / |
Konzept
Schritt 4: Observability, Logs, Metriken, Traces
Observability (Beobachtbarkeit) heißt: Du kannst von außen herausfinden, warum ein System sich so verhält, auch bei Fehlern, die du nicht vorhergesehen hast. Drei Arten von Daten:
| Signal | Was es ist | Gut für | Typischer Preis |
|---|---|---|---|
| Logs | Zeitgestempelte Ereignisse (“Zahlung 4711 abgelehnt”) | Details zu einem einzelnen Fall | viel Volumen, schwer zu aggregieren |
| Metriken (metrics) | Zahlen über die Zeit (Anfragen pro Sekunde, Fehlerrate) | Trends, Dashboards, Alarme | sagt nicht, welcher Nutzer betroffen ist |
| Traces | Der Weg einer Anfrage durch mehrere Services, mit Dauer je Schritt | Wo geht die Zeit verloren? | muss in jedem Service eingebaut sein |
Distributed Tracing funktioniert so: Beim Eintritt bekommt die Anfrage eine Trace-ID. Jeder Service gibt sie an alle Aufrufe weiter (meist als HTTP-Header) und meldet seine Zeitabschnitte (Spans) mit dieser ID. Ein Sammler setzt daraus den Baum zusammen. Der übliche Standard dafür heißt OpenTelemetry (bitte prüfen, ob er für euer Projekt gesetzt ist).
Metriken haben Labels (Dimensionen), z. B. http_requests_total{endpoint="/cart", method="GET", status="200"}. Jede Kombination von Label-Werten ist eine eigene Zeitreihe (time series), und jede Zeitreihe kostet Speicher und Rechenzeit. Die Zahl der verschiedenen Werte eines Labels heißt Kardinalität (cardinality). Beispiel: Bei 10 Endpunkten, 2 Methoden und 3 Statuswerten sind es höchstens 10 mal 2 mal 3 Zeitreihen, also 60 und nicht 15. Ein Label mit sehr vielen Werten (Nutzer-ID, Request-ID, E-Mail) lässt die Zahl explodieren. Solche Werte gehören in Logs und Traces, nicht in Metrik-Labels. Das ist Übung 5.
Schritt 5: SLI, SLO, Error Budget und Alerting auf Symptome
Drei Begriffe, die oft verwechselt werden:
- SLI (service level indicator): eine gemessene Zahl, z. B. “Anteil der Requests ohne Serverfehler”.
- SLO (service level objective): das Ziel für den SLI über einen Zeitraum, z. B. “99,9 % der Requests erfolgreich in 30 Tagen”.
- Error Budget (Fehlerbudget): die Differenz zu 100 %, also der Ausfall, den du dir leisten darfst. Bei 99,9 % sind das 0,1 %.
In Minuten gerechnet (Code ausgeführt) für einen Zeitraum von 30 Tagen:
Ausgabe:
SLO 99.00%: Budget 432.00 Minuten in 30 Tagen
SLO 99.90%: Budget 43.20 Minuten in 30 Tagen
SLO 99.99%: Budget 4.32 Minuten in 30 Tagen
Jede zusätzliche Neun macht das Budget zehnmal kleiner und das Betreiben deutlich teurer. Darum ist 100 % kein sinnvolles Ziel: Es verbietet jede Änderung. Das Budget ist ein Steuerungsinstrument: Ist noch viel Budget übrig, darf das Team riskantere Änderungen ausliefern. Ist es leer, geht Stabilität vor.
Die Burn Rate (Verbrauchsgeschwindigkeit) sagt, wie schnell du das Budget verbrauchst: tatsächliche Fehlerrate geteilt durch die erlaubte Fehlerrate (1 minus SLO). Burn Rate 1 bedeutet: Das Budget reicht genau bis zum Ende des Zeitraums. Burn Rate 4 bedeutet: nach einem Viertel der Zeit ist es leer.
Beispiel mit 2000 Requests, 8 davon mit Status 500 und 20 mit Status 404 (ein Client-Fehler: der Nutzer hat eine falsche Adresse aufgerufen, nicht dein Service):
Ausgabe:
SLI: 0.996
Burn Rate bei SLO 99,9 %: 4.0
Stunden bis das 30-Tage-Budget leer wäre: 180.0
Alerting auf Symptome: Du lässt dich nur wecken (Page), wenn Nutzer etwas merken oder das Budget wirklich in Gefahr ist (Symptom, z. B. hohe Burn Rate). Ursachen wie hohe CPU oder ein voller Speicher sind Hinweise für Dashboards oder Tickets, aber kein Grund für Nachtalarme: Die CPU kann hoch sein, ohne dass jemand etwas merkt, und ein Ausfall kann ohne jede der erwarteten Ursachen kommen. Üblich ist ein Alarm auf die Burn Rate über zwei Zeitfenster (kurz und lang, z. B. 5 Minuten und 1 Stunde). Das kurze Fenster sagt, dass es jetzt brennt, das lange, dass es nicht nur ein Ausreißer war. Der Wert 14,4 für das 30-Tage-Budget stammt aus dem SRE Workbook (bitte prüfen): Bei dieser Rate sind in einer Stunde genau 2 % des Monatsbudgets weg, denn 1 Stunde geteilt durch (720 Stunden geteilt durch 14,4) ist 0,02.
Schritt 6: Incident-Kultur
Fehler passieren. Entscheidend ist, was danach geschieht:
- Blameless Postmortem (schuldfreie Nachbesprechung): Nach einem Vorfall schreibt das Team auf, was passiert ist, warum das System es zugelassen hat und was sich ändert, ohne eine Person zu beschuldigen. Der Gedanke: Wenn ein einzelner Fehler eines Menschen ein System lahmlegen kann, ist das System das Problem. Werden Menschen bestraft, verstecken sie Fehler, und du lernst nichts.
- Chaos Engineering: Du löst Ausfälle absichtlich aus (Instanz killen, Netzwerk verlangsamen), um zu prüfen, ob Resilienz (konzepte/07a und 07b) wirklich greift. Mit einer Hypothese (“wenn eine Instanz stirbt, bleibt die Fehlerrate unter 0,1 %”) und kleinem Radius.
- Game Day: Ein geplanter Übungstag, an dem das Team einen Ausfall durchspielt, damit Abläufe, Alarme und Runbooks vor dem Ernstfall getestet sind.
Falle
- Client-Fehler als Ausfall zählen. 4xx sind meist Nutzerfehler. Zählen sie im SLI mit, verbrennt ein Crawler dein Budget.
- Labels mit hoher Kardinalität. Eine Nutzer-ID als Label macht aus einer Metrik Millionen Zeitreihen und legt das Monitoring lahm.
- Alarme auf Ursachen statt Symptome. Das Team stumpft ab, echte Alarme gehen unter.
- Postmortem mit Schuldigem. Danach meldet niemand mehr Fehler früh.
Übungen
Übung 1: Error Budget und Burn Rate berechnen (ca. 8 Min.)
Schreibe vier kleine Funktionen. Ein Request-Log ist eine Liste von HTTP-Statuscodes, z. B. [200, 404, 500].
sli(log): Anteil der Requests, die kein Serverfehler waren (Status kleiner als 500). Status 4xx zählen als erfolgreich (Client-Fehler). Leeres Log:1.0.budget_minuten(slo, tage): erlaubte Ausfallminuten im Zeitraum, auf 2 Nachkommastellen gerundet. Beispiel:budget_minuten(0.999, 30)ist43.2.burn_rate(log, slo): Fehlerrate geteilt durch die erlaubte Fehlerrate, auf 2 Nachkommastellen gerundet. Leeres Log:0.0. Beispiel: 1 Fehler in 100 Requests bei SLO 0,99 ergibt1.0.stunden_bis_leer(burn, tage): nach wie vielen Stunden wäre ein volles Budget bei konstanter Burn Rate leer, auf 2 Nachkommastellen gerundet. Istburnnull oder kleiner, gibNonezurück. Beispiel:stunden_bis_leer(1, 30)ist720.0.
Die erlaubte Fehlerrate ist das Gegenstück zum SLO. Eine Burn Rate ist immer ein Verhältnis zweier Fehlerraten. Wie viele Minuten hat ein Tag?
def sli(log):
if not log:
return 1.0
ok = sum(1 for status in log if status < 500)
return ok / len(log)
def budget_minuten(slo, tage):
return round((1 - slo) * tage * 24 * 60, 2)
def burn_rate(log, slo):
return round((1 - sli(log)) / (1 - slo), 2)
def stunden_bis_leer(burn, tage):
if burn <= 0:
return None
return round(tage * 24 / burn, 2)
(sli, budget_minuten, burn_rate, stunden_bis_leer)Das Budget ist 1 - slo, nicht slo. Die Burn Rate teilt die tatsächliche Fehlerrate (1 - sli) durch die erlaubte (1 - slo). Bei Burn Rate 1 reicht das Budget genau für den Zeitraum, darum sind es tage * 24 Stunden geteilt durch burn. Status 404 ist Nutzerfehler und zählt nicht.
Übung 2: Kardinalität vorhersagen und den richtigen Alarm wählen (ca. 8 Min.)
Teil 1 bis 3, Kardinalität. Die Metrik http_requests_total hat die Labels endpoint (25 verschiedene Werte), method (4 Werte) und status (6 Werte). Gib die höchstmögliche Zahl von Zeitreihen an (jede Kombination kommt vor):
a: Zahl der Zeitreihen mit diesen drei Labels.b: Zahl der Zeitreihen, wenn ein Team zusätzlich das Labeluser_ideinführt, bei 8000 aktiven Nutzern.c: Zahl der Zeitreihen, wenn das Team stattuser_iddas Labelkundenklasseeinführt (3 Werte: free, pro, enterprise).
Teil 4, Alerting. Dein Checkout-Service hat ein SLO von 99,9 % Erfolgsquote in 30 Tagen. Welche Regel eignet sich am besten als Page (weckt den Bereitschaftsdienst nachts)?
- A Die CPU eines Pods liegt 5 Minuten lang über 80 %, und der Bereitschaftsdienst wird sofort gerufen.
- B Die Burn Rate der Serverfehler liegt sowohl im 5-Minuten-Fenster als auch im 1-Stunden-Fenster über 14,4.
- C Jeder einzelne HTTP-500-Fehler löst sofort eine Page aus, damit kein Fehler unbemerkt bleibt.
- D Der Speicherplatz der Datenbank ist zu 60 % belegt, und der Bereitschaftsdienst wird gerufen, bevor er ganz voll ist.
Trage ein Tupel (a, b, c, "Buchstabe") ein.
Teil 1 bis 3: Ergibt jedes Label einzeln eine Zeitreihe oder jede Kombination von Werten? Teil 4: Was soll eine Nacht-Page anzeigen, die Ursache oder die Wirkung auf Nutzer, und wie oft darf sie fälschlich auslösen?
antwort = (600, 4800000, 1800, "B")
antwortTeil 1 bis 3. Jede Kombination der Label-Werte ist eine eigene Zeitreihe, also wird multipliziert, nicht addiert: 25 mal 4 mal 6 ist 600. Mit user_id: 600 mal 8000 ist 4 800 000. Mit kundenklasse: 600 mal 3 ist 1800. Nutzer-IDs gehören in Logs und Traces, nicht in Metrik-Labels.
Teil 4, B (Symptom). Eine Burn Rate über 14,4 in zwei Fenstern bedeutet: Nutzer sind betroffen, das Budget verbrennt schnell, und es ist kein Ausreißer. Die CPU (A) kann hoch sein, ohne dass jemand etwas merkt, und fehlt bei vielen echten Ausfällen. Ein einzelner 500er (C) liegt im Budget, das du eingeplant hast, und weckt dich ständig. 60 % Speicher (D) ist eine Kapazitätswarnung für ein Ticket, kein Notfall.
Zusatzaufgabe: Blameless Postmortem schreiben (ca. 15 Min., ohne Check)
Fiktives Szenario: Am Freitag um 16:40 geht eine Konfigurationsänderung in Produktion. Sie setzt die maximale Zahl der Datenbankverbindungen eines Checkout-Services von 50 auf 5. Der Checkout antwortet 23 Minuten lang bei 38 % der Anfragen mit Fehler 500, bis ein Rollback läuft. Das SLO des Checkouts ist 99,9 % in 30 Tagen. Die Änderung hatte ein Code Review, lief aber ohne Canary durch, weil die Pipeline Konfigurationsänderungen direkt ausrollt.
Schreibe ein kurzes Postmortem (etwa 8 Zeilen) mit den Teilen: Zusammenfassung, Auswirkung (mit Zahl), Ursachen (mehrere, systemisch), was gut lief, Maßnahmen. Ohne den Namen oder die Rolle einer schuldigen Person.
Zusammenfassung. Eine Konfigurationsänderung reduzierte den Verbindungspool des Checkouts von 50 auf 5. Der Checkout war 23 Minuten lang für einen Teil der Kunden nicht nutzbar.
Auswirkung. 23 Minuten mal 38 % Fehlerquote sind rund 8,74 Fehlerminuten. Das SLO erlaubt 43,2 Minuten in 30 Tagen, also sind rund 20 % des Monatsbudgets verbraucht (8,74 geteilt durch 43,2 ist 0,202).
Ursachen (systemisch).
- Konfigurationsänderungen laufen ohne Canary und ohne automatische Abbruchregel direkt in die Produktion.
- Der Wert 5 wurde von keiner Prüfung als unplausibel erkannt (keine Validierung der Grenzen, kein Test unter Last).
- Der Alarm löste erst nach einer Weile aus. Der Burn-Rate-Alarm hätte die Änderung früher gezeigt als ein Kunde (bitte an der tatsächlichen Alarmzeit prüfen).
Was gut lief. Das Rollback war ein einzelner Befehl und funktionierte beim ersten Versuch.
Maßnahmen. Konfiguration durchläuft dieselbe Canary-Pipeline wie Code. Gültige Bereiche für Pool-Größen werden im Schema geprüft. Der Burn-Rate-Alarm wird mit der Auslösezeit dieses Vorfalls getestet. Ein Game Day übt den Rollback.
Selbstcheck.
Merksatz
Miss mit SLI, SLO und Error Budget, alarmiere auf Symptome und halte die Kardinalität der Labels klein, damit du nur dann geweckt wirst, wenn Nutzer es spüren, und lerne aus Vorfällen ohne Schuldigen.
Prüfstein
- Dein SLO ist 99,9 % in 30 Tagen, und die Burn Rate liegt seit einer Stunde bei 4. Was bedeutet das für das Budget, und würdest du nachts wecken?
- Warum macht ein Label mit der Nutzer-ID das Monitoring kaputt, und welcher Alarm ist besser als “CPU über 90 %”?
Zurück zu Teil 1: Stateless, Reconciliation und Deployments.
Quelle: quellen/konzeptuebersicht-software-grundlagen.md, Abschnitt “7. Verteilte Systeme und Betrieb” (Observability: Logs, Metriken, Traces, SLIs und SLOs; der Prüfstein dieses Abschnitts zum langsamen Downstream ist in konzepte/07a und 07b umgesetzt); quellen/konzeptuebersicht-software-fortgeschritten.docx, Schicht 7 “Observability” (Distributed Tracing, Kardinalität, SLOs und Error Budgets, Alerting auf Symptome) und “Incident-Kultur” (blameless Postmortems, Chaos Engineering, Game Days).
Über die Quelle hinaus (allgemeines Fachwissen): die Funktionsweise von Trace-IDs und Spans, OpenTelemetry (bitte prüfen), pino, winston und prom-client als JS-Bibliotheken (bitte prüfen), die Definitionen von SLI, SLO, Error Budget und Burn Rate, der Wert 14,4 samt Zwei-Fenster-Alarm aus dem SRE Workbook (bitte prüfen), die Ausgestaltung von Postmortem, Chaos Engineering und Game Day. Das Szenario des Postmortems ist erfunden. Alle Zahlen im Text stammen aus dem Ausführen des Codes dieser Lektion (Python 3), nicht aus Messungen realer Systeme.