Infrastructure as Code mit Terraform: Vom manuellen zum automatisierten Cloud-Management

Verwalten Sie die Cloud-Infrastruktur mit Terraform. Behandelt HCL-Syntax, Module, Statusverwaltung, CI/CD-Integration und Bereitstellungsstrategien für mehrere Umgebungen.

E
ECOSIRE Research and Development Team
|16. März 20267 Min. Lesezeit1.4k Wörter|

Infrastruktur als Code mit Terraform: Vom manuellen zum automatisierten Cloud-Management

Organisationen, die Infrastructure as Code (IaC) nutzen, stellen Umgebungen 90 % schneller bereit und erleben 60 % weniger konfigurationsbedingte Ausfälle als Unternehmen, die die Infrastruktur manuell verwalten. Terraform hat sich zum dominierenden IaC-Tool entwickelt, mit über 3.000 Anbietern, die alle wichtigen Cloud-Plattformen und SaaS-Dienste unterstützen.

Dieser Leitfaden behandelt die praktische Terraform-Nutzung für Webanwendungen, ERP-Systeme und E-Commerce-Plattformen – von Ihrer ersten Ressourcendefinition bis hin zu produktionstauglichen Multiumgebungsbereitstellungen.

Wichtige Erkenntnisse

– Terraform macht Infrastrukturänderungen durch Versionskontrolle überprüfbar, testbar und umkehrbar – Remote-Statusverwaltung verhindert Konflikte, wenn mehrere Ingenieure die Infrastruktur ändern

  • Module kapseln wiederverwendbare Muster und reduzieren die Konfiguration von Hunderten von Zeilen auf wenige Parameter – Die Terraform Cloud- oder CI/CD-Integration erzwingt die Disziplin „Planen vor Anwenden“ für sichere Änderungen

Warum Terraform für KMUs

Das manuelle Infrastrukturproblem

Ohne IaC lebt Ihr Infrastrukturwissen in:

– Klickpfade der AWS-Konsole, die niemand dokumentiert hat

  • SSH-Befehle wurden vor Monaten ausgeführt, an die sich niemand erinnert
  • Konfigurationsdateien direkt auf Servern bearbeitet
  • Das mentale Modell eines Ingenieurs, „wie das Netzwerk funktioniert“

Mit Terraform lebt Ihre Infrastruktur in Git. Jede Änderung ist eine Pull-Anfrage. Jeder Einsatz ist reproduzierbar. Jeder Ingenieur kann das Gesamtbild verstehen.

Kernkonzepte

KonzeptBeschreibung
AnbieterPlugin, das mit einer Cloud-Plattform (AWS, GCP, Azure, Cloudflare) interagiert
RessourceEine einzelne Infrastrukturkomponente (EC2-Instanz, RDS-Datenbank, S3-Bucket)
DatenquelleSchreibgeschützter Verweis auf bestehende Infrastruktur
VariableEingabeparameter für wiederverwendbare Konfiguration
AusgabeExportierter Wert aus einer Terraform-Konfiguration
StaatAufzeichnung dessen, was Terraform verwaltet und welche aktuellen Attribute es hat
ModulWiederverwendbare Gruppe von Ressourcen mit einer definierten Schnittstelle

Erste Terraform-Konfiguration

AWS VPC und EC2 für eine Webanwendung

# providers.tf
terraform {
  required_version = ">= 1.7"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  backend "s3" {
    bucket = "ecosire-terraform-state"
    key    = "production/terraform.tfstate"
    region = "us-east-1"
    encrypt = true
    dynamodb_table = "terraform-locks"
  }
}

provider "aws" {
  region = var.aws_region
}

# variables.tf
variable "aws_region" {
  type    = string
  default = "us-east-1"
}

variable "environment" {
  type    = string
  default = "production"
}

variable "instance_type" {
  type    = string
  default = "t3.large"
}

# main.tf
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name        = "${var.environment}-vpc"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

resource "aws_subnet" "public" {
  count             = 2
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.${count.index + 1}.0/24"
  availability_zone = data.aws_availability_zones.available.names[count.index]

  map_public_ip_on_launch = true

  tags = {
    Name = "${var.environment}-public-${count.index + 1}"
  }
}

