Terraform Infrastructure As Code
Terraform: Infrastructure as Code
Terraform ermöglicht das Verwalten von Cloud-Infrastruktur als Code. Lernen Sie die Grundlagen von HashiCorp Terraform.
Was ist Terraform?
# Statt manuell in AWS Console:
# → Klicke hier, fülle das aus, warte...
# Mit Terraform:
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
# Benefits:
# - Versioniert (Git)
# - Wiederholbar
# - Dokumentation der Infrastruktur
# - Einfaches Aufsetzen mehrerer Umgebungen
Installation
# macOS brew install terraform # Ubuntu/Debian wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list sudo apt update && sudo apt install terraform # Version prüfen terraform version
Grundlegende Struktur
project/ ├── main.tf # Hauptkonfiguration ├── variables.tf # Variablen-Definitionen ├── outputs.tf # Output-Werte ├── terraform.tfvars # Variablen-Werte └── providers.tf # Provider-Konfiguration
Erstes Beispiel
# providers.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "eu-central-1"
}
# main.tf
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "WebServer"
Environment = "production"
}
}
# outputs.tf
output "instance_ip" {
value = aws_instance.web.public_ip
}
Terraform Workflow
# 1. Initialisieren (Provider herunterladen) terraform init # 2. Plan anzeigen (was würde passieren?) terraform plan # 3. Änderungen anwenden terraform apply # 4. Ressourcen zerstören terraform destroy # Nur bestimmte Ressource terraform apply -target=aws_instance.web terraform destroy -target=aws_instance.web
Variablen
# variables.tf
variable "environment" {
description = "Deployment environment"
type = string
default = "development"
}
variable "instance_type" {
description = "EC2 instance type"
type = string
default = "t2.micro"
validation {
condition = contains(["t2.micro", "t2.small", "t2.medium"], var.instance_type)
error_message = "Invalid instance type."
}
}
variable "allowed_ports" {
description = "Allowed ports"
type = list(number)
default = [80, 443]
}
variable "tags" {
description = "Resource tags"
type = map(string)
default = {}
}
# terraform.tfvars
environment = "production"
instance_type = "t2.small"
allowed_ports = [80, 443, 8080]
tags = {
Project = "MyApp"
Owner = "team@example.com"
}
# Verwendung
resource "aws_instance" "web" {
instance_type = var.instance_type
tags = var.tags
}
Data Sources
# Existierende Ressourcen abfragen
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
}
data "aws_vpc" "default" {
default = true
}
# Verwendung
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.web.id]
}
State Management
# Remote State (empfohlen für Teams)
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "eu-central-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
# State-Befehle
terraform state list # Ressourcen auflisten
terraform state show aws_instance.web # Details anzeigen
terraform state mv aws_instance.web aws_instance.app # Umbenennen
terraform state rm aws_instance.web # Aus State entfernen
terraform import aws_instance.web i-1234567890 # Importieren
Module
# modules/vpc/main.tf
variable "cidr_block" {}
variable "name" {}
resource "aws_vpc" "main" {
cidr_block = var.cidr_block
tags = {
Name = var.name
}
}
output "vpc_id" {
value = aws_vpc.main.id
}
# main.tf - Modul verwenden
module "vpc" {
source = "./modules/vpc"
cidr_block = "10.0.0.0/16"
name = "production-vpc"
}
# Registry Module verwenden
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.0.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["eu-central-1a", "eu-central-1b"]
}
Praktisches Beispiel
# Vollständiges Beispiel: Web Server mit Security Group
resource "aws_security_group" "web" {
name = "web-sg"
description = "Security group for web servers"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"] # Nur intern
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
vpc_security_group_ids = [aws_security_group.web.id]
user_data = <<-EOF
#!/bin/bash
apt-get update
apt-get install -y nginx
systemctl start nginx
EOF
tags = {
Name = "WebServer"
}
}
💡 Tipp:
Nutzen Sie
terraform plan immer vor apply um unerwartete Änderungen zu vermeiden.