Das Problem: Snowflake-Server

Jeder, der in der Softwareentwicklung arbeitet, kennt das Szenario: Der Produktionsserver, den nur eine Person konfiguriert hat, die inzwischen nicht mehr im Unternehmen ist. Hunderte von manuellen Anpassungen, undokumentiert, Schicht für Schicht entstanden. Diesen Server kann niemand reproduzieren. Er ist ein Snowflake, einzigartig, fragil und im Fehlerfall nicht wiederherstellbar.

Infrastructure as Code (IaC) löst dieses Problem, indem die gesamte Infrastruktur in versionierten, ausführbaren Dateien beschrieben wird. Kein manuelles Klicken in der AWS Console, keine SSH-Sessions, in denen “nur kurz etwas angepasst wird”. Die Infrastruktur ist Code, und damit gelten dieselben Qualitätsmaßstäbe wie für Anwendungscode: Reviews, Versionierung, Tests und automatisierte Deployments.

Terraform: Infrastruktur provisionieren

Terraform von HashiCorp ist ein deklaratives Tool zur Provisionierung von Infrastruktur. Man beschreibt den gewünschten Zustand, und Terraform berechnet den Weg dorthin.

resource "aws_instance" "app_server" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.medium"
  subnet_id     = aws_subnet.private.id

  tags = {
    Name        = "app-server-prod"
    Environment = "production"
    ManagedBy   = "terraform"
  }
}

resource "aws_security_group" "app" {
  name_prefix = "app-"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 8080
    to_port     = 8080
    protocol    = "tcp"
    cidr_blocks = [aws_subnet.private.cidr_block]
  }
}

Die Stärke von Terraform liegt im State Management. Terraform speichert den aktuellen Zustand der Infrastruktur und kann bei jeder Ausführung einen Plan erstellen, der zeigt, welche Änderungen vorgenommen werden. Das macht Infrastrukturänderungen vorhersagbar und reviewbar.

Terraform State: Segen und Herausforderung

Der Terraform State ist gleichzeitig das mächtigste Feature und die größte Fehlerquelle. Er muss zentral und sicher gespeichert werden, ein lokaler State-File ist in Teamprojekten nicht praktikabel. S3 mit DynamoDB-Locking hat sich als robuste Lösung für AWS-Umgebungen etabliert:

terraform {
  backend "s3" {
    bucket         = "terraform-state-prod"
    key            = "infrastructure/terraform.tfstate"
    region         = "eu-central-1"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

Ansible: Server konfigurieren

Während Terraform die Infrastruktur provisioniert, also VMs, Netzwerke, Load Balancer erstellt, übernimmt Ansible die Konfiguration der erstellten Maschinen. Die Trennung ist wichtig: Terraform weiß, dass ein Server existieren soll. Ansible weiß, wie der Server konfiguriert sein soll.

Ansible arbeitet agentless über SSH und verwendet YAML-Playbooks:

- name: Configure application server
  hosts: app_servers
  become: true
  tasks:
    - name: Install Java 11
      apt:
        name: openjdk-11-jdk
        state: present

    - name: Create application user
      user:
        name: appuser
        system: true
        shell: /bin/false

    - name: Deploy application
      copy:
        src: "{{ artifact_path }}"
        dest: /opt/app/application.jar
        owner: appuser
        mode: '0644'
      notify: Restart application

  handlers:
    - name: Restart application
      systemd:
        name: application
        state: restarted

Idempotenz: Der Schlüssel zu zuverlässiger Automatisierung

Ein fundamentales Prinzip sowohl von Terraform als auch von Ansible ist Idempotenz. Eine Operation ist idempotent, wenn sie bei mehrfacher Ausführung dasselbe Ergebnis liefert wie bei einmaliger Ausführung. Das bedeutet: Ein Playbook kann beliebig oft ausgeführt werden, ohne unerwünschte Seiteneffekte zu erzeugen.

In der Praxis heißt das:

  • apt: state=present installiert ein Paket nur, wenn es noch nicht installiert ist
  • terraform apply ändert nur Ressourcen, die vom gewünschten Zustand abweichen
  • Ein korrekt geschriebenes Playbook kann als Drift Detection dienen, es zeigt an, ob sich etwas am System verändert hat

GitOps: Die Infrastruktur im Repository

Die konsequente Umsetzung von IaC führt zu GitOps: Die gesamte Infrastruktur wird in einem Git-Repository verwaltet. Änderungen erfolgen über Pull Requests, werden reviewed und nach dem Merge automatisch angewendet.

Der typische Workflow sieht so aus:

  1. Branch erstellen, Feature-Branch für die Infrastrukturänderung
  2. Änderung implementieren, Terraform-Konfiguration oder Ansible-Playbook anpassen
  3. Plan erstellen, terraform plan zeigt die geplanten Änderungen
  4. Review, Kollegen prüfen den Plan und den Code
  5. Merge, Nach Approval wird der Branch gemergt
  6. Apply, Die CI/CD-Pipeline wendet die Änderungen automatisch an

Dieser Workflow bringt dieselbe Nachvollziehbarkeit in die Infrastruktur, die wir im Anwendungscode längst praktizieren. Jede Änderung ist dokumentiert, reviewt und reproduzierbar.

Reproduzierbare Umgebungen: Dev, Staging, Prod

Einer der größten praktischen Vorteile von IaC ist die Möglichkeit, identische Umgebungen für Development, Staging und Production zu erstellen. In Terraform lässt sich das über Workspaces oder Module-Parametrisierung umsetzen:

module "environment" {
  source = "./modules/app-environment"

  environment   = var.environment  # "dev", "staging", "prod"
  instance_type = var.environment == "prod" ? "t3.large" : "t3.small"
  instance_count = var.environment == "prod" ? 3 : 1
  enable_monitoring = var.environment == "prod" ? true : false
}

Die Umgebungen unterscheiden sich in Größe und Redundanz, aber die Architektur ist identisch. Das eliminiert die klassische Aussage “Aber auf meiner Maschine funktioniert es”, oder zumindest verschiebt sie auf eine beherrschbare Ebene.

Fazit

Infrastructure as Code ist kein optionales Nice-to-have, sondern eine Grundvoraussetzung für professionelle Softwareentwicklung. Die Kombination aus Terraform für die Provisionierung und Ansible für die Konfiguration deckt den gesamten Lebenszyklus ab. Der initiale Aufwand für die Einführung von IaC ist signifikant, wird aber durch reproduzierbare Umgebungen, nachvollziehbare Änderungen und die Möglichkeit zur Automatisierung schnell ausgeglichen. Wer heute noch Server manuell konfiguriert, arbeitet mit einem Risiko, das nicht mehr zeitgemäß ist.