Be Software Architecture Wise
Be Wise Apps

Read in English · Leer en español · Lire en français

Abschnitt 10.5 von 10.8 · Mittelstufe · 22 Min. Lesezeit

CI/CD-Pipelines und Deployment-Strategien

Videolektion

5 Min. · auf Englisch gesprochen, mit Untertiteln
Nur anhören (Audio)
Transkript lesen

Wie schnell und sicher kann Ihr Team etwas ändern? Das entscheidet die Deployment-Pipeline. In dieser Lektion verfolgen Sie eine Änderung vom Commit bis in die Produktion und lernen die Strategien kennen, die den Schaden einer schlechten Version begrenzen.

Stellen Sie sich eine Bäckereikette vor, die ein neues Brot einführt. Sie backt eine Testcharge und prüft sie in der eigenen Backstube. Dann verkauft sie es einen Vormittag lang in einer Filiale, bevor sie es an alle Filialen schickt. Beschweren sich Kunden, war nur eine Filiale betroffen, und das alte Brot liegt noch in den Regalen. Eine Pipeline ist diese Routine, automatisiert: Jede Änderung wird einmal gebaut, in Stufen geprüft, an wenigen Nutzern ausprobiert und erst verteilt, wenn die Belege gut sind. Und ein separater Schalter entscheidet, wann Kunden ein neues Feature sehen.

Die Deployment-Pipeline, 2010 von Jez Humble und David Farley beschrieben, schickt jeden Commit durch automatisierte Stufen, die schnellsten zuerst. Die Commit-Stufe kompiliert, führt Unit-Tests und Prüfungen aus und sollte unter zehn Minuten dauern. Die Paketstufe baut ein Container-Image mit einer Software Bill of Materials, signiert es und pusht es ins Artefakt-Repository, und zwar einmal. Akzeptanztests, Staging und Produktion deployen dann alle genau dieses Image. Eine Änderung rückt nur vor, wenn die vorige Stufe bestanden ist. Das ist Build once, deploy many. Zwischen den Umgebungen unterscheidet sich nur die Konfiguration. Wenn Sie für die Produktion neu bauen, ist das Getestete nicht das Ausgelieferte. Und jeder Fehlschlag stoppt das Band und geht direkt an den Autor zurück, solange die Änderung noch frisch im Gedächtnis ist.

Eine Deployment-Strategie entscheidet, wie vielen Nutzern eine schlechte Version schaden kann, bevor sie gestoppt wird. Recreate stoppt alle alten Instanzen und startet dann die neuen: einfach, aber mit Ausfallzeit, und alle treffen sofort auf eine schlechte Version. Rolling ersetzt Instanzen jeweils zu wenigen und ist der Standard in Kubernetes. Das Zurückrollen dauert so lange wie der Rollout. Blue-Green betreibt eine vollständige neue Umgebung neben der Live-Umgebung, testet sie und schaltet dann den gesamten Traffic am Router um. Das Zurückrollen geht schnell, aber während des Wechsels braucht man bis zu doppelte Kapazität. Ein Canary schickt einen kleinen Anteil des Traffics, etwa ein bis fünf Prozent, an die neue Version, vergleicht ihre Metriken und weitet dann schrittweise aus. Ein Shadow kopiert echte Anfragen an die neue Version, gibt deren Antworten aber nie zurück, daher müssen Seiteneffekte wie Zahlungen unterdrückt werden. Wann immer zwei Versionen gleichzeitig laufen, müssen sie mit den Daten und Nachrichten der jeweils anderen kompatibel sein.

Hier ist ein Canary mit automatisierter Analyse. Nutzer erreichen einen Traffic-Router: einen Load Balancer oder ein Service Mesh. Neunzig Prozent des Traffics gehen an die Produktionsflotte mit Version eins. Fünf Prozent gehen an eine frische Baseline von Version eins und fünf Prozent an den Canary, Version zwei. Der Vergleich mit einer frischen Baseline beseitigt Unterschiede, die nur durch warme Caches und lange Laufzeit entstehen. Ein Analyseschritt vergleicht Fehler, Latenz und Sättigung und weitet den Canary dann auf fünfundzwanzig Prozent aus oder rollt ihn zurück. Das System entscheidet, nicht eine Person vor Dashboards. Das ist Progressive Delivery.

