Read in English · Leer en español · Lire en français
Abschnitt 10.3 von 10.8 · Mittelstufe · 20 Min. Lesezeit
Die Twelve-Factor App und cloud-native Prinzipien
Videolektion
5 Min. · auf Englisch gesprochen, mit UntertitelnNur anhören (Audio)
Transkript lesen
Kubernetes und jede moderne Plattform setzen voraus, dass sich Anwendungen auf bestimmte Weise verhalten. In dieser Lektion lernen Sie diese Regeln kennen, die zwölf Faktoren, und wie Sie einen echten Service daran messen.
Denken Sie an eine Kette von Lieferküchen. Eine gute Rezeptkarte funktioniert in jeder Filiale: Sie führt jede Zutat auf und sagt nichts darüber, in welcher Filiale sie liegt. Jeder Koch kann sie mitten in der Schicht übernehmen, weil nichts Wichtiges nur in einem Kopf steckt. Und wenn sich die Speisekarte ändert, wird eine neue Karte gedruckt und nummeriert, statt die alte zu bekritzeln. Die Twelve-Factor App ist diese Art Rezeptkarte für Software.
2011 veröffentlichte Adam Wiggins, Mitgründer von Heroku, The Twelve-Factor App und bündelte darin, was sein Team aus der Beobachtung sehr vieler Anwendungen auf seiner Plattform gelernt hatte. Es entstand vor Docker und Kubernetes und beschreibt doch fast genau den Vertrag, den diese Plattformen später durchgesetzt haben. Und es geht um die Beziehung einer Anwendung zu ihrer Plattform, nicht um ihr Innenleben: Ein modularer Monolith kann vollständig Twelve-Factor-konform sein.
Gehen wir die Faktoren in Gruppen durch. Faktor eins: eine Codebasis in der Versionsverwaltung, deployt in viele Umgebungen. Faktor zwei: jede Abhängigkeit deklariert, sodass Builds auf jeder Maschine reproduzierbar sind. Die Faktoren drei und vier halten URLs, Zugangsdaten und Backing Services aus dem Code heraus, gefunden über Konfiguration. Ein einfacher Test: Könnte der Code heute veröffentlicht werden, ohne eine einzige Zugangsinformation offenzulegen? Faktor fünf, Build, Release, Run, hält diese Stufen auseinander. Darauf kommen wir gleich zurück. Sechs bis neun machen Skalierung sicher. Prozesse sind zustandslos und teilen nichts. Die App bietet ihren Dienst an, indem sie auf einem Port lauscht. Man skaliert, indem man mehr Prozesse jedes Typs ausführt. Und Prozesse starten schnell und fahren geordnet herunter. Zehn bis zwölf verringern Überraschungen: Entwicklung und Produktion ähnlich halten, Logs als Stream auf die Standardausgabe schreiben und einmalige Aufgaben wie Migrationen als separate Prozesse mit demselben Release ausführen.
Hier ist Faktor fünf. Die Build-Stufe macht aus einem Commit ein ausführbares Artefakt, heute meist ein Container-Image, das über seinen Digest identifiziert wird. Es wird einmal gebaut. Die Release-Stufe kombiniert dieses Image mit der Konfiguration einer Umgebung und gibt dem Ergebnis eine Identität, etwa Release zweiundvierzig. Die Run-Stufe startet Prozesse aus einem Release. Releases sind unveränderlich: Jede Änderung an Code oder Konfiguration erzeugt ein neues Release, nie eine Bearbeitung eines alten. Ein Rollback heißt also einfach, Release einundvierzig erneut auszuführen, ohne Rebuild. Niemand bearbeitet Dateien auf einem Server, also driften Server nicht, und was den Test bestanden hat, ist genau das, was läuft.
Prüfen wir einen echten Service: den fünf Jahre alten Restaurant-Onboarding-Service der Essenslieferplattform, auf zwei von Hand aufgesetzten virtuellen Maschinen. Das Team möchte ihn auf die Container-Plattform umziehen, und das Audit findet neun Probleme. Erstens liegt das Passwort der Produktionsdatenbank in einer Datei im Repository. Jeder, der den Code lesen kann, hat es. Rotieren Sie es sofort, und verschieben Sie es in den Secrets Manager. Priorität eins. Zweitens werden hochgeladene Speisekarten und Logos auf die lokale Festplatte einer Maschine geschrieben. Sie verschwinden, wenn eine Anfrage auf der anderen Maschine landet, und blockieren jeden Umzug auf entsorgbare Container. Ebenfalls Priorität eins. Drittens liegen Sessions im Speicher, sodass jedes Deployment das Restaurantpersonal mitten im Formular abmeldet. Priorität zwei. Ebenso das Deployment per Login auf jeder Maschine mit Code-Pull, Migrationen beider Instanzen beim Start und harte Kills bei Deployments: kein Rollback, Migrationen im Wettlauf und halb gespeicherte Formulare. Log-Dateien, ein nächtlicher Job auf nur einer Maschine und SQLite auf den Laptops können später folgen, mit Priorität drei. Beachten Sie die Reihenfolge: zuerst das Risiko, weil offengelegte Zugangsdaten ein laufender Incident sind, dann was die Zielplattform blockiert, dann Zuverlässigkeit, dann Komfort.
Manche Ratschläge sind gealtert. Umgebungsvariablen sickern in Logs, Absturzberichte und Kindprozesse durch, deshalb gehören Secrets heute in einen Secrets Manager oder besser in Workload Identity, bei der die Plattform jedem Service kurzlebige Zugangsdaten gibt. Zustandslos heißt nicht, dass das System keinen Zustand hat. Es heißt, dass Prozesse ihn nicht halten: Der Zustand wandert in Backing Services, die dafür gemacht sind. Und die heutige Praxis ergänzt vier Themen: darauf auslegen, jederzeit beendet zu werden, nie etwas Laufendes patchen, Logs, Metriken und Traces ausgeben und Sicherheit von Anfang an einbauen.
Der vollständige Abschnitt enthält eine Tabelle aller zwölf Faktoren mit ihren heutigen Einschränkungen und das komplette Audit. Als Nächstes wenden wir in Abschnitt zehn Punkt vier dieselbe Disziplin auf die Infrastruktur selbst an. Bis gleich.
Was Sie wissen müssen
- The Twelve-Factor App (Adam Wiggins, Heroku, 2011, seit 2024 Open Source) beschreibt den Vertrag zwischen einer Anwendung und einer modernen Plattform und gilt für Monolithen wie für Microservices.
- Config (III) und Backing Services (IV) halten alles, was sich zwischen Deployments unterscheidet, außerhalb des Artefakts, sodass ein Artefakt in jeder Umgebung läuft; Secrets gehören heute in einen Secrets Manager oder in eine Workload Identity statt in einfache Umgebungsvariablen.
- Build, Release, Run (V) macht Releases unveränderlich und nummeriert, sodass ein Rollback bedeutet, ein früheres Release auszuführen, und niemand einen laufenden Server bearbeitet.
- Zustandslose Prozesse (VI), Nebenläufigkeit nach Prozesstyp (VIII) und Disposability (IX) machen horizontale Skalierung, Rolling Updates und das Ersetzen ausgefallener Instanzen sicher.
- Dev/Prod-Parität (X), Logs als Streams (XI) und Admin-Prozesse als separate einmalige Prozesse (XII) verringern Überraschungen in der Produktion; Migrationen müssen mit altem und neuem Code kompatibel sein.
- Über die zwölf Faktoren hinaus werden cloud-native Anwendungen auf Disposability, Unveränderlichkeit, Observability und Sicherheit ausgelegt, und Hoffmans Erweiterung von 2016 ergänzt API First, Telemetrie sowie Authentifizierung und Autorisierung.
- Ein Audit anhand der Faktoren sollte Lücken nach Risiko ordnen: zuerst offengelegte Secrets, dann alles, was die Zielplattform blockiert, etwa lokaler Zustand, dann Zuverlässigkeit und Komfort.
Woher die zwölf Faktoren kommen
2011 veröffentlichte Adam Wiggins, Mitgründer von Heroku, The Twelve-Factor App, ein kurzes Webdokument, das bündelte, was das Heroku-Team aus der Beobachtung sehr vieler Anwendungen gelernt hatte, die auf seiner Plattform gebaut, deployt und skaliert wurden. Die Methodik der Twelve-Factor App beschreibt Anwendungen, die sich aus deklarativen, automatisierten Schritten selbst einrichten, einen sauberen Vertrag mit der Plattform darunter haben, sodass sie überall laufen können, Entwicklung und Produktion nah genug beieinander halten, um kontinuierliches Deployment zu ermöglichen, und ohne Neuentwurf horizontal skalieren können.
Das Dokument ist älter als Docker (2013) und Kubernetes (2014), beschreibt aber fast genau den Vertrag, den diese Plattformen später durchgesetzt haben: Eine Anwendung ist eine Menge zustandsloser Prozesse, gebaut zu einem unveränderlichen Artefakt, von außen konfiguriert, die Logs in einen Stream schreibt und mit allem anderen über das Netzwerk spricht. Deshalb ist es bis heute das gemeinsame Vokabular für den Entwurf cloud-nativer Anwendungen. Im November 2024 gab Heroku bekannt, dass die Methodik nun Open Source ist und von einer Community aus Beitragenden mehrerer Unternehmen gepflegt wird, mit dem Ziel, sie an die heutige Praxis anzupassen; die ursprünglichen zwölf Faktoren bleiben der Bezugspunkt.
Die Faktoren betreffen die Beziehung der Anwendung zu ihrer Laufzeitplattform, nicht ihre interne Architektur. Ein modularer Monolith kann vollständig Twelve-Factor-konform sein; eine Menge von Microservices kann jeden Faktor verletzen. Sie ergänzen die Anliegen Deploybarkeit und Betreibbarkeit aus Kapitel 2 und die Prinzipien zu Skalierung und Zustandslosigkeit aus Kapitel 9.
Die zwölf Faktoren, mit heutigen Einschränkungen
| Faktor | Was sie bedeutet | Warum sie zählt | Heutige Einschränkung |
|---|---|---|---|
| I. Codebasis | Eine Codebasis in der Versionsverwaltung pro App, deployt in viele Umgebungen. | Jede Umgebung führt eine Version desselben Codes aus; keine Forks pro Kunde oder pro Umgebung. | Ein Monorepo mit mehreren Apps ist in Ordnung, wenn jede App eine klare Grenze hat; das Antipattern sind kopierte und abgewandelte Forks. |
| II. Abhängigkeiten | Jede Abhängigkeit explizit deklarieren und die App vom Hostsystem isolieren. | Builds sind auf jeder Maschine reproduzierbar; nichts hängt von einem Paket ab, das jemand von Hand installiert hat. | Lock-Dateien und Images machen das zum Standard; gepinnte Abhängigkeiten brauchen trotzdem regelmäßige Updates und Schwachstellenscans. |
| III. Konfiguration | Alles, was sich zwischen Deployments unterscheidet (URLs, Zugangsdaten, Feature-Einstellungen), aus dem Code heraushalten, in der Umgebung. | Ein Artefakt läuft in jeder Umgebung; Secrets gelangen nie ins Repository. | Umgebungsvariablen sickern in Logs, Absturzberichte und Kindprozesse durch; Secrets liest man besser aus einem Secrets Manager oder aus eingehängten Dateien. |
| IV. Backing Services | Datenbanken, Queues, Caches und externe APIs als angebundene Ressourcen behandeln, die über Konfiguration gefunden werden. | Eine lokale Datenbank lässt sich durch eine verwaltete ersetzen, eine ausgefallene durch eine wiederhergestellte Kopie, indem man eine URL ändert. | Ein Austausch ist selten nahtlos, wenn sich die Semantik unterscheidet; Unterschiede hinter Ports und Adaptern isolieren. |
| V. Build, Release, Run | Das Bauen eines Artefakts, seine Kombination mit Konfiguration zu einem Release und seine Ausführung trennen. | Releases sind unveränderlich und nummeriert; jedes Release kann erneut ausgeführt werden; niemand bearbeitet Code auf einem Server. | Heute: einmal in der CI bauen, das Image per Digest speichern, Releases in Git oder im Deployment-Tool festhalten. |
| VI. Prozesse | Die App als einen oder mehrere zustandslose Prozesse ausführen, die nichts teilen; Zustand in Backing Services halten. | Jede Kopie kann jede Anfrage bedienen, also lassen sich Kopien frei hinzufügen, entfernen und ersetzen. | Sticky Sessions verdecken das Problem, statt es zu lösen; die lokale Festplatte ist nur ein Arbeitsbereich für Temporäres. |
| VII. Port-Bindung | Die App ist eigenständig und stellt ihren Dienst bereit, indem sie auf einem Port lauscht. | Die Plattform leitet Verkehr an sie, ohne sie in einen separaten Webserver einzubetten. | Heute universell; Queue-Consumer haben keinen Port, und Service Meshes können davorgeschaltet sein. |
| VIII. Nebenläufigkeit | Horizontal skalieren, indem mehr Prozesse laufen, mit verschiedenen Prozesstypen für verschiedene Arbeit (Web, Worker). | Jede Art von Arbeit skaliert unabhängig nach ihrer eigenen Last. | Autoscaler erledigen das automatisch, auch anhand der Queue-Länge; Threads innerhalb eines Prozesses spielen weiterhin eine Rolle. |
| IX. Disposability | Schnell starten, bei SIGTERM geordnet herunterfahren, einen plötzlichen Tod überstehen. | Schnelle Skalierung, sichere Rolling Deployments und Robustheit gegenüber Abstürzen. | Langsam startende Laufzeitumgebungen brauchen Startup Probes oder Techniken für schnelleren Start; Hintergrundjobs müssen idempotent und fortsetzbar sein. |
| X. Dev/Prod-Parität | Entwicklung, Staging und Produktion zeitlich, personell und bei den Tools so ähnlich wie möglich halten. | Weniger Überraschungen, die erst in der Produktion auftreten; kontinuierliches Deployment wird sicher. | Volle Parität ist zu teuer; vorrangig dieselben Arten und Versionen von Backing Services verwenden, lokal in Containern. |
| XI. Logs | Logs als ungepufferten Event-Stream auf die Standardausgabe schreiben; die Plattform leitet sie weiter. | Die App verwaltet keine Dateien; Logs aller Kopien werden zentral gesammelt. | Strukturierte Logs plus Metriken und Traces verwenden (zum Beispiel über OpenTelemetry); Log-Volumen und Kosten im Blick behalten. |
| XII. Admin-Prozesse | Einmalige Aufgaben (Migrationen, Skripte) als separate Prozesse mit demselben Code und derselben Konfiguration ausführen. | Admin-Aufgaben laufen gegen genau das Release in der Produktion, nicht gegen eine veraltete Kopie. | Als Pipeline-Schritte oder Kubernetes-Jobs ausführen; nie jedes Replikat beim Start ohne Lock Migrationen ausführen lassen. |
Konfiguration, Secrets und Backing Services
Für den Konfigurationsfaktor gibt es einen einfachen Test: Könnte die Codebasis heute veröffentlicht werden, ohne eine einzige Zugangsinformation offenzulegen? Wenn nicht, ist Konfiguration in den Code gesickert. Die Trennung von Konfiguration und Code lässt ein Artefakt unverändert durch jede Umgebung wandern; das ist die Grundlage des Build-once-Prinzips in Abschnitt 10.5 (CI/CD und Deployment). Zur Konfiguration gehören Datenbank- und Service-URLs, Zugangsdaten und umgebungsspezifische Einstellungen; nicht dazu gehört die interne Verdrahtung, die überall gleich ist, etwa welche Klasse welche Route behandelt: Sie gehört in den Code.
Die ursprüngliche Empfehlung, Umgebungsvariablen zu verwenden, ist ungleichmäßig gealtert. Sie sind universell und sprachneutral, und Kubernetes, PaaS-Plattformen und Funktionen unterstützen sie alle. Aber die Umgebung eines Prozesses ist für Kindprozesse sichtbar, landet oft in Absturzberichten und Debugging-Seiten und lässt sich ohne Neustart nicht rotieren. Die heutige Praxis für Secrets ist, sie beim Start aus einem Secrets Manager abzurufen (AWS Secrets Manager, Azure Key Vault, Google Secret Manager, HashiCorp Vault oder OpenBao) oder sie als Dateien einzuhängen, die die Plattform aktualisieren kann, und noch besser, langlebige Secrets durch Workload Identity zu ersetzen, bei der die Plattform jedem Service automatisch kurzlebige Zugangsdaten gibt. Die Absicht des Faktors, Konfiguration außerhalb des Artefakts zu halten, ist unverändert.
Einen Backing Service als angebundene Ressource zu behandeln heißt, dass der Code die Bestelldatenbank, den Zahlungsanbieter und den Message Broker auf dieselbe Weise erreicht: über eine URL und Zugangsdaten, die beim Deployment bereitgestellt werden. Das macht Umgebungen kombinierbar und die Wiederherstellung schneller. Es macht Backing Services nicht wie von Zauberhand austauschbar; wer einen Message Broker durch einen anderen ersetzt, ändert die Zustellsemantik. Der hexagonale Stil aus Kapitel 5 ergänzt den Faktor: Die Konfiguration sagt, wo die Ressource ist, und ein Adapter hinter einem Port verbirgt, wie sie sich verhält.
Build, Release, Run
Der Faktor Build, Release, Run trennt drei Stufen, die oft verschwimmen. Die Build-Stufe macht aus einem Commit ein ausführbares Artefakt, heute meist ein Container-Image, das über seinen Digest identifiziert wird. Die Release-Stufe kombiniert dieses Artefakt mit der Konfiguration einer Umgebung und gibt dem Ergebnis eine Identität, etwa Release v42 des Bestellservice in der Produktion. Die Run-Stufe startet Prozesse aus einem Release. Releases sind unveränderlich: Eine Änderung an Code oder Konfiguration erzeugt ein neues Release, nie eine Bearbeitung eines bestehenden.
Einmal bauen, pro Umgebung releasen, überall ausführen
Diese Trennung macht Deployments langweilig. Niemand bearbeitet Dateien auf einem Server, also driften Server nicht auseinander; dasselbe Image, das im Staging getestet wurde, läuft in der Produktion, also hat ein Testergebnis Aussagekraft; und ein Rollback ist ein schneller, geübter Vorgang statt eines Notfall-Rebuilds. Sie ist auch ein Audit-Trail: Für jeden Zeitpunkt lässt sich genau sagen, welcher Code und welche Konfiguration liefen. Kubernetes führt eine Revisionshistorie der ReplicaSets jedes Deployments, PaaS-Plattformen nummerieren Releases, und GitOps (Abschnitt 10.4) macht die Git-Historie des Release-Repositorys zum Nachweis.
Prozesse, Nebenläufigkeit und Disposability
Zustandslose Shared-Nothing-Prozesse sind die Voraussetzung für fast alles andere in diesem Kapitel: horizontale Skalierung, Rolling Deployments, Autoscaling, das Ersetzen ausgefallener Knoten und die Verteilung über Zonen. Alles, was ein Prozess nur in seinem Speicher oder auf seiner lokalen Festplatte hält (die Session eines Nutzers, eine hochgeladene Datei, ein halb erstellter Bericht), geht verloren, wenn dieser Prozess ersetzt wird, und ist für die anderen Kopien unsichtbar. Kapitel 9 behandelt den Umgang mit Sessions ausführlich (Load Balancing, Zustandslosigkeit und Sessions). Zustand verschwindet nicht; er wandert in Backing Services, die dafür gemacht sind, ihn zu halten.
Der Nebenläufigkeitsfaktor ergänzt, dass verschiedene Arten von Arbeit als verschiedene Prozesstypen laufen sollten, die getrennt skalieren. In der Essenslieferplattform skaliert der Webprozess, der die Kunden-App bedient, mit der Anfragerate, während ein Worker-Prozess, der Bestellbestätigungen verschickt, mit der Queue-Länge skaliert und ein Consumer für Kurierstandorte mit dem Event-Durchsatz. Wer sie in einem Prozesstyp mischt, skaliert alle für den Bedarf eines einzigen.
Disposability verlangt, dass Prozesse in Sekunden starten und sauber stoppen. Bei SIGTERM nimmt ein Webprozess keine Verbindungen mehr an und beendet laufende Anfragen; ein Worker gibt seine aktuelle Nachricht an die Queue zurück oder schließt sie innerhalb der Karenzzeit ab. Weil Prozesse auch ohne Vorwarnung sterben können (ein Knotenausfall, ein Abbruch wegen Speichermangels), muss Arbeit gefahrlos wiederholbar sein: idempotente Nachrichtenverarbeitung wie in der ereignisgesteuerten Architektur und Jobs, die an Checkpoints fortsetzen. George Candea und Armando Fox trieben die Idee 2003 mit Crash-only Software auf die Spitze, die nur eine Art zu stoppen kennt (den Absturz) und eine Art zu starten (die Wiederherstellung), sodass der Wiederherstellungspfad ständig geübt statt erst während eines Incidents entdeckt wird.
Dev/Prod-Parität, Logs und Admin-Prozesse
Der Originaltext benennt drei Lücken zwischen Entwicklung und Produktion: Zeit (Code, der Wochen vor seinem Deployment geschrieben wird), Personal (Entwickler schreiben ihn, der Betrieb deployt ihn) und Tools (SQLite auf dem Laptop, PostgreSQL in der Produktion). Continuous Delivery schließt die erste, Teams, die betreiben, was sie bauen, schließen die zweite, und Container schließen einen großen Teil der dritten: Eine Entwicklerin kann dieselbe PostgreSQL-Version, denselben Message Broker und denselben Cache lokal ausführen, und Tools wie Testcontainers starten echte Abhängigkeiten in Integrationstests. Perfekte Parität ist weder bezahlbar noch nötig; am wichtigsten ist, dieselben Arten und Versionen von Backing Services zu verwenden, denn dort liegen die überraschenden Unterschiede.
Logs als Event-Streams bedeutet, dass die Anwendung jedes Ereignis auf die Standardausgabe schreibt und Speicherung, Rotation und Weiterleitung der Plattform überlässt. Das ist weiterhin richtig, mit zwei heutigen Ergänzungen: Logs sollten strukturiert sein (zum Beispiel JSON mit einheitlichen Feldnamen und einer Anfrage- oder Trace-ID), und Logs sind eines von drei Signalen, neben Metriken und Traces, die ein System beobachtbar machen (Observability). Das Log-Volumen ist außerdem ein echter Kostentreiber; Abschnitt 10.8 kommt darauf zurück.
Admin-Prozesse wie Datenbankmigrationen, Datenreparaturen und einmalige Berichte sollten mit demselben Release (Code und Konfiguration) wie die Anwendung laufen, als separate Prozesse. In Kubernetes ist das typischerweise ein Job, den die Pipeline ausführt, bevor die neue Version ausgerollt wird. Migrationen brauchen besondere Sorgfalt: Sie müssen sowohl mit der alten als auch mit der neuen Codeversion kompatibel sein, die nebeneinander laufen; das ist die Disziplin Expand and Contract der Schemaevolution.
Über die zwölf Faktoren hinaus
Die zwölf Faktoren waren nie als vollständig gedacht, und spätere Autoren haben sie erweitert. Kevin Hoffmans Beyond the Twelve-Factor App (O’Reilly, 2016) erweiterte die Liste auf fünfzehn und ergänzte API First (den Vertrag vor der Implementierung entwerfen), Telemetrie (Metriken, Health und Tracing einbauen) sowie Authentifizierung und Autorisierung (Sicherheit als Entwurfsanliegen von Anfang an). Die heutige Praxis ergänzt vier Themen, die jede cloud-native Anwendung erfüllen sollte.
Disposability, ernst genommen. Darauf auslegen, jederzeit beendet zu werden: idempotente Operationen, kurze Anfrage-Timeouts, begrenzte Startzeit, geordnetes Leerlaufen (Drain) und kein einzelner Prozess, dessen Verlust ins Gewicht fällt. Unveränderlichkeit. Nie einen laufenden Container oder Server patchen; ein neues Image bauen und ihn ersetzen (Abschnitt 10.4 zu Immutable Infrastructure). So lässt sich jede laufende Instanz auf einen Commit zurückführen, und Drift entfällt. Observability. Strukturierte Logs, Metriken und Traces über einen Standard wie OpenTelemetry ausgeben, Health-Endpoints bereitstellen, die den eigenen Zustand des Prozesses widerspiegeln, und den Trace-Kontext über Aufrufe hinweg weitergeben, damit der Betrieb Fragen beantworten kann, die er nicht vorhergesehen hat. Sicherheit. Wo möglich als Nicht-Root-Benutzer mit schreibgeschütztem Dateisystem laufen; Zugangsdaten über Workload Identity statt über langlebige Schlüssel beziehen; für jeden Backing Service das Prinzip der geringsten Rechte anwenden; und aus minimalen, gescannten, signierten Images bauen (Sicherheit der Software-Lieferkette).
Ausgearbeitetes Beispiel
Ausgearbeitetes Beispiel: Audit des Restaurant-Onboarding-Service
Der Restaurant-Onboarding-Service der Essenslieferplattform ist eine fünf Jahre alte Webanwendung auf zwei von Hand aufgesetzten virtuellen Maschinen hinter einem Load Balancer mit Sticky Sessions. Das Team möchte sie auf die Container-Plattform des Unternehmens umziehen. Ein Audit anhand der Faktoren findet neun Probleme; jedes erhält ein Risiko, eine Korrektur und eine Priorität.
| 1. Passwort der Produktionsdatenbank in einer Properties-Datei im Repository (III) | Risiko: Jeder mit Lesezugriff auf den Code, auch ehemalige externe Auftragnehmer, hat die Zugangsdaten. Korrektur: das Passwort sofort rotieren, in den Secrets Manager verschieben, beim Deployment injizieren. Priorität 1. |
|---|---|
| 2. Hochgeladene Speisekarten und Logos auf der lokalen Festplatte der VM (VI, IV) | Risiko: Dateien verschwinden, wenn eine Anfrage auf der anderen VM landet oder eine VM ersetzt wird; blockiert jeden Umzug auf entsorgbare Container. Korrektur: Object Storage, mit einer einmaligen Kopie der vorhandenen Dateien. Priorität 1. |
| 3. Sessions im Prozessspeicher, Sticky Load Balancing (VI) | Risiko: Jedes Deployment meldet das Restaurantpersonal mitten im Formular ab. Korrektur: signierte Session-Tokens oder ein gemeinsamer Session-Speicher. Priorität 2. |
4. Deployment per SSH, git pull und Neustart auf jeder VM (V, II) | Risiko: Die beiden VMs führen nach einem fehlgeschlagenen Pull unterschiedlichen Code aus; kein Rollback. Korrektur: Die CI baut ein Image pro Commit; nummerierte Releases. Priorität 2. |
| 5. Migrationen laufen beim Start automatisch auf beiden Instanzen (XII) | Risiko: Zwei Instanzen laufen bei derselben Migration in eine Race Condition. Korrektur: ein separater Migrationsschritt in der Pipeline, mit Änderungen nach Expand and Contract. Priorität 2 (Priorität 1, wenn es schon eine Race Condition gab). |
6. Bei Deployments mit kill -9 beendet (IX) | Risiko: halb gespeicherte Onboarding-Formulare. Korrektur: SIGTERM behandeln, Anfragen auslaufen lassen, Readiness und eine Pre-Stop-Verzögerung ergänzen. Priorität 2. |
| 7. Logs in rotierende Dateien auf jeder VM geschrieben (XI) | Risiko: Logs gehen mit der VM verloren; schwer über Instanzen hinweg zu durchsuchen. Korrektur: strukturiertes JSON auf die Standardausgabe, zentral gesammelt. Priorität 3, günstig zusammen mit Punkt 4 umzusetzen. |
| 8. Nächtlicher Auszahlungsbericht als Cron-Eintrag nur auf VM 1 (XII, VIII) | Risiko: Der Job hört stillschweigend auf, wenn VM 1 neu aufgebaut wird, oder läuft doppelt, wenn er kopiert wird. Korrektur: ein geplanter Job auf der Plattform, idempotent gemacht. Priorität 3. |
| 9. Entwickler nutzen SQLite, die Produktion PostgreSQL (X) | Risiko: SQL, das lokal funktioniert, schlägt in der Produktion fehl. Korrektur: PostgreSQL in einem Container für Entwicklung und Tests. Priorität 3. |
Die Prioritäten folgen zuerst dem Risiko (offengelegte Zugangsdaten sind ein laufender Incident), dann dem, was die Zielplattform blockiert (lokaler Zustand), dann der Zuverlässigkeit, dann dem Komfort.
Das Team muss nicht alles vor dem Umzug beheben: Die Punkte 1 und 2 sind Voraussetzungen; die Punkte 3 bis 6 lassen sich während des Umzugs erledigen; die Punkte 7 bis 9 können folgen.
Ein solches Audit ist auch gutes Material für einen Architecture Decision Record: Es erklärt, warum jede Änderung vorgenommen wird, in welcher Reihenfolge und was bewusst zurückgestellt wurde.
Häufige Fragen
Muss jede Anwendung alle zwölf Faktoren erfüllen?
Nein. Sie sind eine Checkliste von Eigenschaften, die Deployment, Skalierung und Wiederherstellung auf einer modernen Plattform günstig machen. Behandeln Sie jede Lücke als Risiko mit Kosten, und beheben Sie zuerst die, die Ihre Plattform blockieren oder die Sicherheit gefährden, wie im Audit oben.
Gilt die Methodik für Serverless-Funktionen?
Weitgehend, und die Plattform erzwingt das meiste davon: Funktionen sind zustandslos, von außen konfiguriert, entsorgbar und werden von der Plattform geloggt. Aufmerksamkeit brauchen weiterhin Konfiguration und Secrets, Backing Services, Idempotenz und Dev/Prod-Parität, da die lokale Emulation der Event-Quellen eines Anbieters unvollkommen ist.
Ist Twelve-Factor noch relevant, seit es Kubernetes gibt?
Ja, denn Kubernetes setzt es voraus. Ein Pod, der Sessions im Speicher hält, Dateien lokal schreibt oder zwei Minuten zum Starten braucht, kämpft gegen die Rolling Updates, das Autoscaling und das Rescheduling der Plattform. Die Faktoren beschreiben, was eine Anwendung tun muss, damit die Automatisierung der Plattform hilft statt schadet.
Prüfen Sie Ihr Verständnis
Welcher einfache Test zeigt, ob Konfiguration in den Code gesickert ist?
Fragen Sie, ob die Codebasis heute veröffentlicht werden könnte, ohne irgendwelche Zugangsdaten offenzulegen. Wenn nicht, steckt Konfiguration (zumindest die Secrets) im Code.
Warum macht Build, Release, Run ein Rollback schnell?
Jedes Release ist eine unveränderliche Kombination aus einem gebauten Artefakt und Konfiguration mit eigener Identität, also bedeutet ein Rollback, das vorherige Release erneut auszuführen, ohne etwas neu zu bauen oder zu bearbeiten.
Ein Service speichert hochgeladene Dateien auf der lokalen Festplatte seines Servers. Welchen Faktor verletzt das, und was geht kaputt?
Prozesse (VI) und wohl auch Backing Services (IV): Dateien fehlen, wenn Anfragen eine andere Kopie erreichen, und gehen verloren, wenn die Instanz ersetzt wird; das blockiert horizontale Skalierung und entsorgbare Container.
Warum sollten Migrationen nicht automatisch in jedem Replikat beim Start laufen?
Mehrere Replikate können dieselbe Migration gleichzeitig ausführen und in eine Race Condition laufen, und der Start wird langsam und fragil. Migrationen sollten einmal laufen, als separater Admin-Schritt in der Pipeline, mit demselben Release.
Quellen und weiterführende Literatur
Haben Sie eine Frage zu diesem Abschnitt? ArchitectBot, der KI-Lernassistent des Kurses, antwortet zuerst aus dem Kurs.
Fragen: „Welche Twelve-Factor-Lücken sollten wir beheben, bevor wir einen alten Service auf Kubernetes umziehen, und welche können warten?“