Wenn eine grüne Pipeline keine gesunde Bereitstellung bedeutet

Sie haben gerade ein Deployment abgeschlossen. Die Pipeline zeigt grün. Jeder Build-Schritt war erfolgreich, jeder Test lief sauber, und das Deploy-Script wurde ohne einen einzigen Fehler beendet. Sie machen Ihren Laptop zu und fühlen sich gut.

Dann kommt die erste Benutzermeldung. Die App lädt langsam. Einige Anfragen schlagen fehl. Wenige Minuten später ist der Datenbank-Verbindungspool erschöpft, und die App ist praktisch down.

Was ist passiert? Die Pipeline sagte, alles sei in Ordnung.

Dieses Szenario ist häufiger, als die meisten Teams zugeben möchten. Ein erfolgreicher Build beweist nur, dass Ihr Code kompilieren oder paketieren kann. Er beweist nicht, dass Ihre Anwendung tatsächlich Anfragen empfangen, sich mit ihrer Datenbank verbinden oder korrekte Antworten zurückgeben kann. Es gibt eine Lücke zwischen „das Deployment ist abgeschlossen“ und „die Anwendung funktioniert“. Diese Lücke ist der Ort, an dem Health Signals ins Spiel kommen.

Was ein Health Signal tatsächlich aussagt

Ein Health Signal ist die Art und Weise, wie Ihre Anwendung ihren eigenen Zustand meldet. Die häufigste Form ist ein Health-Endpoint: eine dedizierte URL, die Ihre Pipeline, Ihr Load Balancer oder Ihr Betriebsteam aufrufen kann, um zu prüfen, ob die App funktioniert. Sie haben wahrscheinlich schon Endpoints mit den Namen /health oder /healthz gesehen. Bei Aufruf gibt eine gesunde Anwendung HTTP 200 zurück. Eine ungesunde gibt 500 oder einen anderen Fehlercode zurück.

Aber der wahre Wert liegt nicht im Endpoint selbst. Er liegt darin, was der Endpoint tatsächlich prüft. Ein Health-Endpoint, der immer 200 zurückgibt, unabhängig vom tatsächlichen Zustand der Anwendung, ist schlimmer als gar kein Health Check. Er erzeugt falsches Vertrauen. Ihre Pipeline denkt, das Deployment sei erfolgreich, aber Ihre Benutzer stoßen bereits auf Fehler.

Readiness vs. Liveness: Zwei unterschiedliche Fragen

Es gibt zwei verschiedene Arten von Health Checks, und sie beantworten unterschiedliche Fragen.

Das folgende Flussdiagramm veranschaulicht den Unterschied zwischen Liveness- und Readiness-Checks und wie sie Entscheidungen beim Deployment leiten:

flowchart TD A[Health Check Request] --> B{Is the app process running?} B -->|No| C[Liveness fails: Restart container] B -->|Yes| D{Is the app ready to serve traffic?} D -->|No| E[Readiness fails: Remove from load balancer] D -->|Yes| F[Readiness passes: Send traffic] C --> G[Automatic recovery attempt] E --> H[Wait and retry readiness] F --> I[App serves users normally] H --> D G --> B

Readiness teilt dem System mit, ob die Anwendung bereit ist, Traffic anzunehmen. Wenn eine Anwendung gerade gestartet ist, benötigt sie möglicherweise ein paar Sekunden, um eine Verbindung zur Datenbank herzustellen, den Cache zu laden oder Verbindungen aufzuwärmen. Während dieser Zeit sollte die App sich selbst als „nicht bereit“ melden. Der Load Balancer oder Orchestrator hält dann Anfragen zurück, bis die App signalisiert, dass sie bereit ist. Ohne einen ordnungsgemäßen Readiness-Check könnten Benutzer auf eine halb initialisierte Anwendung treffen, die Fehler oder Timeouts zurückgibt.

Liveness teilt dem System mit, ob die Anwendung noch lebt und verarbeitet. Wenn die Anwendung in einen Deadlock gerät, der Speicher ausgeht oder in einen Zustand gerät, in dem sie keine Arbeit mehr erledigen kann, erkennt der Liveness-Check dies. In containerisierten Umgebungen wie Kubernetes löst ein fehlgeschlagener Liveness-Check typischerweise einen automatischen Neustart aus.

Beide Checks dienen unterschiedlichen Zwecken in Ihrer Deployment-Pipeline. Wenn Sie ein Deployment durchführen, ruft die Pipeline normalerweise zuerst den Readiness-Check auf. Wenn die neue Version nicht innerhalb einer angemessenen Zeit bereit wird, kann die Pipeline sofort entscheiden, ein Rollback durchzuführen. Das ist weitaus besser, als eine halbfertige Version für Benutzer bereitzustellen. Liveness-Checks hingegen sind nach Abschluss des Deployments nützlicher. Sie halten die Anwendung über die Zeit hinweg gesund.

Hier ist ein praktisches YAML-Beispiel, das beide Probes für ein Kubernetes-Deployment konfiguriert:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    spec:
      containers:
      - name: app
        image: my-app:1.0.0
        ports:
        - containerPort: 8080
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
          failureThreshold: 3
        livenessProbe:
          httpGet:
            path: /live
            port: 8080
          initialDelaySeconds: 15
          periodSeconds: 20
          failureThreshold: 3