Das Deployment installiert eine neue Version in einer Umgebung. Das Release macht ein Verhalten für Nutzer verfügbar. Feature-Flags trennen beides: Der Code wird ausgeschaltet deployt und später schrittweise und umkehrbar freigegeben. Jedes Flag verursacht laufende Kosten, also geben Sie Flags ein Ablaufdatum und löschen Sie sie, sobald sie entschieden sind. Und weil sich Daten nicht wie Code zurückrollen lassen, müssen Schemaänderungen abwärtskompatibel sein: zuerst Expand, und Contract erst in einem späteren Release.

Fügen wir alles zusammen. Der Bestellservice ändert die Berechnung der Liefergebühren. Der neue Rechner steckt hinter einem ausgeschalteten Release-Flag, und eine reine Expand-Migration fügt eine neue Spalte hinzu. Die Änderung wird um zwei Minuten nach zehn gemergt. Lint, Unit-Tests und Scans dauern sechs Minuten, und um neun Minuten nach wird ein signiertes Image gepusht. Die additive Migration läuft um Viertel nach zehn als eigener Schritt. Die laufende Version ignoriert die neue Spalte, also bricht nichts. Dann besteht dasselbe Image die Staging-Tests. Um zehn Uhr fünfunddreißig gehen fünf Prozent des Produktionstraffics an die neue Version, mit noch ausgeschaltetem Flag. Zwanzig Minuten Analyse gegen eine frische Baseline: bestanden. Der Traffic steigt in Fünfzehn-Minuten-Schritten auf fünfundzwanzig, fünfzig und hundert Prozent und ist um elf Uhr vierzig fertig. Das Deployment ist abgeschlossen, und doch hat kein Kunde die neue Gebühr gesehen. Am nächsten Tag schaltet die Produktmanagerin das Flag für zehn Prozent der Kunden in einer Stadt ein und weitet es dann im Laufe einer Woche auf alle Städte aus. Deployment-Risiko und Release-Risiko wurden getrennt behandelt, jedes mit kleinem Blast Radius.

Der vollständige Abschnitt behandelt Trunk-Based Development, die vier Arten von Feature-Flags und wann man zurück- oder vorwärtsrollt. Als Nächstes, in Abschnitt zehn Punkt sechs, betrachten wir den Betrieb über mehrere Regionen. Bis gleich.

Was Sie wissen müssen

Vom Commit bis in die Produktion: wozu eine Pipeline da ist

Abschnitt 0.8 (Wie Software entsteht) hat Continuous Integration (jede Änderung wird automatisch zusammengeführt und geprüft), Continuous Delivery (der Hauptbranch ist jederzeit releasefähig) und Continuous Deployment (jede Änderung, die die Prüfungen besteht, geht ohne menschliche Entscheidung in Produktion) eingeführt. Dieser Abschnitt behandelt sie als Architektur: als Gestaltung des Wegs, den eine Änderung nimmt, und der Strategien, die sie in Produktion bringen, ohne Nutzern zu schaden.

Die zentrale Idee ist die Deployment-Pipeline, beschrieben von Jez Humble und David Farley in Continuous Delivery (2010). Jeder Commit löst eine automatisierte Folge von Stufen aus. Frühe Stufen sind schnell und günstig und fangen die meisten Probleme ab; spätere Stufen sind langsamer, realistischer und teurer. Eine Änderung gelangt nur dann in die nächste Stufe, wenn die vorige bestanden wurde; je weiter ein Build kommt, desto mehr Vertrauen hat er sich also verdient. Ein Fehlschlag an beliebiger Stelle stoppt diesen Build und geht direkt an die Person zurück, die die Änderung gemacht hat, solange sie ihr noch frisch im Gedächtnis ist.

Für Architekten ist die Pipeline aus drei Gründen wichtig. Erstens wird hier die Deploybarkeit, ein Qualitätsmerkmal aus Abschnitt 2.6, tatsächlich erreicht oder verspielt. Zweitens begrenzt ihre Geschwindigkeit, wie schnell die Organisation auf eine Marktveränderung oder eine Sicherheitslücke reagieren kann: Braucht ein einzeiliger Fix zwei Tage bis in die Produktion, ist die Architektur zwei Tage langsam, wie auch immer der Code aussieht. Drittens bestimmt die Gestalt des Systems die Gestalt der Pipeline: Unabhängig deploybare Services können unabhängige Pipelines haben, aber ein verteilter Monolith erzwingt koordinierte Releases, wie clever die Werkzeuge auch sein mögen.

