Spis treści 12 sekcji
  1. Czym jest Infrastructure as Code?
  2. Dlaczego IaC jest niezbędny?
  3. Czym jest Terraform?
  4. Podstawy Terraform - kluczowe koncepcje
  5. Trzy kluczowe komendy
  6. Praktyczny przykład - pełna infrastruktura
  7. Moduły - organizacja kodu
  8. Best practices
  9. Terraform vs klikanie w konsoli
  10. Jak zacząć z Terraform?
  11. Najczęściej zadawane pytania (FAQ)
  12. Następny krok
TL;DR
  • Infrastructure as Code (IaC) to zarządzanie infrastrukturą za pomocą plików konfiguracyjnych zamiast ręcznego klikania
  • Terraform od HashiCorp to standard w branży - 8 na 10 ofert pracy Cloud/DevOps wymaga jego znajomości
  • Terraform używa języka HCL (deklaratywnego) i wspiera multi-cloud (AWS, Azure, GCP)
  • Trzy kluczowe komendy: terraform init, terraform plan, terraform apply
  • State (plik stanu) to serce Terraform - w zespole zawsze przechowuj go zdalnie (S3 z natywnym lockingiem; starszy wariant: S3 + DynamoDB)

Czym jest Infrastructure as Code?

Infrastructure as Code (IaC) to zarządzanie infrastrukturą IT za pomocą plików konfiguracyjnych zamiast ręcznego klikania w konsoli. Zamiast logować się do AWS i tworzyć zasoby myszką, opisujesz je w kodzie - a narzędzie automatycznie tworzy, modyfikuje i usuwa zasoby za Ciebie.

Dlaczego to rewolucja? Bo infrastruktura staje się kodem - a kod możesz wersjonować w Git, review'ować w pull requestach, testować automatycznie i wdrażać przez CI/CD. Koniec z "kto zmienił security group w piątek o 23:00 i nie powiedział".

Dlaczego IaC jest niezbędny?

Zanim zacząłem używać Terraform, tworzenie środowisk w AWS zajmowało mi godziny klikania w konsoli. Po przejściu na IaC ten sam proces zajmuje minuty i jest powtarzalny za każdym razem.

  • Powtarzalność - ten sam kod tworzy identyczną infrastrukturę za każdym razem. Dev, staging, produkcja - z tego samego szablonu
  • Wersjonowanie - każda zmiana infrastruktury w historii Git. Kto zmienił, kiedy, dlaczego
  • Code review - zmiana infrastruktury przechodzi przez PR, tak jak zmiana kodu aplikacji
  • Automatyzacja - tworzenie całego środowiska jednym poleceniem. Nowy klient? `terraform apply` i gotowe
  • Dokumentacja - kod Terraform JEST dokumentacją Twojej infrastruktury. Zawsze aktualną
  • Disaster Recovery - stracisz środowisko? `terraform apply` odtworzy je od zera

Czym jest Terraform?

Terraform to narzędzie IaC od HashiCorp - do 2023 open source, obecnie na licencji BUSL (dla użytkowników nadal darmowe; w pełni open-source'owym forkiem jest OpenTofu). To standard w branży - zdecydowana większość ofert pracy Cloud/DevOps w Polsce wymaga znajomości Terraform.

Dlaczego Terraform, a nie alternatywy?

NarzędzieTwórcaMulti-cloudJęzykPopularność
TerraformHashiCorpTak (AWS, Azure, GCP, 1000+ providerów)HCLDominujące
CloudFormationAWSTylko AWSJSON/YAMLPopularne w czystym AWS
PulumiPulumiTakPython, TS, GoRosnące
CDKAWSGłównie AWSPython, TS, JavaRosnące

Terraform wygrywa dzięki multi-cloud (jeden język do AWS, Azure, GCP), ogromnej społeczności i ekosystemowi modułów. Nawet jeśli używasz tylko AWS, Terraform jest lepszym wyborem niż CloudFormation - jest szybszy, ma lepszą składnię i łatwiej się go uczy.

Podstawy Terraform - kluczowe koncepcje

HCL - język Terraform

Terraform używa języka HCL (HashiCorp Configuration Language). Jest deklaratywny - opisujesz CZEGO chcesz, nie JAK to zrobić.

# Definiujesz provider (AWS)
provider "aws" {
  region = "eu-central-1"
}

# Definiujesz zasoby
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0" # przykładowe ID - AMI różnią się między regionami
  instance_type = "t3.micro"

  tags = {
    Name        = "WebServer"
    Environment = "production"
  }
}

