Die Skalierung von Terraform über organisatorische Grenzen hinweg erfordert eine sorgfältige Balance zwischen Standardisierung und Flexibilität. Durch klare Team-Strukturen, durchdachte Governance, automatisierte CI/CD-Prozesse und geeignete Tooling-Unterstützung können auch komplexe Multi-Tenant-Infrastrukturen effektiv verwaltet werden. Mit diesem Fundament können Sie Ihre Terraform-Praxis von einzelnen Teams auf die gesamte Organisation ausweiten und dabei Konsistenz, Sicherheit und Effizienz gewährleisten.
Dies ist der erste Teil einer Serie über die Konzeption von Mandantenfähigkeit als Infrastructure-as-Code in großen Infrastrukturen.
Einleitung
In der Welt der modernen Cloud-Infrastrukturen klingt „Multi-Tenancy“ zunächst nach einem dieser Buzzwords, die man auf Konferenzen hört, während man heimlich auf seinem Handy E-Mails checkt. Doch für Unternehmen, die Dutzende oder gar Hunderte verschiedene Mandanten, Abteilungen oder Kunden auf einer gemeinsamen Infrastruktur bedienen, ist es bittere Realität: Mit steigender Anzahl an Tenants wächst die Komplexität überproportional (oft quadratisch oder kubisch), da sich die Anzahl der Abhängigkeiten und Schnittstellen vervielfacht.
Stellen Sie sich vor, Sie müssten 20 separate Terraform-Projekte verwalten – jedes mit eigenen Variablen, States, Backends und Modulversionen.
Nun stellen Sie sich vor, Sie müssten grundlegende Netzwerkinformationen zwischen diesen Projekten teilen, ohne kopierte Code-Blöcke zu verwenden, die bei der nächsten Änderung unweigerlich auseinanderdriften.
Und falls Ihnen das noch als überschaubar erscheint, fügen Sie noch die organisatorische Dimension hinzu: Stellen Sie sich noch zusätzlich vor, dass in den verschiedenen Projekten auch verschiedene Mitarbeiter und CI/CD-Pipelines die Infrastruktur als Infrastructure-as-Code implementieren. Vielleicht sind es sogar Teams aus anderen Unternehmensbereichen, mit unterschiedlichen Entscheidern und Managern im jeweiligen Organigramm.
Herzlich willkommen in der Welt des Multi-Tenancy-Managements mit Terraform.
Traditionelle Terraform-Ansätze stoßen hier schnell an ihre Grenzen. Das klassische Muster – ein Repository, ein State, ein Workspace – funktioniert hervorragend für überschaubare Umgebungen. Doch sobald Sie Informationen zwischen logisch getrennten Infrastrukturbereichen teilen müssen, wird es kompliziert. Es taugen Fragen auf wie:
- Wie stellen Sie sicher, dass alle Teams auf dieselben grundlegenden Netzwerkkonfigurationen zugreifen?
- Wie sorgen Sie dafür, dass Änderungen an solchen grundlegenden Konfigurationen automatisch zu den davon abhängigen Teams propagiert werden?
- Wie können Sie vermeiden, dass unterschiedliche Teams Konfigurationen erzeugen, die sich überlappen oder vielleicht sogar gegenseitig ausschließlich, wie zum Beispiel identische Netzwerkadressen?
- Wie vermeiden Sie, dass ein Team versehentlich die Ressourcen eines anderen Teams überschreibt?
- Und wie bewahren Sie trotz steigender Komplexität den Überblick?
In einem vorherigen Artikel haben wir gesehen, wie leicht Infrastruktur-Katastrophen entstehen können. Der Fall Knight Capital – wo eine inkonsistente Bereitstellung auf nur acht Servern zu einem Verlust von 460 Millionen Dollar führte – ist ein mahnendes Beispiel. Wenn schon ein einzelnes System mit wenigen Komponenten solch dramatische Folgen haben kann, wie verhält es sich dann mit komplexen Multi-Tenant-Umgebungen?
Die gute Nachricht: Mit den richtigen Mustern und Techniken lässt sich diese Komplexität beherrschen. Terraform bietet mit seinem Remote State-Konzept einen eleganten Weg, Informationen zwischen verschiedenen Infrastrukturdomänen zu teilen, ohne die Isolation der Tenants zu gefährden.
In diesem ersten Teil unserer Serie „Terraform at Scale“ werden wir uns mit genau diesem Thema befassen:
- Wie können wir Terraform effektiv einsetzen, um Multi-Tenancy-Umgebungen zu verwalten?
- Wie vererben wir Informationen gezielt zwischen organisatorischen Einheiten?
Wir werden praktische Muster erläutern, die in verschiedenen Kundenprojekten erfolgreich eingesetzt wurden, und die Ihnen helfen werden, Ihre eigene Terraform-Infrastruktur auf die nächste Stufe zu heben – ganz ohne 460-Millionen-Dollar-Fehler.
Multi-Tenancy verstehen – mehr als nur getrennte Umgebungen
Wenn wir von Multi-Tenancy – oder Mandantenfähigkeit – in der Cloud-Welt sprechen, denken viele zunächst an vollständig isolierte Umgebungen: Kunde A bekommt sein eigenes Netzwerk, Kunde B bekommt sein eigenes Netzwerk, und nie sollen die beiden sich treffen. Diese Sichtweise ist nicht falsch, aber sie greift zu kurz, besonders wenn es um Infrastructure-as-Code (IaC) geht.
Im Kontext von Terraform bedeutet Multi-Tenancy nicht nur die technische Trennung von Ressourcen, sondern auch die organisatorische Strukturierung von Code, States und Workflows. Es geht darum, wie wir unsere Infrastruktur so modularisieren, dass sie die Realität unserer Organisation widerspiegelt – sei es ein Dienstleister mit externen Kunden oder ein Unternehmen mit verschiedenen Geschäftsbereichen und Projekten.
Logische vs. physische Tenant-Trennung
Bei der physischen Trennung erhält jeder Tenant seine eigenen, dedizierten Ressourcen – eigene Server, Netzwerke, Speichersysteme. Dies bietet maximale Isolation, ist aber kostspielig und oft unnötig streng. Die logische Trennung hingegen nutzt gemeinsame physische Ressourcen, trennt aber die Daten und den Zugriff auf Anwendungsebene. In der Praxis sehen wir meist Mischformen:
- Netzwerkebene: Eigene VPCs oder Subnetze pro Tenant, aber gemeinsame physische Infrastruktur
- Compute-Ebene: Dedizierte VM-Instanzen, aber auf gemeinsamer Hardware
- Datenebene: Eigene Datenbanken oder Schemas, aber möglicherweise auf gemeinsamen Datenbankservern
- Identitätsebene: Getrennte IAM-Policies und Rollen, aber innerhalb eines gemeinsamen Identitätssystems
Mit Terraform können wir diese verschiedenen Trennungsebenen elegant abbilden, müssen aber die Informationsflüsse zwischen ihnen sorgfältig gestalten.
Die Organisation von Mandanten in der Realität
In der Praxis sind Mandantenstrukturen selten eindimensional. Ein typisches Unternehmen hat beispielsweise:
- Geschäftsbereiche (Finanzen, HR, Produktion, Vertrieb)
- Funktionale Teams innerhalb dieser Bereiche (Entwicklung, QA, Operations)
- Projekte, die oft bereichsübergreifend sind
- Umgebungen (Entwicklung, Test, Produktion) für jedes Projekt
- Regionale Strukturen aufgrund rechtlicher oder latenzbasierter Anforderungen
Diese organisatorischen Dimensionen überlagern sich, und unsere Terraform-Struktur muss diese Komplexität abbilden können.
Während Cloud-Anbieter wie AWS mit Organizations oder OCI mit Compartments hierfür hierarchische Strukturen anbieten, muss unser Terraform-Code oft noch feingranularer organisiert werden. Denn in unterschiedlichen Abteilungen und deren Teams arbeiten auch unterschiedliche Menschen, mit unterschiedlichen Kompetenz- und Verantwortungsbereichen, und vielleicht sogar mit unterschiedlichen Erwartungen, Zielen und bei globalen Playern of auch verschiedenen kulturellen Hintergründen.
All dies sorgt für eine Komplexität, welche bei der Abbildung in Code für ständige Überraschungen sorgen kann - sowohl positive als auch negative.
Die Herausforderung besteht zudem auch darin, dass die verschiedenen Dimensionen unterschiedliche Informationen bereitstellen bzw. benötigen. Zum Beispiel:
- Das Netzwerkteam definiert grundlegende Netzwerke und Subnetze,
- das Sicherheitsteam konfiguriert Firewalls, Policies und Zertifikate,
- das Storageteam kümmert sich um Filer, Block Storages, Object Storages und Backups,
- das Datenbankteam stellt die Datenbanken bereit,
- und die Anwendungsteams müssen auf diese relevanten Informationen zugreifen können, ohne sie duplizieren zu müssen.
Das Problem der Informationsvererbung
Und genau hier liegt die eigentliche Schwierigkeit: Wie stellen wir sicher, dass Änderungen an grundlegenden Infrastrukturkomponenten automatisch an alle abhängigen Komponenten weitergegeben werden?
- Wenn unser Netzwerkteam eine Subnetz-CIDR ändert, wie erfahren alle VMs davon?
- Wenn wir neue Cloud-Regionen hinzufügen, wie stellen wir sicher, dass alle Teams dieselben Standard-Einstellungen verwenden?
In einer kleinen Umgebung könnten wir all das in einem einzigen Terraform-State verwalten. Doch das führt schnell zu einem State-Monolithen mit:
- Hunderten oder Tausenden von Ressourcen
- Langsamen Planungszeiten
- Dem Risiko, dass ein Team versehentlich die Ressourcen eines anderen Teams beeinträchtigt
Die Alternative – völlig getrennte States ohne Informationsaustausch – führt zu:
- Duplizierung,
- Inkonsistenzen,
- und dem berüchtigten „Copy & Paste DevOps“, das wir alle zu vermeiden suchen.
Glücklicherweise bietet Terraform mit dem Remote-State-Konzept eine elegante Lösung für dieses Dilemma. Im nächsten Abschnitt werden wir sehen, wie wir durch die gezielte Nutzung von Remote States eine flexible, skalierbare Informationsvererbung zwischen Mandanten ermöglichen können – ohne unsere Tenant-Isolation zu gefährden.
Das Terraform Remote State
Terraform speichert Informationen über Ihre Infrastruktur in einer Zustandsdatei – dem sogenannten State File, welches als Single Source of Truth für die Infrastruktur dient.
Für jeden, der schon einmal versehentlich eine lokale .tfstate-Datei gelöscht hat, ist dies schmerzlich bewusst. Diese unscheinbare Datei ist das Gedächtnis von Terraform – ohne sie weiß Terraform nicht mehr, welche Ressourcen bereits erstellt wurden, und würde versuchen, alles neu zu provisionieren – oft mit katastrophalen Folgen.
Was ist Terraform Remote State und wozu wird es benötigt?
Dies bringt mehrere wesentliche Vorteile:
- Kollaboration: Mehrere Teammitglieder können an derselben Infrastruktur arbeiten, ohne sich State-Dateien manuell austauschen zu müssen.
- Sicherheit: State-Dateien enthalten oft sensible Informationen – eine zentrale Speicherung ermöglicht besseren Schutz.
- State-Locking: Verhindert, dass mehrere Personen gleichzeitig Änderungen durchführen, was zu Inkonsistenzen führen könnte.
- Informationsaustausch: Remote States können als Datenquelle für andere Terraform-Projekte dienen.
In großen Infrastrukturen ist dieser letzte Punkt besonders entscheidend. Er ermöglicht uns, eine skalierbare und modulare Architektur aufzubauen:
- Jedes Team oder Projekt verwaltet seine eigenen Terraform States, ohne Abhängigkeiten zu anderen Teams direkt in den Code zu schreiben.
- Gemeinsame Infrastrukturkomponenten (z. B. Netzwerke, Identitäts- und Zugriffskontrollen, gemeinsame Dienste) können als solches Remote State von den jeweiligen Verantwortungsbereichen bereitgestellt werden.
- Änderungen in der globalen Infrastruktur werden automatisch an abhängige Projekte weitergegeben.
Bedeutung von Remote State für Multi-Tenancy-Architekturen
In einer typischen Multi-Tenancy-Umgebung haben wir verschiedene Ebenen der Infrastruktur, die aufeinander aufbauen:
- Globale Infrastruktur: Grundlegende Netzwerke, IAM-Konfigurationen, gemeinsame (shared) Services
- Tenant-spezifische Ressourcen: Datenbanken, Anwendungsserver, Storage-Lösungen, ...
- Anwendungsebene: Die eigentlichen Workloads des Tenants
Mit Remote States können wir diese Schichten sauber trennen, ohne dass höhere Schichten grundlegende Informationen der unteren Schichten duplizieren müssen.
Ein Anwendungsteam kann beispielsweise auf Netzwerkinformationen zugreifen, die vom Netzwerkteam verwaltet werden, ohne eigene Netzwerkressourcen definieren zu müssen.
Remote State in der Praxis
Sehen wir uns an, wie das in der Praxis aussiehen kann:
- Ein zentrales Infrastruktur-Team verwaltet die grundlegenden Netzwerkkonfigurationen und Storagesysteme für alle Teams in einem eigenen Terraform-Projekt.
- Das zentrale Security NOC definiert die Firewalls und zugehörigen Regeln sowie die Policies.
- Das Datenbanken-Team verwaltet die Datenbanken und stellt den Tenants isolierte Datenbank-Partitionen zur Verfügung.
- Ein Anwendungsteam kann dann in seinen eigenen Terraform-Projekten der verschiedenen Value Streams auf diese Netzwerkinformationen, Storagesysteme, Sicherheitsvorgaben und Datenbanken zugreifen, ohne sie erneut zu definieren. Ebenso können die Pipelines der verschiedenen Value Streams über Remote State auch miteinander Daten austauschen.
- Falls das Netzwerk-, Storage-, Security- oder Datenbankenteam Änderungen vornimmt, fließen diese automatisch in die nachgelagerten Projekte ein.
Die data source "terraform_remote_state" im Detail
Das Herzstück dieses Informationsaustauschs ist die terraform_remote_state Data Source. Sie ermöglicht es einem Terraform-Projekt, auf den State eines anderen Projekts zuzugreifen. Hier ein einfaches Beispiel:
data "terraform_remote_state" "network" { backend = "remote" config = { organization = "my-org" workspaces = { name = "network-global" } } } resource "cloud_instance" "app_server" { image_id = "image-12345678" instance_type = "standard" subnet_id = data.terraform_remote_state.network.outputs.private_subnet_id }
In diesem Beispiel greift unser Anwendungsteam auf die Subnetz-ID zu, die vom Netzwerkteam definiert wurde. Entscheidend ist, dass wir nur auf Werte zugreifen können, die explizit als output definiert wurden – dies schafft eine klare Schnittstelle zwischen den Projekten.
Ein weiteres mächtiges Feature: Wir können auf States aus verschiedenen Backends zugreifen und so Informationen zwischen unterschiedlichen Umgebungen (z.B. AWS und OCI) austauschen. Für Organisationen, die Multiple-Cloud-Strategien verfolgen, ist dies besonders wertvoll.
Sicherheitsüberlegungen bei der Freigabe von State-Informationen
So leistungsfähig Remote States auch sind – sie erfordern sorgfältige Planung bezüglich Sicherheit. State-Dateien enthalten potentiell sensible Informationen:
- Zugriffskontrolle: Nicht jedes Team sollte Zugriff auf jeden Remote State haben. Nutzen Sie die Zugriffskontrollen Ihres Backend-Providers (z.B. IAM-Policies für S3).
- Sensible Daten: State-Dateien können Passwörter und andere Secrets enthalten. Nutzen Sie Terraform's sensitive = true für Outputs und erwägen Sie den Einsatz von HashiCorp Vault für kritische Geheimnisse.
- Verschlüsselung: Stellen Sie sicher, dass Ihre State-Dateien im Ruhezustand und während der Übertragung verschlüsselt sind.
- Output-Kontrolle: Geben Sie nur die wirklich benötigten Informationen über Outputs frei. Jeder Output schafft eine Abhängigkeit und potentielle Sicherheitsrisiken. Packen Sie keine sensible Daten in Outputs. Vermeiden Sie in Outputs die Verwendung von sensitive = true generell, denn diese Daten lassen sich nicht vererben.
Ein besonders effektives Muster ist die Erstellung spezifischer "Schnittstellen-States" oder "Proxy-States", die ausschließlich dazu dienen, kuratierte Informationen für andere Teams bereitzustellen. Diese enthalten keine tatsächlichen Ressourcen, sondern nur Data Sources, die Informationen aus dem eigentlichen Infrastruktur-State auslesen und als gefilterte Outputs bereitstellen. Der Mandant erhält dann Zugriff auf das State mit den ausgewählten Informationen, aber nicht auf das Original mit potenziell sensitiven oder für andere Tenants bestimmte Daten.
Mit diesen Grundlagen können wir nun ein Architekturbeispiel betrachten: Wie sieht Multi-Tenancy in der Praxis aus, und wie setzen wir Remote States ein, um Informationen zwischen Organisationseinheiten zu vererben?
Das klären wir in nicht allzu ferner Zukunft im nächsten Abschnitt dieser Serie.