Zero-Downtime-Deployments auf Kubernetes: Readiness, Rolling Update und Rollback
Der Rollout war grün, trotzdem sahen Nutzer 20 Sekunden lang 502-Fehler. Was ein Rolling Update allein nicht leistet: Readiness, sauberes Beenden, Disruption Budgets, Migrationen in zwei Schritten und ein Rollback auf eine gepinnte Version.

Freitag, 14 Uhr, ein Release der Bestell-API mit zwei Replicas. Kubernetes meldet den Rollout als erfolgreich, das Monitoring zeigt trotzdem 20 Sekunden lang 502-Fehler am Ingress. Zwei Ursachen, die fast jedes Team einmal trifft: Der neue Pod bekam Traffic, bevor die Anwendung ihre Konfiguration geladen hatte, und der alte wurde beendet, während noch Anfragen liefen.
Ein Zero-Downtime-Deployment ist ein Rollout, bei dem während des gesamten Wechsels jede Anfrage von einer Version beantwortet wird, die bereit ist – ohne abgebrochene Verbindungen, ohne Fehlerseiten. Kubernetes liefert die Bausteine, aber nicht alle sind von Haus aus passend eingestellt.
Was leistet ein Rolling Update – und was nicht?
RollingUpdate ist die Standardstrategie eines Deployments. maxSurge legt fest, wie viele Pods zusätzlich entstehen dürfen, maxUnavailable, wie viele fehlen dürfen; beide stehen standardmäßig auf 25 %, der erste aufgerundet, der zweite abgerundet. Bei einem Replica heißt das: ein Pod zusätzlich, keiner fehlt – der alte geht erst, wenn der neue bereit ist. Bei vier Replicas darf einer fehlen; wer das nicht will, setzt maxUnavailable: 0.
„Bereit“ heißt: Die Readiness-Probe war erfolgreich. Ein Container ohne Probe gilt als bereit, sobald er läuft – und genau dann kommt der erste 502.
Readiness, Liveness, Startup: Welche Probe wofür?
- Readiness entscheidet über Traffic. Schlägt sie fehl, nimmt Kubernetes den Pod aus den EndpointSlices seiner Services; er läuft weiter, bekommt aber keine Anfragen.
- Liveness entscheidet über Neustarts, etwa nach einem Deadlock. Sie wartet nicht auf die Readiness und startet eine langsam bootende Anwendung ohne Verzögerung in einer Schleife neu.
- Startup schützt langsame Starter: Bis sie erfolgreich war, laufen die anderen beiden nicht.
Eine Liveness-Probe, die die Datenbank prüft, startet bei einem Datenbank-Hänger alle Pods zugleich neu – die Kubernetes-Doku warnt ausdrücklich vor solchen Kaskaden. Und ein TCP-Check zeigt nur, dass der Port offen ist; ein HTTP-Check auf /ready weiß, ob Caches und Verbindungen stehen.
Wie beende ich einen Pod, ohne Anfragen zu verlieren?
Beim Beenden schickt das Kubelet SIGTERM an den Hauptprozess, wartet die terminationGracePeriodSeconds ab – standardmäßig 30 Sekunden – und schickt dann SIGKILL. Gleichzeitig, nicht vorher, nimmt die Control Plane den Pod aus den EndpointSlices; Ingress-Controller erfahren davon mit Verzögerung und schicken noch kurz Anfragen an einen Prozess, der schon herunterfährt.
- Ein
preStop-Hook mit wenigen Sekunden Pause überbrückt das, seit Kubernetes 1.30 ohne Shell im Image:preStop: {sleep: {seconds: 5}}. - Die Anwendung nimmt nach SIGTERM keine neuen Verbindungen an, beantwortet laufende Anfragen und beendet sich – alles innerhalb der Grace Period.
- Der Prozess muss das Signal bekommen: Die Shell-Form von ENTRYPOINT startet ihn als Kind von
/bin/sh -c, und die Shell reicht Signale nicht weiter. Die exec-Form vermeidet das.
Node-Drains: Wozu ein PodDisruptionBudget?
Node-Upgrades und das Verkleinern eines Pools leeren Nodes; Werkzeuge wie kubectl drain nutzen dafür die Eviction-API. Ein PodDisruptionBudget legt fest, wie viele Pods einer Anwendung dabei gleichzeitig fehlen dürfen – Rolling Updates bremst es nicht.
- Ab zwei Replicas:
maxUnavailable: 1– der Drain verschiebt einen Pod nach dem anderen. - Nie ein Budget ohne erlaubte Unterbrechung: Dann wird der Drain nie fertig.
- Bei einem Replica hilft kein Budget; wer keine Lücke will, braucht zwei.
Datenbankmigrationen: erst erweitern, dann aufräumen
Während eines Rolling Updates laufen alte und neue Version gegen dieselbe Datenbank. Passt das Schema nur zur neuen, hilft keine Probe. Das Gegenmittel heißt Expand/Contract oder Parallel Change:
- Expand: neue Spalte oder Tabelle hinzufügen, nullable oder mit Default – die alte Version merkt nichts.
- Migrate: Code ausrollen, der beides schreibt und das Neue liest; Altbestände nachfüllen.
- Contract: erst im nächsten Release das Alte entfernen.
Ein Umbenennen wird damit zu drei Releases, jedes einzeln zurückrollbar.
Wann eine kurze Pause unvermeidbar ist
Ein ReadWriteOnce-Volume hängt an genau einem Node. Landet der neue Pod auf einem anderen, kann er es nicht einbinden, solange der alte es hält – der Rollout steht. Solche Dienste nutzen Recreate: Erst gehen die alten Pods, dann startet der neue. Die Pause dauert, bis das Volume umgehängt und die Anwendung gestartet ist; planen Sie sie ein. Mehr dazu in Persistente Volumes auf Kubernetes: ReadWriteOnce, Recreate und der Snapshot vor dem Löschen.
Rollback – und wann Canary oder Blue-Green lohnen
kubectl rollout undo setzt auf das vorige ReplicaSet zurück. Zeigt das Template aber auf einen Tag, der inzwischen ein anderes Image meint, kommt nicht die alte Version zurück. Ein Rollback ist nur einer, wenn er auf einen Digest zeigt – mehr in Rollback auf Kubernetes: Warum ein Tag keine Version ist.
Canary und Blue-Green gehen weiter: Ein kleiner Teil des Traffics läuft auf die neue Version, oder eine zweite Umgebung wartet auf den Umschalter – etwa mit Argo Rollouts, Flagger oder gewichteten Routen im Gateway API. Das lohnt sich, wenn 5 % Ihres Traffics in Minuten aussagekräftige Fehlerraten liefern und Metriken automatisch entscheiden. Für die meisten Teams ohne Platform-Team bringen saubere Probes, Shutdown und Migrationen mehr.
Was Clusterward davon übernimmt – und was nicht
Clusterward rollt Git- und Container-Services als Deployment mit Rolling Update und den Kubernetes-Standardwerten aus. Jeder Container bekommt eine Readiness-Probe als TCP-Check auf seinen Port (erste Prüfung nach 5 Sekunden, dann alle 10, nach drei Fehlschlägen nicht bereit). Gesund ist ein Deployment erst, wenn jede Instanz der neuen Version Verbindungen annimmt und die alten weg sind; schafft die neue Version das nicht innerhalb des Readiness-Timeouts – Standard 120 Sekunden, pro Service bis 3.600 einstellbar –, gilt es als fehlgeschlagen, und die Meldung sagt, dass der Rollout im Cluster weiterläuft. Services mit Volume laufen mit einer Instanz und Recreate (Volumes & Snapshots). Rollouts aus der Scaleway-Registry sind auf den Digest gepinnt; „Restore this version…“ in der Deployment-Historie holt genau dieses Image zurück (Deployments).
Was es nicht gibt: Canary oder Blue-Green, einstellbare Liveness- oder Startup-Probes, einen HTTP-Pfad für die Readiness, preStop-Hook oder längere Grace Period und PodDisruptionBudgets für Git- und Container-Services. Ihre Anwendung muss SIGTERM also selbst sauber behandeln. Ein Helm-Chart-Service rendert seine Objekte selbst und kann eigene Probes und ein Budget mitbringen.
Fazit
Ohne Ausfall auszurollen ist vor allem eine Frage der Details: eine Readiness-Probe, die wirklich Bereitschaft meint, ein Shutdown, der Anfragen zu Ende bringt, ein Budget für Drains und Migrationen, die zwei Versionen vertragen. Wo ein Volume an einem Node hängt, bleibt eine kurze Pause – die ehrliche Antwort ist, sie einzuplanen.
Releases ohne 502? Beschreiben Sie uns, wie Ihre Anwendung heute startet und herunterfährt. Wir sagen Ihnen, wo die Lücke im Rollout steckt. Frage stellen →
Quellen und weiterführende Links
Häufige Fragen
- Ein Rollout, bei dem während des ganzen Wechsels jede Anfrage von einer bereiten Version beantwortet wird. Dafür braucht es ein Rolling Update, eine Readiness-Probe, die echte Bereitschaft prüft, ein sauberes Beenden alter Pods mit SIGTERM und kurzer Pause sowie Datenbankmigrationen, die alte und neue Version zugleich vertragen.