Die Stufen einer typischen Pipeline

Eine Deployment-Pipeline: Commit, Build, Paket, Akzeptanztests, Staging und Produktion, mit einem Artefakt, das einmal in ein Repository gepusht und von jeder späteren Stufe gepullt wirdCommitPush auf mainoder PR mergenBuildCompile, Unit-Tests, LintPaketImage + SBOMSign, PushAkzeptanzAPI- undVertragstestsStagingDeploy, Smoke-TestsProduktionCanary, dannvoller RolloutJede Stufe ist automatisiert; eine Änderung rückt nur vor, wenn die vorige bestanden istArtefakt-Repositoryunveränderliches Image pro Commit, per Digest adressiert1× pushendasselbe Image pullenJeder Fehlschlag stoppt das Band und benachrichtigt den Autor in Minuten
Ein Artefakt wird einmal gebaut und gepusht; jede spätere Stufe deployt genau dieses Artefakt, und jeder Fehlschlag stoppt das Band.

Was jede Stufe tut und wie lange sie dauern sollte

  1. Commit-Stufe (Ziel: unter 10 Minuten)Kompilieren, Unit-Tests, Linter, statische Analyse und Schwachstellenscans der Abhängigkeiten ausführen. Auf diese Stufe warten die Entwickler, also muss sie schnell sein; langsame Tests gehören weiter nach hinten.
  2. PaketDas deploybare Artefakt bauen (meist ein Container-Image), eine Software Bill of Materials (SBOM) erzeugen, es signieren und in das Artefakt-Repository pushen. Maßnahmen für die Software-Lieferkette behandelt Abschnitt 8.6.
  3. Akzeptanz und IntegrationDas Artefakt in eine temporäre oder gemeinsame Testumgebung deployen und API-Tests, Consumer-Driven-Contract-Tests und einige End-to-End-Abläufe ausführen. Performance- und Sicherheitstests können hier parallel oder nach Zeitplan laufen.
  4. StagingIn eine Umgebung deployen, die wie die Produktion konfiguriert ist, Datenbankmigrationen anwenden, Smoke-Tests ausführen. Ihr Wert hängt davon ab, wie genau sie der Produktion in Konfiguration, Datenstruktur und Abhängigkeiten entspricht.
  5. ProduktionMit einer Strategie deployen, die die Betroffenheit begrenzt (Rolling, Blue-Green oder Canary), mit echten Metriken gegen Service Level Objectives prüfen und dann automatisch abschließen oder zurückrollen.

Build once, deploy many und das Artefakt-Repository

Eine Regel aus Continuous Delivery, die noch immer erstaunlich oft verletzt wird, lautet Build once, deploy many: Jede Änderung genau einmal kompilieren und verpacken und dann dasselbe Artefakt durch jede Umgebung weiterreichen. Baut ein Team für Staging und noch einmal für die Produktion, ist das Getestete nicht das Ausgelieferte. Ein anderer Compiler-Patch, eine über Nacht auf eine neuere Version aufgelöste Abhängigkeit oder ein geändertes Basis-Image können die beiden Builds unterscheiden, und die Tests beweisen nichts über den zweiten.

Was sich zwischen Umgebungen unterscheidet, ist die Konfiguration, die beim Deployment oder beim Start übergeben wird (Datenbankadressen, Zugangsdaten, Feature-Flag-Einstellungen) und nie in das Artefakt eingebacken ist. Das ist der Konfigurationsfaktor der Twelve-Factor App. Ein Container-Image mit dem Tag orders:4f1c2ab (dem Commit-Hash) wird in Test, Staging und Produktion deployt; nur seine Umgebungsvariablen und eingebundenen Secrets ändern sich.

Das Artefakt-Repository ist der Speicher zwischen Build und Deployment: eine Container-Registry (Amazon ECR, Azure Container Registry, Google Artifact Registry, GitHub Container Registry, Harbor) oder ein universelles Repository wie JFrog Artifactory oder Sonatype Nexus für Pakete und Binärdateien. Behandeln Sie es als kritische Infrastruktur. Deployen Sie über einen unveränderlichen Digest (sha256:...) statt über ein veränderliches Tag wie latest, das auf ein anderes Image umgesetzt werden kann; bewahren Sie Artefakte, die in Produktion sind oder waren, so lange auf, wie Sie womöglich auf sie zurückrollen oder sie untersuchen müssen; und halten Sie die Herkunft (Provenance) fest, also welcher Commit, welcher Pipeline-Lauf und welche Abhängigkeiten jedes Artefakt erzeugt haben.

