Clusterward
← Zurück zum Blog
BetriebAktualisiert Florian Apel

Rollback auf Kubernetes: Warum ein Tag keine Version ist

Ein Rollback, der dasselbe Tag neu zieht, holt die kaputte Version zurück. Wer zuverlässig zurück will, braucht den Digest jeder Auslieferung, und einen Plan für die Datenbank.

Titelbild: Rollback auf Kubernetes: Warum ein Tag keine Version ist

Freitagnachmittag, ein Release geht raus, die Fehlerrate steigt. Der Griff zum Rollback ist reflexartig: kubectl rollout undo. Kubernetes meldet Erfolg, die Pods starten neu, und die Fehlerrate bleibt. Der Rollback hat funktioniert, nur hat er nichts zurückgeholt. Der Grund steckt in einer Zeile des Manifests: image: registry/shop:main.

Ein Tag ist ein Zeiger

Ein Image-Tag wie main, latest oder v2 ist ein veränderlicher Zeiger. Jeder Build, der dasselbe Tag pusht, verschiebt ihn. kubectl rollout undo stellt die vorherige Pod-Vorlage wieder her, und in der steht dasselbe Tag. Die Nodes ziehen das Image neu, bei imagePullPolicy: Always oder auf einem frischen Node sicher, und bekommen die neue, kaputte Version. Kubernetes hat genau das getan, was im Manifest stand.

Unveränderlich ist nur der Digest, die Prüfsumme des Image-Manifests: registry/shop@sha256:4f1c…. Ein Digest zeigt immer auf dasselbe Image, egal wohin ein Tag später wandert.

Drei Regeln für Rollbacks, die zurückholen

  1. Jede Auslieferung hält den Digest fest. Nicht das Tag, das im Build stand, sondern den Digest, auf den es in dem Moment zeigte. Wer ihn in der Pod-Vorlage ausrollt, rollt bei einem Undo auch wirklich die alte Version aus.
  2. Jeder Build bekommt zusätzlich ein festes Tag. Etwa sha-<commit>. Das Tag main darf weiter wandern, aber jede Version bleibt unter einem Namen auffindbar, den niemand überschreibt.
  3. Ein Neustart zieht nicht still eine neue Version. Wer Umgebungsvariablen ändert und neu startet, erwartet dieselbe Version mit neuer Konfiguration. Zeigt das Tag inzwischen woanders hin, kommt ohne Absicht ein neuer Build mit.

Helm macht es anders, aber nicht vollständig

helm rollback stellt Chart-Version und Values einer früheren Revision wieder her, und Helm hält die Historie in Secrets im Namespace. Das ist ein echter Schritt zurück für alles, was im Chart steht. Steht im Chart aber tag: main, gilt dasselbe wie oben: Die Values kommen zurück, das Image nicht unbedingt.

Was kein Rollback zurückholt

Das wichtigste Kapitel, weil es am häufigsten schiefgeht.

Die Datenbank. Hat das neue Release eine Migration ausgeführt, eine Spalte gelöscht oder umbenannt, läuft die alte Version gegen ein Schema, das sie nicht kennt. Der Rollback der Anwendung wird zum zweiten Ausfall. Die Antwort sind Migrationen in zwei Schritten: erst erweitern (neue Spalte, alte bleibt), ausrollen, und erst im nächsten Release aufräumen. Dann kann jede Version gegen das Schema der nächsten laufen.

Konfiguration und Secrets. Ein Rollback des Images lässt Umgebungsvariablen, Secrets und Domains, wie sie sind. Meist ist das richtig, denn ein rotierter Schlüssel soll nicht zurückrotiert werden. Aber es heißt: Wer mit dem Release auch Konfiguration geändert hat, muss sie selbst zurückdrehen.

Daten auf Volumes. Was die neue Version geschrieben hat, bleibt geschrieben. Dafür gibt es Snapshots, nicht Rollbacks.

Ein Rollback in der Praxis

So sieht ein guter Rollback aus, in dieser Reihenfolge:

  1. In der Historie die letzte gesunde Auslieferung finden, mit ihrem Digest.
  2. Prüfen, ob das fehlerhafte Release eine Migration enthielt. Wenn ja: Ist das alte Schema noch kompatibel?
  3. Genau diesen Digest ausrollen, ohne neuen Build.
  4. Fehlerrate und Logs der Instanzen ansehen, bis sie stabil sind.
  5. Den Fehler im Code beheben und normal neu ausliefern, statt den Rollback-Zustand wochenlang zu halten.

