Usamos cookies para mejorar tu experiencia en el sitio
CodeWorlds

Infrastructure as Code z Terraform — Plany Architektoniczne Imperium

Imperium Rzymskie słynęło z planów architektonicznych — każdy akwedukt, droga i fortyfikacja była najpierw zaprojektowana na papierze, zanim rozpoczęto budowę. Dzięki temu mogły być odtwarzane w różnych prowincjach z identycznym rezultatem. W DevOps, tę samą filozofię realizuje Infrastructure as Code (IaC) — definiowanie infrastruktury w plikach konfiguracyjnych zamiast ręcznego klikania w panelach administracyjnych.

Czym jest Infrastructure as Code?

IaC to podejście, w którym infrastruktura (serwery, bazy danych, sieci) jest definiowana w kodzie — wersjonowanym, testowalnym i powtarzalnym:

1// Ręczne zarządzanie vs IaC
2const comparison = {
3  reczne: {
4    metoda: 'Klikanie w AWS Console / Heroku Dashboard',
5    problemy: [
6      'Brak powtarzalności — każde środowisko inne',
7      'Brak historii zmian — kto co zmienił?',
8      'Brak code review — nikt nie weryfikuje zmian',
9      'Trudne do odtworzenia po awarii',
10    ],
11  },
12  iac: {
13    metoda: 'Terraform / Pulumi / CloudFormation',
14    korzysci: [
15      'Powtarzalność — identyczne środowiska',
16      'Git history — pełna historia zmian',
17      'Code review — zespół weryfikuje infrastrukturę',
18      'Disaster recovery — odtworzenie w minuty',
19    ],
20  },
21};

Terraform — Podstawy

Terraform (HashiCorp) to najpopularniejsze narzędzie IaC. Używa deklaratywnego języka HCL (HashiCorp Configuration Language):

1# Instalacja Terraform
2brew install terraform
3
4# Inicjalizacja projektu
5terraform init
6
7# Podgląd zmian
8terraform plan
9
10# Zastosowanie zmian
11terraform apply
12
13# Usunięcie infrastruktury
14terraform destroy

Cykl życia Terraform

1// Cykl pracy z Terraform
2const terraformWorkflow = {
3  krok1_init: 'terraform init — pobierz providery i moduły',
4  krok2_plan: 'terraform plan — pokaż co się zmieni (DRY RUN)',
5  krok3_apply: 'terraform apply — zastosuj zmiany na infrastrukturze',
6  krok4_destroy: 'terraform destroy — usuń całą infrastrukturę',
7};
8
9// Plan to jak "blueprint" — widzisz zmiany ZANIM je zastosujesz
10// Apply to jak "budowa" — Terraform tworzy zasoby w chmurze

Provider — Dostawca usług

Provider to wtyczka łącząca Terraform z dostawcą chmury:

1# main.tf — Konfiguracja providera
2terraform {
3  required_providers {
4    aws = {
5      source  = "hashicorp/aws"
6      version = "~> 5.0"
7    }
8  }
9
10  # Backend — gdzie przechowywać stan
11  backend "s3" {
12    bucket = "roman-imperium-terraform-state"
13    key    = "production/terraform.tfstate"
14    region = "eu-central-1"
15  }
16}
17
18provider "aws" {
19  region = var.aws_region
20
21  default_tags {
22    tags = {
23      Project     = "roman-imperium"
24      Environment = var.environment
25      ManagedBy   = "terraform"
26    }
27  }
28}

Variables — Zmienne Terraform

1# variables.tf — Definicje zmiennych
2variable "aws_region" {
3  description = "Region AWS"
4  type        = string
5  default     = "eu-central-1"
6}
7
8variable "environment" {
9  description = "Srodowisko (dev, staging, production)"
10  type        = string
11}
12
13variable "app_name" {
14  description = "Nazwa aplikacji"
15  type        = string
16  default     = "roman-imperium-api"
17}
18
19variable "db_instance_class" {
20  description = "Klasa instancji bazy danych"
21  type        = string
22  default     = "db.t3.micro"
23}
24
25variable "app_port" {
26  description = "Port aplikacji NestJS"
27  type        = number
28  default     = 4000
29}

Resources — Tworzenie infrastruktury

Serwer dla NestJS (EC2)