resource "aws_instance" "app" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = var.instance_type
  subnet_id     = aws_subnet.public[0].id

  vpc_security_group_ids = [aws_security_group.app.id]
  key_name               = aws_key_pair.deploy.key_name

  root_block_device {
    volume_size = 50
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name        = "${var.environment}-app"
    Environment = var.environment
  }
}

resource "aws_db_instance" "postgres" {
  identifier     = "${var.environment}-db"
  engine         = "postgres"
  engine_version = "17"
  instance_class = "db.t3.medium"

  allocated_storage     = 50
  max_allocated_storage = 200
  storage_encrypted     = true

  db_name  = "ecosire"
  username = "app"
  password = var.db_password

  vpc_security_group_ids = [aws_security_group.db.id]
  db_subnet_group_name   = aws_db_subnet_group.main.name

  backup_retention_period = 7
  backup_window           = "03:00-04:00"
  maintenance_window      = "sun:04:00-sun:05:00"

  skip_final_snapshot = false
  final_snapshot_identifier = "${var.environment}-db-final"

  tags = {
    Environment = var.environment
  }
}

Module für wiederverwendbare Infrastruktur

Erstellen eines Webanwendungsmoduls

# modules/web-app/main.tf
variable "name" {
  type = string
}

variable "environment" {
  type = string
}

variable "instance_type" {
  type    = string
  default = "t3.medium"
}

variable "vpc_id" {
  type = string
}

variable "subnet_ids" {
  type = list(string)
}

resource "aws_lb" "app" {
  name               = "${var.name}-${var.environment}-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb.id]
  subnets            = var.subnet_ids
}

resource "aws_lb_target_group" "app" {
  name     = "${var.name}-${var.environment}-tg"
  port     = 3000
  protocol = "HTTP"
  vpc_id   = var.vpc_id

  health_check {
    path                = "/health"
    healthy_threshold   = 2
    unhealthy_threshold = 3
    interval            = 30
  }
}

resource "aws_autoscaling_group" "app" {
  name                = "${var.name}-${var.environment}-asg"
  min_size            = 2
  max_size            = 10
  desired_capacity    = 2
  vpc_zone_identifier = var.subnet_ids
  target_group_arns   = [aws_lb_target_group.app.arn]

  launch_template {
    id      = aws_launch_template.app.id
    version = "$Latest"
  }

  tag {
    key                 = "Name"
    value               = "${var.name}-${var.environment}"
    propagate_at_launch = true
  }
}

output "alb_dns_name" {
  value = aws_lb.app.dns_name
}

Verwendung des Moduls

# environments/production/main.tf
module "web" {
  source = "../../modules/web-app"

  name          = "ecosire-web"
  environment   = "production"
  instance_type = "t3.large"
  vpc_id        = module.network.vpc_id
  subnet_ids    = module.network.public_subnet_ids
}

module "api" {
  source = "../../modules/web-app"

  name          = "ecosire-api"
  environment   = "production"
  instance_type = "t3.large"
  vpc_id        = module.network.vpc_id
  subnet_ids    = module.network.public_subnet_ids
}

Staatsverwaltung

Remote-Status mit S3

# Bootstrap: create the state bucket and DynamoDB table manually or with a separate config
resource "aws_s3_bucket" "terraform_state" {
  bucket = "ecosire-terraform-state"

  lifecycle {
    prevent_destroy = true
  }
}

resource "aws_s3_bucket_versioning" "terraform_state" {
  bucket = aws_s3_bucket.terraform_state.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_dynamodb_table" "terraform_locks" {
  name         = "terraform-locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}

Die Statussperre über DynamoDB verhindert, dass zwei Ingenieure terraform apply gleichzeitig ausführen, was den Status beschädigen könnte.

Dateisicherheit angeben

Die Terraform-Statusdatei enthält vertrauliche Informationen, einschließlich Datenbankkennwörtern, API-Schlüsseln und Ressourcen-IDs. Schützen Sie es:

  • Im Ruhezustand verschlüsseln: S3-Bucket-Versionierung + serverseitige Verschlüsselung
  • Während der Übertragung verschlüsseln: HTTPS nur für den Statuszugriff
  • Zugriff einschränken: IAM-Richtlinien schränken ein, wer den Status lesen/schreiben kann
  • Niemals an Git übergeben: Statusdateien dürfen niemals der Versionskontrolle unterliegen
  • Versionierung aktivieren: Die S3-Versionierung ermöglicht die Wiederherstellung nach einem beschädigten Zustand

CI/CD-Integration

GitHub-Aktionen Terraform-Pipeline

name: Terraform
on:
  pull_request:
    paths: ['infrastructure/**']
  push:
    branches: [main]
    paths: ['infrastructure/**']

jobs:
  plan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3

      - name: Terraform Init
        run: terraform init
        working-directory: infrastructure/environments/production

      - name: Terraform Plan
        run: terraform plan -out=tfplan
        working-directory: infrastructure/environments/production

      - name: Comment PR with plan
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            const plan = require('fs').readFileSync('infrastructure/environments/production/tfplan.txt', 'utf8');
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## Terraform Plan\n\`\`\`\n${plan}\n\`\`\``
            });

  apply:
    needs: plan
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3

      - name: Terraform Apply
        run: terraform apply -auto-approve
        working-directory: infrastructure/environments/production