Trunk-Based Development und kleine Batches

Wie Code verzweigt wird, entscheidet, wie oft er wirklich integriert wird. Beim Trunk-Based Development integrieren alle mindestens täglich kleine Änderungen in einen Hauptbranch (den Trunk), entweder durch direkte Commits oder über kurzlebige Branches und Pull Requests, die Stunden statt Wochen leben. Das DORA-Forschungsprogramm hat kurzlebige Branches und häufiges Mergen wiederholt mit höherer Lieferleistung in Verbindung gebracht, und es ist eine Voraussetzung für Continuous Integration im wörtlichen Sinn: Code, der drei Wochen auf einem Branch liegt, wird nicht kontinuierlich integriert.

Langlebige Feature-Branches fühlen sich sicherer an, weil unfertige Arbeit getrennt bleibt, doch das Risiko wird nur aufgeschoben: Je länger zwei Branches auseinanderlaufen, desto größer und riskanter wird der spätere Merge und desto länger sieht die Pipeline Code, der nicht der Code ist, der ausgeliefert wird. GitFlow, ein Branching-Modell mit langlebigen Develop- und Release-Branches, das Vincent Driessen 2010 veröffentlichte, wurde breit übernommen; 2020 ergänzte Driessen einen Hinweis, dass Teams, die kontinuierlich ausliefern, etwa bei Webanwendungen, einen einfacheren Workflow erwägen sollten. Teams, die große Änderungen im Trunk vornehmen müssen, nutzen zwei Techniken: Feature-Flags, die unfertiges Verhalten verbergen, und Branch by Abstraction, das eine Schnittstelle vor die alte Implementierung setzt, die neue dahinter baut und umschaltet, sobald sie bereit ist.

An den Rändern sind sich Praktiker wirklich uneinig. Open-Source-Projekte mit vielen nicht vertrauenswürdigen Beitragenden setzen auf längerlebige Pull Requests und Reviews, und regulierte Teams brauchen für Audits manchmal explizite Release-Branches. Das Prinzip, das diese Uneinigkeit übersteht, ist die Batchgröße: Je kleiner jede Änderung, desto leichter lässt sie sich prüfen, testen, deployen, diagnostizieren und rückgängig machen.

name: delivery
on:
  push:
    branches: [main]
env:
  IMAGE: registry.example.com/food/orders:${{ github.sha }}
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: make lint test              # fast feedback first
      - run: docker build -t "$IMAGE" . && docker push "$IMAGE"
  staging:
    needs: build
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - uses: actions/checkout@v4
      - run: ./deploy.sh staging "$IMAGE" && ./smoke-test.sh staging
  production:
    needs: staging
    runs-on: ubuntu-latest
    environment: production            # can require an approval
    steps:
      - uses: actions/checkout@v4
      - run: ./deploy.sh production "$IMAGE" --canary 5
Ein minimaler Continuous-Delivery-Workflow in GitHub-Actions-Syntax: einmal bauen und testen, ein nach dem Commit benanntes Image pushen, dieses Image nach Staging und dann als Canary in die Produktion deployen. GitLab CI, Azure Pipelines, Jenkins und andere drücken dieselben Stufen aus. Registry-Login und Deploy-Skripte sind weggelassen.

Deployment-Strategien

Eine Deployment-Strategie entscheidet, wie die neue Version die alte in der Produktion ersetzt, und damit, wie vielen Nutzern eine schlechte Version schaden kann, bevor sie gestoppt wird. Die Strategien unterscheiden sich in der zusätzlichen Infrastruktur, die sie brauchen, darin, wie schnell sie zurückrollen, und ob zwei Versionen gleichzeitig laufen. Wann immer zwei Versionen gleichzeitig laufen, müssen sie mit den Daten und Nachrichten der jeweils anderen kompatibel sein; das ist der Preis jeder Strategie außer Recreate.

Deployment-Strategien im Vergleich