Providers

Provider to plugin, który mówi Terraform jak komunikować się z daną platformą. Dla AWS to `hashicorp/aws`:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

Resources

Resource to pojedynczy zasób infrastruktury (instancja EC2, bucket S3, baza RDS). Składnia:

resource "TYPE" "NAME" {
  # konfiguracja
}

# Przykłady:
resource "aws_s3_bucket" "data" {
  bucket = "my-app-data-bucket"
}

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
}

Variables i Outputs

# Zmienne wejściowe
variable "instance_type" {
  description = "Typ instancji EC2"
  type        = string
  default     = "t3.micro"
}

# Użycie zmiennej
resource "aws_instance" "web" {
  instance_type = var.instance_type
}

# Outputy - wyświetlanie wartości
output "instance_ip" {
  value = aws_instance.web.public_ip
}

State - serce Terraform

Terraform przechowuje stan infrastruktury w pliku state (domyślnie `terraform.tfstate`). State mapuje kod Terraform na realne zasoby w AWS. Dzięki temu Terraform wie, co istnieje, co zmienić i co usunąć.

Uwaga: W zespole state MUSI być przechowywany zdalnie (remote state), np. w S3. Lokalny state w zespole to proszenie się o konflikty i utratę infrastruktury. Z mojego doświadczenia - to pierwszy błąd, który popełnia każdy początkujący zespół.
terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "production/terraform.tfstate"
    region         = "eu-central-1"
    use_lockfile   = true  # natywny locking w S3 (Terraform 1.10+)
    encrypt        = true
  }
}

Trzy kluczowe komendy

# 1. Inicjalizacja - pobiera providery i konfiguruje backend
terraform init

# 2. Plan - podgląd zmian (co będzie stworzone/zmienione/usunięte)
terraform plan

# 3. Apply - aplikacja zmian (tworzy/modyfikuje/usuwa zasoby)
terraform apply

# Bonus: Destroy - usunięcie WSZYSTKICH zasobów z kodu
terraform destroy

Workflow: init -> plan -> (review) -> apply. Zawsze rób `plan` przed `apply` i sprawdzaj, co Terraform zamierza zmienić.

Uwaga: Komenda terraform destroy usuwa WSZYSTKIE zasoby zdefiniowane w kodzie. Nigdy nie uruchamiaj jej na produkcji bez potrójnego sprawdzenia. W CI/CD pipeline destroy powinien wymagać dodatkowego zatwierdzenia.

Praktyczny przykład - pełna infrastruktura

Postawmy prostą infrastrukturę: VPC + subnet + EC2 + Security Group:

# main.tf
provider "aws" {
  region = "eu-central-1"
}

# VPC
resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  tags = { Name = "main-vpc" }
}

# Public Subnet
resource "aws_subnet" "public" {
  vpc_id                  = aws_vpc.main.id
  cidr_block              = "10.0.1.0/24"
  availability_zone       = "eu-central-1a"
  map_public_ip_on_launch = true
  tags = { Name = "public-subnet" }
}

# Internet Gateway
resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.main.id
  tags   = { Name = "main-igw" }
}

# Route Table
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw.id
  }
}

resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