In diesem Beispiel prüft der Readiness-Probe /ready alle 10 Sekunden nach einer anfänglichen Verzögerung von 5 Sekunden. Wenn er dreimal fehlschlägt, stoppt Kubernetes den Traffic zum Pod. Der Liveness-Probe prüft /live seltener und startet den Container neu, wenn er fehlschlägt.

Was ein guter Health Check tatsächlich prüft

Ein Health Check, der einfach nur 200 zurückgibt, ohne etwas zu überprüfen, ist eine Dekoration, kein Signal. Ein sinnvoller Health Check sollte die Komponenten testen, die für die Funktion Ihrer Anwendung wichtig sind:

  • Datenbank-Konnektivität: Kann die App die Datenbank erreichen und eine einfache Abfrage ausführen?
  • Kritische externe APIs: Sind die Dienste, von denen Ihre App abhängt, verfügbar?
  • Interne Ressourcen: Ist der Thread-Pool gesund? Liegt die Speichernutzung innerhalb der Grenzen?

Aber es gibt einen Zielkonflikt. Ein Health Check, der bei jedem Aufruf jede Abhängigkeit testet, kann zur Belastung für das System werden. Wenn Ihre Pipeline oder Ihr Load Balancer den Endpoint alle paar Sekunden aufruft, kann ein schwerer Check die Leistung beeinträchtigen oder sogar kaskadierende Ausfälle verursachen.

Ein gängiges Muster ist, Liveness-Checks leichtgewichtig zu halten: einfach bestätigen, dass der Prozess läuft. Readiness-Checks können tiefer gehen, da sie seltener aufgerufen werden und ihr Ergebnis direkt beeinflusst, ob Traffic zur Instanz geleitet wird.

Health Signals bei progressiven Deployment-Strategien

Health Signals werden noch wichtiger, wenn Sie Deployment-Strategien wie Canary oder Blue-Green verwenden. Stellen Sie sich vor, Sie rollen eine neue Version für eine kleine Untergruppe von Benutzern aus. Ihre Pipeline kann den Health-Endpoint dieser neuen Version überwachen. Wenn der Health Check Fehler anzeigt oder die Antwortzeit steigt, kann die Pipeline den Traffic automatisch zurück zur alten Version leiten.

Ohne Health Signals sind Sie auf Benutzermeldungen angewiesen. Benutzermeldungen sind wertvoll, aber sie kommen spät. Bis jemand einen Fehlerbericht einreicht, sind möglicherweise bereits viele Benutzer betroffen. Ein Health Check, der alle paar Sekunden läuft, kann Probleme innerhalb von Sekunden erkennen, nicht Minuten oder Stunden.

Was passiert, wenn Health Checks fehlen oder schwach sind

Teams, die ordnungsgemäße Health Checks auslassen, entdecken Probleme oft auf die harte Tour. Ein Deployment gelingt, aber die neue Version kann keine Verbindung zur Datenbank herstellen, weil sich eine Anmeldeinformation geändert hat. Die Pipeline meldet Erfolg. Benutzer sehen Fehler. Jemand muss manuell nachforschen, das Problem erkennen und ein Rollback auslösen. Dieser Prozess braucht Zeit, und während dieser Zeit ist die Anwendung beeinträchtigt.

Das Gleiche gilt für Abhängigkeiten. Wenn Ihre Anwendung von einer externen API abhängt und diese API ausfällt, wird ein guter Health Check die Anwendung als ungesund melden. Ein schwacher Health Check meldet sie als gesund, und Ihre Benutzer erleben Fehler, während Ihr Monitoring-Dashboard grün anzeigt.

Eine kurze praktische Checkliste

Wenn Sie Health Checks für Ihre Anwendung einrichten, hier eine kurze Liste von Dingen, die Sie überprüfen sollten:

  • Prüft Ihr Health-Endpoint tatsächlich etwas Sinnvolles oder gibt er nur 200 zurück?
  • Haben Sie separate Readiness- und Liveness-Checks mit unterschiedlichen Tiefen?
  • Nutzt Ihre Pipeline den Readiness-Check, um zu entscheiden, ob das Deployment fortgesetzt oder ein Rollback durchgeführt wird?
  • Sind Ihre Health Checks leichtgewichtig genug, dass sie die Leistung nicht beeinträchtigen, wenn sie häufig aufgerufen werden?
  • Nutzen Ihre progressiven Deployment-Strategien Health Signals, um Probleme frühzeitig zu erkennen?

Der wahre Test eines Deployments

Eine grüne Pipeline ist kein Beweis dafür, dass Ihre Anwendung funktioniert. Sie ist ein Beweis dafür, dass Ihr Build- und Deploy-Prozess fehlerfrei gelaufen ist. Der wahre Test kommt nach dem Deployment, wenn Traffic auf die neue Version trifft. Health Signals sind die Brücke zwischen „das Deployment ist abgeschlossen“ und „die Anwendung bedient die Benutzer tatsächlich korrekt“.

Wenn Ihre Pipeline innerhalb von Sekunden erkennen kann, dass eine neue Version nicht gesund ist, und automatisch ein Rollback durchführt, haben Sie sich davon verabschiedet, zu hoffen, dass Deployments gut gehen, und wissen jetzt, dass sie sicher sind. Das ist der Unterschied zwischen einem Deployment, das auf dem Papier gut aussieht, und einem, das tatsächlich in der Produktion funktioniert.