Tags, Digests und Build-Pipelines

Den Digest bekommt man an drei Stellen, und keine davon ist aufwendig:

  • Beim Build. docker buildx build --metadata-file meta.json schreibt den Digest des gepushten Images in eine Datei. Die Pipeline gibt ihn an das Deployment weiter.
  • Aus der Registry. Jede Registry nach dem Docker-Standard liefert den Digest zu einem Tag im Header Docker-Content-Digest. Werkzeuge wie crane digest registry/shop:main fragen genau das ab.
  • Aus dem Cluster. Der Status eines laufenden Pods enthält unter imageID den Digest, den der Node tatsächlich gezogen hat. Das ist der ehrlichste Beleg dafür, was gerade läuft.

Wichtig ist, dass der Digest dort gespeichert wird, wo man ihn im Ernstfall sucht: in der Deploy-Historie, neben Zeitpunkt, Commit und der Person, die ausgerollt hat.

Migrationen, die einen Rollback überleben

Ein Beispiel macht das Muster klar. Eine Spalte name soll in first_name und last_name aufgeteilt werden.

  1. Release A: erweitern. Neue Spalten anlegen, die Anwendung schreibt in alte und neue, liest weiter aus der alten. Ein Rollback von A ist harmlos, die alte Version ignoriert die neuen Spalten.
  2. Datenübernahme. Bestehende Zeilen füllen, im Hintergrund, in kleinen Stapeln.
  3. Release B: umstellen. Die Anwendung liest aus den neuen Spalten und schreibt weiter in beide. Ein Rollback auf A funktioniert, weil die alte Spalte noch gepflegt wird.
  4. Release C: aufräumen. Erst wenn B eine Weile stabil lief, entfällt das Schreiben in die alte Spalte, und eine spätere Migration löscht sie.

Das sind drei Releases statt einem. Dafür ist jeder einzelne Schritt umkehrbar, und kein Rollback trifft auf ein Schema, das die alte Version nicht versteht.

Rollback oder Fix nach vorn?

Nicht jeder Fehler braucht einen Rollback. Die Faustregel: Wenn Nutzer gerade betroffen sind und die Ursache nicht in Minuten klar ist, zurück zur letzten gesunden Version. Wenn der Fehler eng begrenzt ist, der Fix klein und die Pipeline schnell, kann ein Fix nach vorn der kürzere Weg sein. Was nie gut geht: eine halbe Stunde lang in der Produktion nach der Ursache suchen, während Nutzer Fehler sehen. Erst stabilisieren, dann verstehen.

Wie Clusterward das umsetzt

Clusterward rollt jede Auslieferung eines Images aus der Scaleway Container Registry mit dem Digest aus, den das Tag in diesem Moment hatte, und hält ihn in der Deploy-Historie fest. Neue Builds bekommen zusätzlich ein festes sha--Tag. „Diese Version wiederherstellen“ rollt genau das Image einer früheren gesunden Auslieferung aus, ohne Build; bei Helm-Services Chart-Version und Values. Ein Neustart behält das laufende Image, statt ein verschobenes Tag zu ziehen. Konfiguration, Secrets, Domains, Volumes und die Datenbank bleiben bewusst, wie sie sind, und der Dialog sagt das vorher. Mehr unter Deployments; wie Datenbanken und Volumes zurückkommen, unter Backups & Wiederherstellung. Ob der Rollback gewirkt hat, zeigen die Logs aller Instanzen unter Logs & Monitoring.

Fazit

Ein Rollback ist nur so gut wie die Version, auf die er zeigt. Rollen Sie Digests aus statt Tags, geben Sie jedem Build ein festes Tag und planen Sie Migrationen so, dass die alte Version mit dem neuen Schema leben kann. Dann ist der Freitagnachmittag ein Klick und kein Abend.

Ihre Rollbacks absichern? Beschreiben Sie uns Ihren Build und Ihr Deployment. Wir sagen Ihnen, an welcher Stelle ein Rollback heute ins Leere greift. Frage stellen →

Quellen und weiterführende Links

Häufige Fragen

  • Weil in der vorherigen Pod-Vorlage dasselbe veränderliche Tag steht, etwa image: registry/shop:main. Ziehen die Nodes das Image neu, bei imagePullPolicy: Always oder auf einem frischen Node sicher, bekommen sie den neuen, kaputten Build. Kubernetes tut genau, was im Manifest steht. Zuverlässig zurück geht es nur mit dem Digest.