StrategieSo funktioniert esRisiko für NutzerRollbackZusätzliche Kosten und Komplexität
RecreateAlle alten Instanzen stoppen, dann die neuen starten.Ausfallzeit während des Wechsels; jeder Nutzer trifft sofort auf eine schlechte Version.Die alte Version erneut deployen, mit weiterer Ausfallzeit.Keine. Akzeptabel für interne Tools, Batch-Jobs und Wartungsfenster.
RollingInstanzen jeweils zu wenigen ersetzen (Standard von Kubernetes für Deployments, wobei maxSurge und maxUnavailable beide standardmäßig 25 % betragen).Die Betroffenheit wächst mit dem Fortschritt des Rollouts; Health Checks erkennen Abstürze, aber keine subtilen Fehler.Rollback, indem die alte Version erneut ausgerollt wird; das dauert so lange wie der Rollout.Gering. Alte und neue Version laufen nebeneinander, müssen also kompatibel sein.
Blue-GreenEine vollständige neue Umgebung (Green) neben der Live-Umgebung (Blue) betreiben, sie testen und dann den gesamten Traffic am Router umschalten.Alle Nutzer wechseln auf einmal, aber die neue Umgebung wurde vor dem Umschalten geprüft.Schnell: den Router zurückschalten, solange Blue noch läuft.Bis zu doppelte Kapazität während des Wechsels; gemeinsame Datenbanken müssen mit beiden Versionen funktionieren.
CanaryEinen kleinen Anteil des Traffics (etwa 1–5 %) an die neue Version senden, ihre Metriken vergleichen und dann schrittweise ausweiten.Nur der Nutzeranteil des Canary trifft auf eine schlechte Version, und nur, bis die Analyse sie stoppt.Schnell: das Gewicht des Canary auf null setzen.Braucht gewichtetes Routing, gute Metriken und genug Traffic für einen aussagekräftigen Vergleich.
Shadow (Dark Launch)Echte Anfragen an die neue Version kopieren; ihre Antworten werden verglichen oder verworfen, nie zurückgegeben.Direkt keines, sofern Seiteneffekte (Zahlungen, E-Mails, Schreibzugriffe) unterdrückt oder simuliert werden.Nichts zurückzurollen; Nutzer waren nie davon abhängig.Doppelte Last auf dem gespiegelten Pfad und sorgfältiger Umgang mit Seiteneffekten; am besten für Lesepfade und Neuentwicklungen.

Das Blue-Green-Deployment beschrieb Martin Fowler 2010 und nannte Dan North und Jez Humble als Urheber; das Canary Release, benannt nach den Kanarienvögeln, die Bergleute zum Aufspüren von Gas mitnahmen, beschrieb Danilo Sato 2014 auf derselben Website. In Kubernetes sind Rolling Updates eingebaut; Blue-Green- und Canary-Releases kommen meist von einem Progressive-Delivery-Controller (Argo Rollouts, Flagger) oder von einem Service Mesh und dem gewichteten Routing der Gateway API. Auf verwalteten Plattformen heißen die entsprechenden Funktionen Traffic Splitting oder Deployment Slots.

Canary Release mit automatisierter Analyse

Canary Release mit automatisierter Analyse: Ein Router schickt 90 Prozent des Traffics an die Produktion, 5 Prozent an eine frische Baseline der alten Version und 5 Prozent an den Canary; ein Analyseschritt vergleicht Metriken von Baseline und Canary und weitet aus oder rollt zurückNutzerTraffic-RouterLoad Balanceroder Service MeshProduktion v1meiste InstanzenBaseline v1neu, gleiche GrößeCanary v2neue Version90%5%5%Canary-Analysevergl. Fehler,Latenz, SättigungMetrikenBeschlussok: auf 25 % erhöhenFehler: Rollbackneue Traffic-Gewichte automatisch setzen
Der Vergleich des Canary mit einer frischen Baseline der alten Version statt mit der lange laufenden Flotte beseitigt Unterschiede, die nur durch Laufzeit und warme Caches entstehen.

Deployment und Release mit Feature-Flags trennen

