Wenn eine Infrastruktur-Konfiguration mehrere Umgebungen bedienen muss

Sie haben eine Terraform-Konfiguration, die Ihr VPC, Subnetze und Load Balancer definiert. Sie funktioniert perfekt für Ihre Entwicklungsumgebung. Jetzt brauchen Sie denselben Aufbau für Staging und Production. Der naive Ansatz ist, den gesamten Ordner dreimal zu kopieren und ein paar Variablenwerte zu ändern. Das funktioniert, bis Sie eine Security-Group-Regel aktualisieren müssen und feststellen, dass Sie dieselbe Änderung an drei Stellen vornehmen müssen – in der Hoffnung, keine zu verpassen.

Das Problem liegt nicht im Schreiben von Infrastruktur-Code. Das Problem ist, denselben Code über mehrere Umgebungen hinweg zu verwalten, ohne alles zu duplizieren oder versehentlich die Produktion zu beeinträchtigen, während Sie an der Entwicklung arbeiten.

Zwei gängige Ansätze lösen dieses Problem: Workspaces und separate Root-Module. Sie handhaben das gleiche Problem auf grundlegend unterschiedliche Weise, und die Wahl zwischen ihnen hängt davon ab, wie Ihr Team arbeitet und wie stark Ihre Umgebungen getrennt sein müssen.

Workspaces: Eine Codebasis, mehrere Zustände

Workspaces sind eine Funktion, die in Tools wie Terraform integriert ist und es Ihnen ermöglicht, denselben Quellcode mit verschiedenen State-Dateien zu verwenden. Stellen Sie es sich wie einen Konfigurationsordner vor, der drei verschiedene Umgebungen erzeugen kann. Der Code ist identisch. Was sich ändert, ist die State-Datei, die nachverfolgt, was bereitgestellt wurde.

Der Workflow ist unkompliziert. Sie erstellen einen Workspace für jede Umgebung und wechseln dann vor dem Ausführen von Änderungen in den richtigen Workspace. Das Tool leitet State-Lese- und Schreibvorgänge automatisch an den richtigen Backend-Speicherort weiter, basierend darauf, welcher Workspace aktiv ist. Wenn Sie sich im Development-Workspace befinden, betreffen Ihre Änderungen nur den Development-State. Der Production-State bleibt unberührt.

Das folgende Diagramm veranschaulicht den strukturellen Unterschied zwischen den beiden Ansätzen.

So sieht dieser Workflow in der Praxis aus:

# Erstelle einen Workspace für jede Umgebung
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod

# Wechsel zum Development-Workspace
export TF_WORKSPACE=dev
# Oder: terraform workspace select dev

# Plane und wende Änderungen für den aktiven Workspace an
export TF_VAR_instance_type=t3.micro
terraform plan -out=dev.tfplan
terraform apply dev.tfplan

# Wechsel zur Produktion, wenn bereit
export TF_WORKSPACE=prod
export TF_VAR_instance_type=t3.large
terraform plan -out=prod.tfplan
terraform apply prod.tfplan
flowchart TD subgraph Workspaces A1["Eine Codebasis"] --> B1["Workspace: dev"] A1 --> C1["Workspace: staging"] A1 --> D1["Workspace: prod"] B1 --> E1["State: dev"] C1 --> F1["State: staging"] D1 --> G1["State: prod"] E1 --> H1["Ein Backend"] F1 --> H1 G1 --> H1 end subgraph Root_Modules I1["Geteiltes Modul"] --> J1["Root-Konfig: dev"] I1 --> K1["Root-Konfig: staging"] I1 --> L1["Root-Konfig: prod"] J1 --> M1["Backend: dev"] K1 --> N1["Backend: staging"] L1 --> O1["Backend: prod"] end

Dies funktioniert gut, wenn Ihre Umgebungen ähnlich sind und die Unterschiede auf Variablenwerte beschränkt sind. Vielleicht verwendet die Entwicklung kleinere Instanzgrößen, Staging mittlere Instanzen und die Produktion die größten. Die Struktur ist dieselbe. Nur die Zahlen ändern sich.

Aber Workspaces haben versteckte Kosten. Da alle Umgebungen in derselben Codebasis leben, ist das Risiko, im falschen Workspace zu arbeiten, real. Ein Entwickler, der im Development-Workspace arbeitet, kann versehentlich einen Plan oder Apply gegen die Produktion ausführen, wenn er vergisst, zu wechseln. Das Tool verhindert dies nicht. Es verfolgt nur, welcher Workspace aktiv ist. Die menschliche Aufmerksamkeit wird zur Sicherheitsbarriere.

Es gibt eine weitere Einschränkung. Wenn Sie die Konfigurationsstruktur ändern, wird die Änderung in jeder Umgebung gleichzeitig wirksam. Sie können nicht zuerst Staging aktualisieren, überprüfen, ob es funktioniert, und dann dieselbe Änderung einen Tag später in die Produktion einspielen. Alle Umgebungen bewegen sich gemeinsam, da sie denselben Code teilen. Wenn die Änderung etwas kaputt macht, bricht es überall gleichzeitig.