# Security Group
resource "aws_security_group" "web" {
  name_prefix = "web-"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["YOUR_IP/32"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# AMI pobierane dynamicznie - ID AMI różnią się między regionami
data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-2023*-x86_64"]
  }
}

# EC2 Instance
resource "aws_instance" "web" {
  ami                    = data.aws_ami.amazon_linux.id
  instance_type          = "t3.micro"
  subnet_id              = aws_subnet.public.id
  vpc_security_group_ids = [aws_security_group.web.id]

  user_data = <<-EOF
    #!/bin/bash
    yum update -y
    yum install -y httpd
    systemctl start httpd
    echo "Hello from Terraform!" > /var/www/html/index.html
  EOF

  tags = { Name = "web-server" }
}

output "web_url" {
  value = "http://${aws_instance.web.public_ip}"
}

Trzy komendy i masz pełną infrastrukturę z VPC, subnetem, security group i serwerem webowym:

terraform init
terraform plan    # sprawdź co zostanie stworzone
terraform apply   # potwierdź "yes"
Koszty: Ten przykład nie jest w 100% darmowy - publiczny adres IPv4 kosztuje ok. 3,6 USD/mies., a t3.micro poza Free Tier ok. 8 USD/mies. Po zakończeniu testów uruchom terraform destroy, żeby nie płacić za zapomniane zasoby.

Moduły - organizacja kodu

Gdy Twoja infrastruktura rośnie, musisz ją zorganizować. Moduły to "paczki" kodu Terraform do reużycia:

# Struktura katalogów
modules/
  vpc/
    main.tf
    variables.tf
    outputs.tf
  ec2/
    main.tf
    variables.tf
    outputs.tf

# Użycie modułu
module "vpc" {
  source = "./modules/vpc"
  cidr   = "10.0.0.0/16"
}

module "web_server" {
  source    = "./modules/ec2"
  subnet_id = module.vpc.public_subnet_id
  instance_type = "t3.micro"
}

Terraform Registry to repozytorium gotowych modułów od społeczności. Nie pisz VPC od zera - użyj modułu `terraform-aws-modules/vpc/aws`.

Best practices

Pro tip: W projektach, które prowadziłem, te zasady oszczędziły nam dziesiątek godzin debugowania i zapobiegły niejednej awarii na produkcji.
  1. Remote state z locking - zawsze S3 z use_lockfile = true (DynamoDB to starsze, deprecated podejście), nigdy lokalny state w zespole
  2. Struktura katalogów per środowisko - oddzielne foldery/workspaces dla dev/staging/prod
  3. Używaj zmiennych - nigdy nie hardkoduj wartości (AMI ID, CIDR, nazwy)
  4. Formatuj kod - `terraform fmt` przed każdym commitem
  5. Waliduj - `terraform validate` w CI/CD pipeline
  6. Plan w CI/CD - automatyczny `terraform plan` na PR, `apply` po merge
  7. Nie edytuj state ręcznie - używaj `terraform state` commands
  8. Taguj zasoby - Environment, Project, ManagedBy=terraform

Terraform vs klikanie w konsoli

AspektKonsola AWSTerraform
Szybkość uczeniaSzybka (GUI)Wolniejsza (musisz znać HCL)
PowtarzalnośćBrak (ręczna praca)Pełna (kod = infrastruktura)
Code reviewNiemożliweTak (PR na zmianę infra)
Disaster recoveryOdtwarzaj ręcznie`terraform apply` i gotowe
ŚrodowiskaKopiuj ręcznieTen sam kod, inne zmienne
DokumentacjaMusisz pisać osobnoKod jest dokumentacją

Konsola jest dobra do nauki i eksploracji. Produkcyjna infrastruktura powinna być w Terraform.