Deployment installiert eine neue Version der Software in einer Umgebung; Release macht ein Verhalten für Nutzer verfügbar. Behandelt man beides als ein Ereignis, wird jedes Deployment zu einem Geschäftsereignis, mit all der Nervosität, die das mit sich bringt. Feature-Flags (Feature Toggles) trennen die beiden: Der neue Code wird ausgeschaltet deployt, und das Verhalten wird später durch eine Konfigurationsänderung freigegeben, schrittweise und umkehrbar. Pete Hodgsons Artikel Feature Toggles (aka Feature Flags) auf martinfowler.com (2017) unterscheidet vier Kategorien danach, wie lange sie leben und wie dynamisch sie entscheiden.

Hodgsons vier Kategorien von Feature Toggles

KategorieZweckTypische LebensdauerWie dynamisch
Release-TogglesUnfertige oder unveröffentlichte Features im Trunk ausliefern, ausgeschaltet.Tage bis wenige Wochen; nach dem Release entfernen.Meist statisch pro Release.
Experiment-TogglesA/B- oder multivariate Tests, die jeden Nutzer einer Kohorte zuordnen.Lange genug für statistisch belastbare Ergebnisse, dann entfernt.Pro Anfrage, nach Nutzerkohorte.
Ops-TogglesBetriebliche Steuerungen, etwa das Abschalten eines teuren Empfehlungsbereichs unter Last (Kill Switches).Meist kurz; einige Kill Switches bleiben langfristig erhalten.Zur Laufzeit geändert, oft während eines Incidents.
Permissioning-TogglesFeatures für bestimmte Nutzer: Premium-Stufen, Betatester, interne Mitarbeitende.Können jahrelang bestehen.Pro Anfrage, nach Nutzer.

Flags verursachen laufende Kosten. Jedes Flag verdoppelt die Pfade durch den Code, den es schützt, erhöht die Zahl der Testkombinationen und hinterlässt toten Code, sobald seine Entscheidung feststeht. Hodgson empfiehlt, Flags wie einen Lagerbestand zu behandeln: Beim Anlegen eines Release-Toggles eine Aufgabe zum Entfernen anlegen, Flags ein Ablaufdatum geben, Tests ergänzen, die fehlschlagen, sobald ein Flag sein Datum überschritten hat, und begrenzen, wie viele gleichzeitig existieren dürfen. Der Verlust von Knight Capital im Jahr 2012, beschrieben in Abschnitt 1.3, ging auf ein umfunktioniertes Flag zurück, das alten Code auf einem Server reaktivierte, der bei einem manuellen Deployment übersehen worden war: eine Mahnung, Flag-Namen nie wiederzuverwenden und toten Code hinter entschiedenen Flags zu löschen. Im großen Maßstab werden Flags von einem eigenen Dienst bereitgestellt (Open-Source-Optionen wie Unleash und Flagsmith, kommerzielle wie LaunchDarkly oder die herstellerneutrale OpenFeature-API), damit sich eine Änderung in Sekunden verbreitet und protokolliert wird.

Datenbankänderungen in der Pipeline

Code lässt sich in Sekunden zurückrollen, Daten nicht. Ein Deployment, das eine Spalte umbenennt und dann zurückgerollt wird, lässt den alten Code vor einem Schema zurück, das er nicht versteht. Die Antwort, ausführlich behandelt unter Schemaevolution, besteht darin, jede Schemaänderung abwärtskompatibel zur gerade laufenden Codeversion zu machen, mit Expand and Contract: zuerst die neue Struktur hinzufügen, Code deployen, der beide schreibt und jede liest, Daten nachfüllen (Backfill), die Leser umstellen und die alte Struktur erst in einem späteren Release entfernen, wenn nichts sie mehr nutzt.

In der Pipeline heißt das: Migrationen sind versionierte Artefakte, die als eigener Schritt laufen, bevor der Code deployt wird, der sie braucht, und sie werden an einer Kopie der Daten in Produktionsgröße getestet, damit eine Sperre auf einer großen Tabelle im Staging entdeckt wird statt zur Mittagszeit. Destruktive Schritte (Spalten oder Tabellen löschen) werden verzögert und separat ausgeführt, weil sie die einzige Art von Änderung sind, die ein Rollback nicht rückgängig machen kann. Eine nützliche Pipeline-Prüfung lässt den Build fehlschlagen, wenn eine Migration nicht additiv ist, es sei denn, sie ist ausdrücklich als Contract-Schritt gekennzeichnet.

Progressive Delivery und automatisierte Canary-Analyse