Root-Module: Separate Ordner, gemeinsame Logik

Die Alternative besteht darin, jeder Umgebung ein eigenes Root-Modul zu geben. Statt eines Ordners mit drei Workspaces haben Sie drei Ordner: dev, staging und prod. Jeder Ordner enthält seine eigene Hauptkonfigurationsdatei und seine eigene State-Backend-Konfiguration. Sie sind vollständig unabhängig.

Aber Sie schreiben die Infrastrukturlogik nicht dreimal neu. Jedes Root-Modul ruft dieselben gemeinsamen Module aus einem modules-Verzeichnis auf. Die VPC-Definition, die Subnetzlogik, die Load-Balancer-Konfiguration – all das lebt in wiederverwendbaren Modulen. Die Root-Module rufen diese Module nur mit umgebungsspezifischen Variablen auf.

Der Vorteil liegt auf der Hand. Sie können nicht versehentlich die Produktion ändern, während Sie in der Entwicklung arbeiten, da Sie explizit das Verzeichnis wechseln müssen. Die Trennung ist physisch, nicht nur logisch. Sie können Umgebungen auch unabhängig voneinander aktualisieren. Die Produktion kann auf einer stabilen Version eines Moduls bleiben, während die Entwicklung die neueste Version mit experimentellen Änderungen verwendet. Staging kann zuerst aktualisiert, getestet und erst dann in die Produktion übernommen werden.

Der Nachteil ist die Duplizierung, aber es ist eine strukturelle Duplizierung, keine logische. Sie wiederholen die Modulaufrufe und die Variablendefinitionen für jede Umgebung. Sie wiederholen nicht die eigentliche Infrastrukturlogik. Die Module enthalten die Logik, und sie werden gemeinsam genutzt. Die Duplizierung liegt in der Verkabelung, nicht in der Implementierung.

Wann man was verwendet

Workspaces passen zu kleinen Teams mit wenigen Umgebungen und minimalen Unterschieden zwischen ihnen. Wenn Sie zwei nahezu identische Umgebungen haben, reduzieren Workspaces den Overhead. Sie schreiben den Code einmal, und der Workspace kümmert sich um die State-Trennung.

Root-Module funktionieren besser für größere Teams, Umgebungen, die eine strikte Trennung erfordern, oder Situationen, in denen jede Umgebung unterschiedliche Genehmigungs-Workflows benötigt. Wenn Produktionsänderungen einen Pull-Request-Review, eine Manager-Freigabe und ein Änderungsfenster erfordern, während Entwicklungsänderungen direkt angewendet werden können, machen Root-Module diese Trennung natürlich. Jeder Umgebungsordner kann seine eigene CI/CD-Pipeline mit unterschiedlichen Hürden haben.

Viele Teams beginnen mit Workspaces, weil sie einfacher einzurichten sind. Wenn das Team wächst und die Anzahl der Umgebungen zunimmt, migrieren sie zu Root-Modulen. Die Migration ist nicht schmerzhaft, da die Module bereits getrennt sind. Sie erstellen einfach neue Root-Ordner, die dieselben Module aufrufen.

Eine praktische Checkliste

Bevor Sie sich für einen Ansatz entscheiden, gehen Sie diese Fragen durch:

  • Wie viele Umgebungen verwalten Sie? Mehr als drei sprechen für Root-Module.
  • Benötigen Umgebungen unterschiedliche Genehmigungsprozesse? Ja bedeutet Root-Module.
  • Kann ein Fehler in einer Umgebung eine andere beeinträchtigen? Wenn ja, reduzieren Root-Module dieses Risiko.
  • Ist Ihre Teamgröße größer als fünf Personen? Größere Teams profitieren von einer expliziten Ordner-Trennung.
  • Müssen Sie Umgebungen zu unterschiedlichen Zeiten aktualisieren? Root-Module ermöglichen phasenweise Rollouts.

Wenn Sie drei oder mehr dieser Fragen mit Ja beantwortet haben, beginnen Sie mit Root-Modulen. Wenn Sie die meisten mit Nein beantwortet haben, werden Ihnen Workspaces vorerst gute Dienste leisten.

Die konkrete Erkenntnis

Workspaces und Root-Module lösen dasselbe Problem mit unterschiedlichen Kompromissen. Workspaces reduzieren die Code-Duplizierung, erhöhen aber das operationelle Risiko. Root-Module fügen strukturelle Duplizierung hinzu, geben Ihnen aber klare Grenzen zwischen den Umgebungen. Wählen Sie basierend darauf, wie Ihr Team arbeitet und wie viel Isolation Ihre Umgebungen benötigen. Fangen Sie einfach an, aber wissen Sie, wann Sie wechseln müssen. Das Ziel ist nicht, am ersten Tag den perfekten Ansatz zu wählen. Das Ziel ist zu erkennen, wann Ihr aktueller Ansatz anfängt, mehr Probleme zu verursachen, als er löst.