Jak zacząć z Terraform?

  1. Zainstaluj Terraform - `brew tap hashicorp/tap && brew install hashicorp/tap/terraform` (Mac - oficjalny tap; samo `brew install terraform` instaluje przestarzałą wersję 1.5.7), `choco install terraform` (Windows) lub pobierz z terraform.io
  2. Skonfiguruj AWS CLI - `aws configure` z Access Key i Secret Key
  3. Stwórz prosty projekt - zacznij od S3 bucket, potem EC2, potem VPC
  4. Naucz się state - zrozum jak działa, skonfiguruj remote state
  5. Naucz się modułów - używaj gotowych z Registry, pisz własne

Najczęściej zadawane pytania (FAQ)

Czy Terraform jest trudny do nauczenia?

Terraform jest łatwiejszy niż większość narzędzi DevOps. Język HCL jest deklaratywny i czytelny - opisujesz co chcesz, nie jak to zrobić. Podstawy (init, plan, apply, zmienne, moduły) można opanować w 2-3 tygodnie. Najtrudniejsza część to zrozumienie stanu (state) i zarządzanie nim w zespole. Znajomość usług AWS, które automatyzujesz, jest ważniejsza niż sam Terraform.

Terraform vs CloudFormation - co wybrać?

Terraform jest lepszym wyborem w większości przypadków. Obsługuje multi-cloud (AWS, Azure, GCP), ma czytelniejszą składnię HCL, szybciej wdraża zmiany i ma ogromną społeczność z gotowymi modułami. CloudFormation wygrywa tylko w specyficznych scenariuszach - pełna integracja z AWS (StackSets, Service Catalog) i gdy firma wymaga 100% AWS-native rozwiązań. Na rynku pracy Terraform jest zdecydowanie bardziej poszukiwany.

Czy Terraform jest darmowy?

Tak, Terraform CLI jest darmowy w użyciu - licencja BUSL ogranicza tylko firmy budujące konkurencyjne produkty komercyjne. Możesz go pobrać, zainstalować i używać bez żadnych opłat. HashiCorp oferuje też HCP Terraform (dawniej Terraform Cloud) z darmowym planem do 500 zarządzanych zasobów, bez limitu użytkowników, z remote state i interfejsem webowym. Płatne plany (Essentials, Standard, Premium - rozliczane per zarządzany zasób) dodają governance, SSO i zaawansowane zarządzanie statem dla większych zespołów.

Jak bezpiecznie zarządzać state w zespole?

Zawsze używaj remote state z lockingiem. Standardowa konfiguracja to bucket S3 z natywnym lockingiem (use_lockfile = true, od Terraform 1.10); tabela DynamoDB na lock to starsze podejście, obecnie deprecated. Dzięki temu członkowie zespołu nie nadpiszą sobie nawzajem zmian. Nigdy nie edytuj pliku state ręcznie - używaj komend terraform state. Włącz szyfrowanie bucketa S3 i ogranicz dostęp przez IAM policy. Pamiętaj też, że state przechowuje wartości wrażliwe (np. hasła do RDS) czystym tekstem - nigdy nie commituj terraform.tfstate do Git i traktuj dostęp do niego jak dostęp do sekretów.

Następny krok

Terraform wymaga znajomości usług AWS, które automatyzujesz. Jeśli nie znasz jeszcze EC2, VPC i S3, zacznij od naszego kursu AWS od podstaw, a potem wróć do Terraform.

Chcesz zobaczyć Terraform w praktyce z AWS? Sprawdź naszą Akademię CloudManiak, gdzie budujemy kompletne projekty IaC od zera.

Terraform to kluczowa umiejętność na drodze do kariery Cloud Engineera - sprawdź naszą roadmapę Jak zostać Cloud Engineerem. A jeśli interesujesz się kontenerami, przeczytaj Docker dla początkujących.

Emil Kowalczyk

Pasjonat chmury i twórca CloudManiak.pl. Na co dzień MSP Engineer w amerykańskiej firmie ClearScale (AWS Premier Tier Partner). Pomagam osobom wchodzącym do świata chmury zdobywać wiedzę i certyfikaty.