AWS / Cloud
Terraform auf AWS: Infrastructure as Code für Einsteiger
Wer AWS-Infrastruktur manuell über die Konsole verwaltet, kennt das Problem: Ein vergessenes Security-Group-Ruleset hier, eine falsch konfigurierte IAM-Policy dort – und plötzlich unterscheiden sich Staging- und Produktionsumgebung in Details, die niemand mehr nachvollziehen kann. Terraform löst dieses Problem, indem es Infrastruktur als versionierten, wiederholbaren Code beschreibt. Dieser Artikel erklärt die Grundkonzepte und zeigt, wie man damit auf AWS praktisch arbeitet.
Was ist Terraform?
Terraform ist ein Open-Source-Werkzeug von HashiCorp, das Infrastructure as Code (IaC) umsetzt. Statt Ressourcen manuell anzulegen, schreibt man sie in der deklarativen Sprache HCL (HashiCorp Configuration Language) nieder. Terraform liest diese Dateien, vergleicht den gewünschten Zustand mit dem tatsächlichen Zustand der Infrastruktur und führt nur die notwendigen Änderungen durch. Es gibt keine Skriptlogik, die Schritt für Schritt Befehle abarbeitet – man beschreibt was existieren soll, nicht wie es erstellt wird.
Terraform unterstützt über sogenannte Provider Hunderte von Plattformen. Der AWS-Provider ist einer der am weitesten entwickelten und deckt nahezu alle AWS-Dienste ab – von EC2 und S3 bis zu RDS, EKS und Lambda.
Die drei Kernkonzepte: State, Plan, Apply
Terraform arbeitet mit einem State: einer JSON-Datei, die den aktuell verwalteten Zustand der Infrastruktur speichert. Standardmäßig liegt diese Datei lokal, für Teamarbeit sollte sie jedoch remote gespeichert werden – zum Beispiel in einem S3-Bucket mit DynamoDB-Locking.
Der Workflow besteht aus drei Schritten:
- terraform init – lädt den AWS-Provider und initialisiert das Backend.
- terraform plan – zeigt eine Vorschau aller geplanten Änderungen, ohne etwas anzufassen.
- terraform apply – setzt die Änderungen durch, nach einer abschließenden Bestätigung.
Der Plan-Schritt ist besonders wertvoll: Er macht sichtbar, ob eine Änderung eine Ressource ersetzt (destroy + create) oder nur aktualisiert. Das verhindert ungewollte Ausfallzeiten.
Erste Schritte: Projekt aufsetzen
Terraform benötigt lokal lediglich das CLI-Binary und AWS-Credentials – entweder über
Umgebungsvariablen, eine ~/.aws/credentials-Datei oder eine IAM-Rolle. Eine
minimale Projektstruktur sieht so aus:
mkdir tf-demo && cd tf-demo
# Hauptkonfiguration
touch main.tf variables.tf outputs.tf
# Remote Backend-Konfiguration (optional, aber empfohlen)
touch backend.tf
In main.tf definiert man zunächst den required Provider und die Region:
Brauchst du Unterstützung bei der Umsetzung?
30-Min Call — kostenlos, unverbindlich, konkret.
Ressourcen definieren: Ein S3-Bucket als Beispiel
Eine der einfachsten AWS-Ressourcen ist ein S3-Bucket. Die folgende HCL-Konfiguration erstellt einen Bucket mit aktivierter Versionierung und blockiertem öffentlichem Zugriff:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
resource "aws_s3_bucket" "app_assets" {
bucket = "mein-app-assets-${var.environment}"
tags = {
Environment = var.environment
ManagedBy = "terraform"
}
}
resource "aws_s3_bucket_versioning" "app_assets" {
bucket = aws_s3_bucket.app_assets.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_public_access_block" "app_assets" {
bucket = aws_s3_bucket.app_assets.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
Zu beachten: Ressourcenattribute anderer Ressourcen lassen sich direkt referenzieren –
aws_s3_bucket.app_assets.id gibt die Bucket-ID zurück, ohne sie hartcodieren zu
müssen. Terraform löst diese Abhängigkeiten selbst auf und erstellt Ressourcen in der richtigen
Reihenfolge.
Variablen und Outputs
Hardcodierte Werte in Terraform-Dateien sind ein Antipattern. Variablen entkoppeln
Konfiguration von Code. Sie werden in variables.tf deklariert:
Typen können string, number, bool, list
oder map sein. Sensitive Variablen – etwa Datenbankpasswörter – können mit
sensitive = true markiert werden, damit Terraform sie nicht im Plan-Output anzeigt.
Outputs exportieren Werte nach außen und sind nützlich, wenn mehrere Terraform-Module
miteinander kommunizieren sollen oder wenn man nach einem Apply die ARN einer neu erstellten
Ressource benötigt. Sie werden in outputs.tf definiert und erscheinen am Ende von
terraform apply im Terminal.
Remote State mit S3 und DynamoDB
Sobald mehrere Personen an derselben Infrastruktur arbeiten, ist lokaler State gefährlich. Zwei parallele Applies können den State korrumpieren. Die Lösung ist ein Remote Backend mit State Locking:
Ein S3-Bucket speichert die State-Datei, eine DynamoDB-Tabelle übernimmt das Locking. Die
Tabelle braucht lediglich einen Partition Key namens LockID vom Typ String. Das
Backend wird in backend.tf konfiguriert. Nach terraform init migriert
Terraform den bestehenden lokalen State automatisch in den Bucket.
Wichtig: Der S3-Bucket und die DynamoDB-Tabelle für den Remote State müssen manuell oder über ein separates Bootstrap-Projekt erstellt werden – sie können nicht durch denselben Terraform-Code verwaltet werden, der sie als Backend nutzt.
Module: Wiederverwendbare Bausteine
Ein Terraform-Modul ist schlicht ein Verzeichnis mit .tf-Dateien. Module machen
Konfigurationen wiederverwendbar und erzwingen Konventionen. Das Terraform Registry enthält
viele geprüfte Module für gängige AWS-Patterns – etwa für VPC-Setups, EKS-Cluster oder
RDS-Instanzen.
Ein Modul wird mit dem module-Block eingebunden. Man übergibt Variablen als
Argumente und kann die Outputs des Moduls in anderen Ressourcen verwenden. Eigene Module lohnen
sich besonders, wenn dieselbe Ressourcenkombination in mehreren Umgebungen oder Projekten
auftaucht – etwa ein Standard-Setup aus EC2-Instanz, Security Group und IAM-Rolle.
Typische Anfängerfehler und wie man sie vermeidet
State-Drift: Wer AWS-Ressourcen außerhalb von Terraform ändert – etwa über
die Konsole –, erzeugt Drift zwischen State und Realität. terraform refresh
synchronisiert den State, aber langfristig sollte Infrastruktur ausschließlich über Terraform
geändert werden.
Zu breite IAM-Rechte: Terraform benötigt IAM-Rechte, um Ressourcen zu verwalten. Die Versuchung ist groß, einfach AdministratorAccess zu vergeben. Besser ist es, eine dedizierte IAM-Rolle mit genau den Rechten zu erstellen, die für die verwalteten Ressourcen nötig sind.
Fehlende Lifecycle-Regeln: Manche Ressourcen – etwa RDS-Instanzen oder
Elasticsearch-Domains – werden bei Parameteränderungen ersetzt statt aktualisiert. Mit
lifecycle { prevent_destroy = true } schützt man kritische Ressourcen vor
versehentlichem Löschen.
Provider-Version nicht gepinnt: Ohne eine explizite Versionseinschränkung im
required_providers-Block kann terraform init eine neuere,
inkompatible Provider-Version laden. Immer eine Constraint wie ~> 5.0 angeben.
Nächste Schritte
Mit den beschriebenen Grundlagen lässt sich bereits eine solide AWS-Infrastruktur verwalten. Wer tiefer einsteigen möchte, sollte sich mit Terraform Workspaces beschäftigen – sie ermöglichen mehrere State-Instanzen innerhalb desselben Projekts, etwa für verschiedene Umgebungen. Für komplexere Projekte bietet sich Terragrunt an, ein Wrapper um Terraform, der DRY-Konfiguration und modulare Strukturen erleichtert.
Ebenso lohnt ein Blick auf terraform import: Bestehende, manuell erstellte
AWS-Ressourcen lassen sich damit rückwirkend unter Terraform-Verwaltung stellen, ohne sie neu
erstellen zu müssen. Das ist der häufigste erste Schritt, wenn ein bereits laufendes AWS-Konto
auf IaC umgestellt werden soll.