Progressive Delivery, ein Begriff, den James Governor vom Analystenhaus RedMonk 2018 populär machte, verbindet Canaries, Feature-Flags und automatisierte Prüfung: Eine Änderung erreicht schrittweise größere Zielgruppen, und bei jedem Schritt entscheidet das System, nicht eine Person vor Dashboards, ob es weitergeht. Die Entscheidung nutzt die automatisierte Canary-Analyse: Die Metriken des Canary (Fehlerrate, Latenzperzentile, Sättigung, Geschäftssignale wie aufgegebene Bestellungen) werden statistisch mit einer Baseline verglichen. Netflix und Google haben ihre Analyse-Engine Kayenta 2018 als Open Source veröffentlicht; Argo Rollouts und Flagger bieten in Kubernetes ähnliche Analyseschritte.

Drei Details entscheiden, ob man der Analyse trauen kann. Vergleichen Sie Gleiches mit Gleichem: Eine frische Baseline der alten Version, die denselben Traffic-Anteil erhält, verhindert, dass der neuen Version Unterschiede angelastet werden, die von kalten Caches oder kürzlichen Neustarts herrühren. Sorgen Sie für genug Traffic: Bei 5 % eines Service mit zehn Anfragen pro Minute sieht eine Stunde Canary dreißig Anfragen, zu wenige, um eine Fehlerrate von 1 % zu erkennen; Services mit wenig Traffic brauchen daher längere Schritte, synthetische Last oder eine andere Strategie. Wählen Sie Metriken, die an die Service Level Objectives und an Geschäftsergebnisse gebunden sind, denn eine Version kann schnell und fehlerfrei sein und dabei still die falsche Liefergebühr berechnen.

Rollback oder Roll-forward

Wenn ein Release schiefgeht, gibt es zwei Auswege. Ein Rollback kehrt zum vorherigen Artefakt zurück; das ist schnell und braucht keinen neuen Code, sofern die vorherige Version noch mit den aktuellen Daten und den Versionen anderer Services funktioniert. Ein Roll-forward liefert eine Korrektur über die Pipeline aus; das ist langsamer, aber manchmal die einzige Option, etwa nach einer nicht umkehrbaren Datenmigration oder einer Änderung, von der andere Services bereits abhängen.

Eine vernünftige Grundregel lautet erst zurückrollen, später diagnostizieren: den Dienst mit der schnellsten sicheren Maßnahme wiederherstellen und dann ohne Druck untersuchen. Ein Roll-forward unter Druck umgeht tendenziell die Prüfungen der Pipeline, und eine überhastete Korrektur eines Produktionsincidents ist eine klassische Quelle des nächsten Incidents. Ein Rollback ist nur dann eine echte Option, wenn er eingeplant ist: frühere Artefakte aufbewahrt, Schemaänderungen für mindestens eine Version in beide Richtungen kompatibel, Nachrichten für alte und neue Consumer lesbar und der Rollback-Pfad selbst regelmäßig geübt. Ein Team, das noch nie zurückgerollt hat, sollte davon ausgehen, dass es das nicht kann.

Ausgearbeitetes Beispiel

Ausgearbeitetes Beispiel: eine neue Liefergebührenregel ausliefern

Der Bestellservice der Essenslieferplattform ändert die Berechnung der Liefergebühren: Statt einer Pauschale zählen nun Entfernung und Nachfrage. Das Team nutzt Trunk-Based Development, ein Canary-Deployment und ein Release-Flag.

ÄnderungNeuer Gebührenrechner hinter einem Release-Flag dynamic-delivery-fee, standardmäßig aus; eine reine Expand-Migration fügt eine nullable Spalte fee_rule_version hinzu.
Vom Commit zum ArtefaktUm 10:02 in main gemergt. Lint, Unit-Tests und Scans dauern 6 Minuten; das Image orders:4f1c2ab wird mit SBOM und Signatur um 10:09 gepusht.
MigrationDie additive Migration läuft um 10:15 als eigener Pipeline-Schritt. Die laufende Version ignoriert die neue Spalte, also bricht nichts.
StagingDasselbe Image wird um 10:16 deployt; Vertragstests mit dem Zahlungs- und dem Restaurantservice sowie Smoke-Tests sind um 10:31 bestanden.
CanaryUm 10:35 gehen 5 % des Produktionstraffics an die neue Version, noch mit ausgeschaltetem Flag. Eine Analyse über 20 Minuten vergleicht p99-Latenz, 5xx-Rate und Bestellerfolg mit einer frischen Baseline: bestanden.
RolloutDie Gewichte steigen in 15-Minuten-Schritten auf 25 %, 50 % und 100 %; abgeschlossen um 11:40. Das Deployment ist fertig, und doch hat noch kein Kunde die neue Gebühr gesehen.
ReleaseAm nächsten Tag aktiviert die Produktmanagerin das Flag für 10 % der Kunden in einer Stadt, beobachtet Bestellkonversion und Beschwerden und weitet es dann im Laufe einer Woche auf alle Städte aus.
AufräumenDas Flag und der Pauschalgebühren-Code werden im folgenden Sprint gelöscht; eine spätere Contract-Migration macht die Spalte zur Pflicht.

