#infrastructure #Cloud ## 1. Was ist Terraform? Terraform ist ein Open-Source-Tool (ursprünglich MIT, seit 2023 Business Source License, BSL) von HashiCorp zur **deklarativen** Beschreibung und Verwaltung von Infrastruktur als Code (Infrastructure as Code, IaC). Mit Terraform kannst du: - Infrastruktur in Cloud-Providern (AWS, Azure, GCP, …), On-Premise und weiteren Systemen **beschreiben** (als Code). - Aus dieser Beschreibung eine **gewünschte Zielkonfiguration** (Desired State) definieren. - Terraform berechnet dann, **welche Änderungen nötig sind**, um vom Ist-Zustand zum Soll-Zustand zu gelangen. - Diese Änderungen werden mit `terraform apply` **automatisch ausgeführt**. Terraform ist besonders stark in: - **Multi-Cloud- und Hybrid-Szenarien** - **Reproduzierbaren Umgebungen** (z.B. Dev, Test, Prod) - **Versionierbarer Infrastruktur** (Git) - **Team-Kollaboration** an Infrastruktur --- ## 2. Grundkonzepte von Terraform Die wichtigsten Bausteine: ### 2.1 Provider Provider sind die „Treiber“, mit denen Terraform mit einem externen System spricht, z.B.: - `aws` – Amazon Web Services - `azurerm` – Microsoft Azure - `google` – Google Cloud - `kubernetes` – Kubernetes-Cluster - `helm`, `docker`, `vault`, `github`, viele weitere In Terraform-Code bindet man einen Provider ein, z.B.: ```hcl terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } } provider "aws" { region = "eu-central-1" } ``` ### 2.2 Ressourcen **Ressourcen** (`resource`) sind die eigentlichen Infrastruktur-Objekte, z.B.: - `aws_instance` (EC2-VM) - `aws_s3_bucket` - `azurerm_resource_group` - `google_compute_instance` Beispiel: ```hcl resource "aws_s3_bucket" "example" { bucket = "mein-terraform-bucket-12345" acl = "private" } ``` `aws_s3_bucket` ist der Ressourcentyp, `"example"` der Name innerhalb der Terraform-Konfiguration. ### 2.3 Datenquellen (Data Sources) `data`-Blöcke lesen Informationen aus einer bestehenden Umgebung, ohne etwas zu verändern. ```hcl data "aws_ami" "ubuntu" { most_recent = true filter { name = "name" values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] } owners = ["099720109477"] # Canonical } ``` Die Daten können dann in Ressourcen verwendet werden. ### 2.4 Variablen und Outputs **Variablen** (`variable`) erlauben Parametrisierung: ```hcl variable "region" { type = string default = "eu-central-1" description = "AWS Region" } ``` Aufgerufen z.B.: `var.region`. **Outputs** (`output`) geben wichtige Informationen aus (z.B. IP-Adressen): ```hcl output "instance_ip" { value = aws_instance.web.public_ip } ``` ### 2.5 Module Module sind wiederverwendbare Bausteine von Terraform-Konfigurationen (eine Art „Bibliothek“ von Infrastruktur). - Ein Modul ist einfach ein Ordner mit `.tf`-Dateien. - Man kann eigene Module oder Community-Module nutzen (z.B. aus dem Terraform Registry). Beispiel Nutzung eines Moduls: ```hcl module "network" { source = "./modules/network" vpc_cidr = "10.0.0.0/16" } ``` Oder: ```hcl module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "5.0.0" name = "main-vpc" cidr = "10.0.0.0/16" azs = ["eu-central-1a", "eu-central-1b"] } ``` ### 2.6 Terraform State Terraform hält den Zustand der verwalteten Ressourcen in einer **State-Datei** (`terraform.tfstate`) fest. - Der State ist die „Wahrheit“, mit der Terraform den Ist-Zustand kennt. - Daran erkennt Terraform, welche Ressource es schon erstellt hat und wie deren IDs, Attribute usw. sind. - Änderungen am Code werden mit dem State abgeglichen → Terraform generiert einen Plan. State kann liegen: - lokal: `terraform.tfstate` im Projektordner - remote (empfohlen für Teams): z.B. in S3, Azure Storage, GCS, Terraform Cloud, etc. Beispiel Backend-Konfiguration (Remote State mit S3): ```hcl terraform { backend "s3" { bucket = "my-terraform-state-bucket" key = "prod/terraform.tfstate" region = "eu-central-1" } } ``` --- ## 3. Typischer Terraform-Workflow ### 3.1 Projektstruktur Beispiel: ```text . ├── main.tf # Ressourcen, Module ├── variables.tf # Variablen ├── outputs.tf # Outputs └── providers.tf # Provider / Backend ``` ### 3.2 Wichtige Terraform-Kommandos 1. `terraform init` - Initialisiert das Projekt - Lädt Provider-Plugins - Konfiguriert Backend (State) 2. `terraform plan` - Zeigt, was Terraform ändern würde (Create/Update/Delete) - Verändert noch nichts - Wichtig für Review (z.B. im CI) 3. `terraform apply` - Führt den Plan aus (Standard: vorher Anzeige + Bestätigung) - Erzeugt/aktualisiert/löscht Ressourcen 4. `terraform destroy` - Löscht alle Ressourcen, die Terraform verwaltet - Vorsicht: de facto „Infrastruktur-Abbau“ Typischer Ablauf: ```bash terraform init terraform plan terraform apply ``` --- ## 4. Terraform-Sprache: HCL (HashiCorp Configuration Language) Terraform benutzt HCL, eine deklarative, blockbasierte Sprache. ### 4.1 Syntax-Grundlagen Blöcke haben Form: ```hcl resource "TYP" "NAME" { argument = "value" block { nested_arg = 123 } } ``` Datentypen: - `string` – `"Text"` - `number` – `42` - `bool` – `true` / `false` - Listen – `["a", "b"]` - Maps – `{ key = "value" }` - Objekte/Tuples – komplexere Typen ### 4.2 Expressions & Referenzen Referenzen auf andere Ressourcen: ```hcl resource "aws_instance" "web" { ami = data.aws_ami.ubuntu.id instance_type = var.instance_type tags = { Name = "web-${var.environment}" } } ``` Referenz-Regel: - `ressourcentyp.name.attribut` - z.B. `aws_instance.web.public_ip` --- ## 5. Praktisches Beispiel Ein minimaler Stack in AWS: ### `providers.tf` ```hcl terraform { required_version = ">= 1.6.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } } provider "aws" { region = var.region } ``` ### `variables.tf` ```hcl variable "region" { type = string default = "eu-central-1" description = "AWS Region" } variable "instance_type" { type = string default = "t3.micro" } variable "environment" { type = string default = "dev" } ``` ### `main.tf` ```hcl data "aws_ami" "ubuntu" { most_recent = true filter { name = "name" values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] } owners = ["099720109477"] } resource "aws_instance" "web" { ami = data.aws_ami.ubuntu.id instance_type = var.instance_type tags = { Name = "web-${var.environment}" Environment = var.environment } } ``` ### `outputs.tf` ```hcl output "web_instance_id" { value = aws_instance.web.id } output "web_instance_ami" { value = aws_instance.web.ami } ``` Ablauf: ```bash terraform init terraform plan terraform apply ``` --- ## 6. Workspaces, Environments und Modularisierung ### 6.1 Workspaces Terraform Workspaces ermöglichen getrennte States innerhalb desselben Codes (z.B. `default`, `dev`, `prod`). ```bash terraform workspace list terraform workspace new dev terraform workspace select dev ``` Dann z.B.: ```hcl variable "environment" { default = terraform.workspace } ``` Viele Teams gehen aber eher über **separate State-Dateien / Ordner / Repos** (z.B. `envs/dev`, `envs/prod`), statt Workspaces intensiv zu nutzen. ### 6.2 Module für Wiederverwendung Struktur-Beispiel: ```text . ├── main.tf ├── modules │ ├── network │ │ ├── main.tf │ │ ├── variables.tf │ │ └── outputs.tf │ └── compute │ ├── main.tf │ ├── variables.tf │ └── outputs.tf ``` In `main.tf`: ```hcl module "network" { source = "./modules/network" vpc_cidr = "10.0.0.0/16" } module "compute" { source = "./modules/compute" vpc_id = module.network.vpc_id subnets = module.network.subnet_ids } ``` --- ## 7. Terraform Cloud / Terraform Enterprise Neben der CLI gibt es: - **Terraform Cloud** (SaaS von HashiCorp) - **Terraform Enterprise** (Self-hosted) Features: - Remote-State-Storage - Remote-Execution (Plans/Applies) - Policies (Sentinel) - Team & Governance (RBAC) - UI für Runs, Logs, States, Variablen Für kleine Teams reicht oft: Git + Remote State (S3/Azure/GCS) + CI/CD Pipeline. --- ## 8. Typische Anwendungsfälle - **Cloud-Infrastruktur**: - VPCs/Netzwerke, Subnets, Security Groups - Compute (VMs, Managed Kubernetes, Serverless) - Datenbanken, Caches, Messaging - **Kubernetes-Infrastruktur**: - Cluster (EKS/AKS/GKE) - Add-ons via `kubernetes`-Provider, `helm`-Provider - **Multi-Cloud-Szenarien**: - Einheitliches Tool für AWS + Azure + GCP - **On-Prem / Sonstiges**: - VMware, OpenStack, F5, GitHub-Repos, DNS (Cloudflare/Route53), Monitoring (Datadog, New Relic), etc. --- ## 9. Vergleich zu anderen Tools ### Terraform vs. CloudFormation / ARM / Bicep - Terraform: - Provider-übergreifend (nicht auf eine Cloud beschränkt) - HCL, verständliche Syntax - CloudFormation (AWS) / ARM/Bicep (Azure) / Deployment Manager (GCP): - Cloud-spezifisch, tief integriert - Gut für reines Single-Cloud-Setup - Multi-Cloud wird komplex ### Terraform vs. Ansible / Chef / Puppet - Terraform: - Fokus: **Provisioning** + Lebenszyklus von Ressourcen - Deklarativ, fokus auf Infrastruktur - Ansible/Chef/Puppet: - Fokus: **Konfiguration** von Servern / Software - IdR. auf bereits existierende Maschinen Häufig werden Terraform + Ansible kombiniert: Terraform baut VMs / Netzwerke, Ansible konfiguriert Software im OS. ### Terraform vs. Pulumi - Pulumi: IaC mit **allgemeinen Programmiersprachen** (TypeScript, Python, Go, C#) - Terraform: HCL, deklarativ, stark verbreitete Community - Pulumi bietet mehr „Programmier-Features“ (Loops, Ifs) direkt in Sprache; Terraform hat ähnliche Mechanismen, aber bewusst begrenzt, um die Konfiguration simpel zu halten. --- ## 10. Best Practices & Stolperfallen ### 10.1 Best Practices - **State nicht lokal** speichern, sondern Remote (z.B. S3 + DynamoDB Locking, Azure Storage + Locks). - **State schützen**: - Zugriff beschränken (IAM/RBAC) - Backups - **Struktur / Modularisierung**: - Wiederverwendbare Module - Trennung von Environments (dev/stage/prod) - **Git-Workflow**: - Terraform-Code in Repos - PRs/Merge-Requests - `terraform plan` via CI im PR anzeigen - **Versionen pinnen**: - Terraform-Version `required_version` - Provider-Versionen fixieren (z.B. `~> 5.0`) - **Kleine, inkrementelle Änderungen**: - Große Umbauten in mehreren Schritten - Plan gut reviewen ### 10.2 Typische Probleme - **State-Drift**: - Ressourcen werden außerhalb von Terraform geändert (z.B. in der Cloud-Konsole) - Plan zeigt unerwartete Änderungen - Lösung: soweit möglich alle Änderungen via Terraform; bei Drift bewusst entscheiden (import, adopt, ignore) - **Manuelles Löschen von Ressourcen**: - Terraform „denkt“, Ressource existiert noch - Beim nächsten Apply werden sie ggf. neu erstellt - **Zyklen in Abhängigkeiten**: - Falsche Referenzen können zyklische Abhängigkeiten erzeugen - **Große States**: - Sehr viele Ressourcen in einem State → langsamere Plans, unübersichtliche Fehler - Lösung: Aufteilen in mehrere Terraform-Projekte / States (z.B. pro Domäne/Layer) --- ## 11. Aktuelle Entwicklungen: Lizenz & OpenTofu HashiCorp hat 2023 die Lizenz von Terraform auf die **Business Source License (BSL)** geändert. Daraufhin entstand ein **Community-Fork**: - **OpenTofu** (ehemals OpenTF): - Komplett Open Source (MPL 2.0) - CLI & HCL weitgehend kompatibel zu Terraform (Stand heute) - Ziel: drop-in Replacement für viele Terraform-Usecases Für einen Einstieg in IaC ist es aber sinnvoll, zuerst die Konzepte anhand von Terraform zu verstehen – die meisten davon sind für OpenTofu nahezu identisch. ---