Multi-Environment-Strategie

UmweltZweckInstanzgrößenKostenziel
EntwicklungFunktionstestst3.micro / t3.small<100 $/Monat
InszenierungValidierung vor der ProduktionSpiegelproduktion (kleiner)~30 % der Produktion
ProduktionLive-VerkehrRichtige Größe für die LadungOptimiert

Verwenden Sie Terraform-Arbeitsbereiche oder separate Verzeichnisse pro Umgebung:

infrastructure/
  modules/
    web-app/
    database/
    network/
  environments/
    development/
      main.tf
      terraform.tfvars
    staging/
      main.tf
      terraform.tfvars
    production/
      main.tf
      terraform.tfvars

Häufig gestellte Fragen

Terraform oder Pulumi – was sollen wir wählen?

Terraform, wenn zu Ihrem Team Betriebsingenieure gehören, die eine deklarative Konfiguration bevorzugen. Pulumi, wenn Ihr Team entwicklerlastig ist und die Infrastruktur lieber in TypeScript oder Python schreibt. Terraform verfügt über ein größeres Ökosystem und mehr Community-Module. Pulumi hat eine steilere anfängliche Lernkurve, ist aber flexibler für komplexe Logik.

Wie importieren wir vorhandene Infrastruktur in Terraform?

Verwenden Sie terraform import, um vorhandene Ressourcen unter Terraform-Verwaltung zu bringen. Zum Beispiel: terraform import aws_instance.app i-1234567890abcdef0. Schreiben Sie nach dem Import die passende Konfiguration. Terraform 1.5+ unterstützt Importblöcke in Konfigurationsdateien für Massenimporte.

Wie gehen wir mit Geheimnissen in Terraform um?

Geben Sie niemals Geheimnisse an Terraform-Dateien weiter. Use terraform.tfvars (excluded from Git), environment variables (TF_VAR_db_password), or a secrets manager (AWS Secrets Manager, HashiCorp Vault). Markieren Sie sensible Variablen mit sensitive = true, um zu verhindern, dass sie in der Planausgabe erscheinen.

Wie hoch sind die Kosten für die Verwaltung von Terraform?

Terraform selbst ist kostenlos und Open Source. Terraform Cloud verfügt über ein kostenloses Kontingent für bis zu 5 Benutzer mit Remote-Status und Plan/Antrag. Die Hauptkosten sind die Lernkurve (20–40 Stunden für einen erfahrenen Ingenieur) und die laufende Wartung (2–4 Stunden pro Monat). Dies wird durch die Zeitersparnis bei der manuellen Infrastrukturverwaltung ausgeglichen.


Was als nächstes kommt

Terraform bietet die Grundlage für eine automatisierte Infrastruktur. Kombinieren Sie es mit CI/CD-Pipelines für die automatisierte Bereitstellung, Überwachung für betriebliche Transparenz und Notfallwiederherstellung für Ausfallsicherheit.

Kontaktieren Sie ECOSIRE für Beratung zur Infrastrukturautomatisierung oder erkunden Sie unseren DevOps-Leitfaden für kleine Unternehmen für die vollständige Roadmap.


Herausgegeben von ECOSIRE – Unterstützung von Unternehmen bei der Automatisierung der Cloud-Infrastruktur.

E

Geschrieben von

ECOSIRE Research and Development Team

Entwicklung von Enterprise-Digitalprodukten bei ECOSIRE. Einblicke in Odoo-Integrationen, E-Commerce-Automatisierung und KI-gestützte Geschäftslösungen.

Chatten Sie auf WhatsApp