1# compute.tf — Serwer aplikacji
2resource "aws_instance" "api_server" {
3  ami           = "ami-0c55b159cbfafe1f0"  # Amazon Linux 2
4  instance_type = "t3.small"
5
6  vpc_security_group_ids = [aws_security_group.api_sg.id]
7  subnet_id              = aws_subnet.public.id
8
9  user_data = <<-EOF
10    #!/bin/bash
11    yum update -y
12    yum install -y docker
13    systemctl start docker
14    docker pull ${var.app_name}:latest
15    docker run -d -p ${var.app_port}:${var.app_port} ${var.app_name}:latest
16  EOF
17
18  tags = {
19    Name = "${var.app_name}-server"
20  }
21}
22
23resource "aws_security_group" "api_sg" {
24  name        = "${var.app_name}-sg"
25  description = "Security group dla API NestJS"
26  vpc_id      = aws_vpc.main.id
27
28  ingress {
29    from_port   = var.app_port
30    to_port     = var.app_port
31    protocol    = "tcp"
32    cidr_blocks = ["0.0.0.0/0"]
33  }
34
35  ingress {
36    from_port   = 443
37    to_port     = 443
38    protocol    = "tcp"
39    cidr_blocks = ["0.0.0.0/0"]
40  }
41
42  egress {
43    from_port   = 0
44    to_port     = 0
45    protocol    = "-1"
46    cidr_blocks = ["0.0.0.0/0"]
47  }
48}

Baza danych MongoDB (DocumentDB)

1# database.tf — Baza danych
2resource "aws_docdb_cluster" "mongodb" {
3  cluster_identifier  = "${var.app_name}-db"
4  engine              = "docdb"
5  master_username     = "imperator"
6  master_password     = var.db_password
7  skip_final_snapshot = var.environment != "production"
8
9  vpc_security_group_ids = [aws_security_group.db_sg.id]
10  db_subnet_group_name   = aws_docdb_subnet_group.db.name
11}
12
13resource "aws_docdb_cluster_instance" "mongodb_instance" {
14  count              = var.environment == "production" ? 2 : 1
15  identifier         = "${var.app_name}-db-${count.index}"
16  cluster_identifier = aws_docdb_cluster.mongodb.id
17  instance_class     = var.db_instance_class
18}

State Management — Zarządzanie stanem

Terraform przechowuje stan (state) — mapowanie między konfiguracją a rzeczywistą infrastrukturą:

1// Stan Terraform
2const terraformState = {
3  localState: {
4    plik: 'terraform.tfstate',
5    problemy: ['Nie współdzielony', 'Brak blokady', 'Ryzyko utraty'],
6  },
7  remoteState: {
8    backend: 'S3, Azure Blob, GCS, Terraform Cloud',
9    korzysci: ['Współdzielony', 'Blokada (locking)', 'Wersjonowanie'],
10  },
11};
12
13// NIGDY nie commituj terraform.tfstate do repozytorium!
14// Zawiera wrażliwe dane (hasła, klucze)

Modules — Reużywalne komponenty

Moduły to reużywalne bloki infrastruktury — jak prefabrykowane elementy rzymskich budowli:

1# modules/nestjs-app/main.tf
2module "nestjs_app" {
3  source = "./modules/nestjs-app"
4
5  app_name        = "roman-imperium-api"
6  environment     = "production"
7  instance_type   = "t3.small"
8  app_port        = 4000
9  db_instance_class = "db.t3.medium"
10}
11
12# Moduł można użyć wielokrotnie
13module "staging_app" {
14  source = "./modules/nestjs-app"
15
16  app_name        = "roman-imperium-api"
17  environment     = "staging"
18  instance_type   = "t3.micro"
19  app_port        = 4000
20  db_instance_class = "db.t3.micro"
21}

Outputs — Wyniki

1# outputs.tf
2output "api_server_ip" {
3  description = "Adres IP serwera API"
4  value       = aws_instance.api_server.public_ip
5}
6
7output "database_endpoint" {
8  description = "Endpoint bazy danych"
9  value       = aws_docdb_cluster.mongodb.endpoint
10  sensitive   = true
11}
12
13output "app_url" {
14  description = "URL aplikacji"
15  value       = "http://${aws_instance.api_server.public_ip}:${var.app_port}"
16}

Praktyczny workflow

1# 1. Inicjalizacja projektu
2terraform init
3
4# 2. Sprawdź formatowanie
5terraform fmt
6
7# 3. Waliduj konfigurację
8terraform validate
9
10# 4. Podgląd zmian (DRY RUN)
11terraform plan -out=tfplan
12
13# 5. Zastosuj zmiany
14terraform apply tfplan
15
16# 6. Sprawdź wyniki
17terraform output

Terraform to plany architektoniczne naszego Imperium — definiujemy infrastrukturę w kodzie, wersjonujemy ją w Git, przeglądamy w code review i stosujemy automatycznie. Dzięki IaC możemy odtworzyć całe środowisko w minuty, nie w dni.

Ir a CodeWorlds