Deployment-Risiko (funktioniert der Code?) und Release-Risiko (mögen die Kunden die neuen Gebühren?) wurden getrennt behandelt, jedes mit eigenem kleinem Blast Radius.

Bei jedem Schritt bis zur Contract-Migration war die Wiederherstellung eine Konfigurationsänderung oder ein Router-Gewicht, kein Notfall-Fix. Vom Commit bis zum vollständigen Produktions-Deployment vergingen etwa 1 Stunde 40 Minuten.

Die Pipeline messen

Die in Abschnitt 2.6 eingeführten DORA-Metriken für die Softwareauslieferung (Change Lead Time, Deployment-Häufigkeit, Change Fail Rate, Wiederherstellungszeit nach fehlgeschlagenem Deployment und Deployment-Rework-Rate) sind größtenteils Eigenschaften von Pipeline und Architektur zusammen. Kleine Batches und Trunk-Based Development verkürzen die Lead Time und erhöhen die Häufigkeit; automatisierte Tests und Canary-Analyse senken die Change Fail Rate; schnelles Rollback und Flags verkürzen die Wiederherstellungszeit. Messen Sie sie pro Service, beobachten Sie Trends statt Einzelwerte, und machen Sie sie nie zu Zielvorgaben für Einzelpersonen; das lädt nur zum Schönen der Zahlen ein.

Prüfen Sie Ihr Verständnis

Warum ist es ein Problem, das Artefakt für die Produktion separat neu zu bauen, selbst wenn der Quellcode identisch ist?

Abhängigkeiten, Basis-Images oder Build-Werkzeuge können sich zwischen den Builds geändert haben, sodass das Produktionsartefakt nicht das getestete ist; einmal bauen und dasselbe Artefakt weiterreichen.

Was ist der Unterschied zwischen dem Deployment eines Features und seinem Release?

Das Deployment installiert den Code in einer Umgebung; das Release macht das Verhalten für Nutzer verfügbar. Mit Feature-Flags lässt sich der Code ausgeschaltet deployen und später schrittweise und umkehrbar freigeben.

Warum liefert ein Canary bei einem Service mit wenig Traffic oft unzuverlässige Ergebnisse?

Ein kleiner Anteil von wenig Traffic ergibt zu wenige Anfragen, um Unterschiede in Fehlerrate oder Latenz mit statistischer Sicherheit zu erkennen; daher müssen die Schritte länger sein, der Traffic synthetisch oder eine andere Strategie gewählt werden.

Wann kann ein Roll-forward die einzige Option sein?

Wenn das Release eine nicht umkehrbare Änderung enthielt, etwa eine destruktive Migration, oder andere Services bereits vom neuen Verhalten abhängen, sodass die vorherige Version nicht mehr korrekt laufen kann.

Weiter · 10.6Multi-Region und EdgeWann und wie Sie über mehrere Regionen hinweg betreiben: Latenz, Disaster Recovery und Datenresidenz, die vier DR-Strategien mit RTO, RPO und Kosten, regionsübergreifende Daten, Failover, Zellen zur Begrenzung des Blast Radius, CDNs und Edge Functions.Weiter →

Quellen und weiterführende Literatur

Haben Sie eine Frage zu diesem Abschnitt? ArchitectBot, der KI-Lernassistent des Kurses, antwortet zuerst aus dem Kurs.

Fragen: „Unser Team deployt alle zwei Wochen mit einer manuellen Checkliste. Welche Änderungen an Pipeline und Deployment sollten wir zuerst vornehmen, um mehrmals täglich sicher zu deployen?“