Klikanie w AWS Console jest świetne na początek, ale gdy tworzysz aplikację AI z prawdziwego zdarzenia, potrzebujesz powtarzalności. Terraform to narzędzie Infrastructure as Code (IaC), które zamienia ręczne konfiguracje w kod — wersjonowany, recenzowany i wdrażany jednym poleceniem.
🎯 Czego się nauczysz:
- Podstaw Terraform i HCL (HashiCorp Configuration Language)
- Konfigurację providera AWS na Windowsie
- Zarządzanie wieloma środowiskami przez Workspaces
- Automatyzację deploymentu skryptami PowerShell
- Izolację stanu (state) per środowisko
- Dobre praktyki nazewnictwa i tagowania zasobów
TL;DR — Szybkie podsumowanie
| Aspekt | Manual (Console) | Terraform |
|---|---|---|
| Powtarzalność | ❌ Ręczna konfiguracja | ✅ Kod = dokumentacja |
| Wersjonowanie | ❌ Brak historii | ✅ Git tracking |
| Środowiska | ❌ Ręczna izolacja | ✅ Workspaces (dev/test/prod) |
| Rollback | ❌ Trudny | ✅ terraform destroy |
| Czas deploymentu | ~30 minut | ~5 minut (po konfiguracji) |
🤔 Dlaczego Terraform dla aplikacji AI?
Gdy budujesz cyfrowego bliźniaka (Digital Twin) — chatbota wykorzystującego modele Bedrock — infrastruktura składa się z wielu moving parts:
- Lambda — backend Pythonowy obsługujący API
- API Gateway — endpointy HTTP dla frontendu
- S3 — bucket na frontend (static hosting) i pamięć konwersacji
- CloudFront — CDN dla frontendu
- IAM — uprawnienia do Bedrock i S3
Ręczne klikanie w konsoli przy trzech środowiskach (dev/test/prod) to prosta droga do błędów. Terraform pozwala zdefiniować to raz i deployować wielokrotnie.
🛠️ Przygotowanie środowiska Windows
Instalacja Terraform
Na Windows najwygodniej użyć winget lub pobrać binarkę:
# Instalacja przez winget (Windows 10/11)
winget install Hashicorp.Terraform
# Weryfikacja
terraform --version
# Terraform v1.10.0 on windows_amd64
C:\tools\terraform i dodaj do PATH.
Struktura projektu
⚙️ Konfiguracja Terraform
1. Provider i wersje (versions.tf)
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
provider "aws" {
region = "us-east-1" # Bedrock najlepiej działa tu
}
# Drugi provider dla certyfikatów (musi być w us-east-1)
provider "aws" {
alias = "us_east_1"
region = "us-east-1"
}
2. Zmienne (variables.tf)
Parametryzacja to klucz do wielu środowisk:
variable "project_name" {
description = "Prefiks dla wszystkich zasobów"
type = string
default = "twin"
validation {
condition = can(regex("^[a-z0-9-]+$", var.project_name))
error_message = "Tylko małe litery, cyfry i myślniki."
}
}
variable "environment" {
description = "Środowisko: dev, test, prod"
type = string
validation {
condition = contains(["dev", "test", "prod"], var.environment)
error_message = "Dozwolone wartości: dev, test, prod."
}
}
variable "bedrock_model_id" {
description = "ID modelu AWS Bedrock"
type = string
default = "amazon.nova-micro-v1:0" # Tani model dla dev
}
3. Główna konfiguracja (main.tf)
locals {
name_prefix = "${var.project_name}-${var.environment}"
common_tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "terraform"
}
}
# S3 dla pamięci konwersacji (prywatny)
resource "aws_s3_bucket" "memory" {
bucket = "${local.name_prefix}-memory-${data.aws_caller_identity.current.account_id}"
tags = local.common_tags
}
# Lambda function
resource "aws_lambda_function" "api" {
filename = "${path.module}/../backend/lambda-deployment.zip"
function_name = "${local.name_prefix}-api"
role = aws_iam_role.lambda_role.arn
handler = "lambda_handler.handler"
runtime = "python3.12"
timeout = var.lambda_timeout
environment {
variables = {
S3_BUCKET = aws_s3_bucket.memory.id
BEDROCK_MODEL_ID = var.bedrock_model_id
}
}
}
4. Wyjścia (outputs.tf)
output "api_gateway_url" {
description = "URL API Gateway"
value = aws_apigatewayv2_api.main.api_endpoint
}
output "cloudfront_url" {
description = "URL CloudFront"
value = "https://${aws_cloudfront_distribution.main.domain_name}"
}
🗂️ Workspaces — klucz do izolacji środowisk
Terraform Workspaces pozwalają utrzymać osobny stan (state) dla każdego środowiska bez duplikowania kodu.
Ręczne wpisywanie komend jest podatne na błędy. Stwórzmy scripts/deploy.ps1:
param(
[string]$Environment = "dev", # dev | test | prod
[string]$ProjectName = "twin"
)
$ErrorActionPreference = "Stop"
Write-Host "🚀 Deploying $ProjectName to $Environment..." -ForegroundColor Green
# 1. Budowanie pakietu Lambda
Set-Location (Split-Path $PSScriptRoot -Parent)
Write-Host "📦 Building Lambda package..." -ForegroundColor Yellow
Set-Location backend
uv run deploy.py # Tworzy lambda-deployment.zip
Set-Location ..
# 2. Terraform - inicjalizacja i apply
Set-Location terraform
terraform init -input=false
# Sprawdź czy workspace istnieje
if (-not (terraform workspace list | Select-String $Environment)) {
terraform workspace new $Environment
} else {
terraform workspace select $Environment
}
# Apply z auto-approve
terraform apply -var="project_name=$ProjectName" -var="environment=$Environment" -auto-approve
# Pobierz outputy
$ApiUrl = terraform output -raw api_gateway_url
$FrontendBucket = terraform output -raw s3_frontend_bucket
Set-Location ..\frontend
# 3. Budowanie frontendu
Write-Host "📝 Building frontend..." -ForegroundColor Yellow
"NEXT_PUBLIC_API_URL=$ApiUrl" | Out-File .env.production -Encoding utf8
npm install
npm run build
# 4. Deploy do S3
aws s3 sync .\out "s3://$FrontendBucket/" --delete
Write-Host "`n✅ Deployment complete!" -ForegroundColor Green
.\scripts\deploy.ps1 -Environment dev lub .\scripts\deploy.ps1 -Environment prod
⚡ Konfiguracja per środowisko
Utwórz terraform/prod.tfvars dla produkcji:
project_name = "twin"
environment = "prod"
bedrock_model_id = "amazon.nova-lite-v1:0" # Lepszy model
lambda_timeout = 60
api_throttle_burst_limit = 20
use_custom_domain = true
root_domain = "twojadomena.pl"
Dla dev wystarczy terraform.tfvars:
project_name = "twin"
environment = "dev"
bedrock_model_id = "amazon.nova-micro-v1:0" # Tańszy
use_custom_domain = false
🧹 Czyszczenie zasobów (destroy)
Aby uniknąć kosztów za zapomniane zasoby, stwórz scripts/destroy.ps1:
param(
[Parameter(Mandatory=$true)]
[string]$Environment,
[string]$ProjectName = "twin"
)
Write-Host "🗑️ Destroying $ProjectName-$Environment..." -ForegroundColor Red
Set-Location (Join-Path (Split-Path $PSScriptRoot -Parent) "terraform")
# Pobierz nazwy bucketów przed destroy
$AccountId = aws sts get-caller-identity --query Account --output text
$FrontendBucket = "$ProjectName-$Environment-frontend-$AccountId"
$MemoryBucket = "$ProjectName-$Environment-memory-$AccountId"
# Opróżnij S3 (Terraform nie usunie niepustych bucketów)
aws s3 rm "s3://$FrontendBucket" --recursive 2>$null
aws s3 rm "s3://$MemoryBucket" --recursive 2>$null
# Destroy
terraform workspace select $Environment
terraform destroy -auto-approve
Write-Host "✅ Environment $Environment destroyed" -ForegroundColor Green
✨ Dobre praktyki
| Praktyka | Implementacja |
|---|---|
| Taguj wszystko | Dzięki local.common_tags masz pełną widoczność kosztów per środowisko w AWS Cost Explorer |
| Nazewnictwo z prefixem | Używaj ${local.name_prefix} (np. twin-dev-api) aby uniknąć konfliktów nazw |
| State backend | Dla zespołów przenieś stan do S3 zamiast trzymać lokalnie |
| .gitignore |
*.tfstate.terraform/*.tfvars (oprócz przykładów)
|
🐛 Troubleshooting Windows
terraform nie jest rozpoznawane jako polecenieRozwiązanie: Dodaj ścieżkę do Terraform do zmiennych środowiskowych PATH (System Properties → Environment Variables).
Rozwiązanie: W HCL używaj forward slashes (
/) lub podwójnych backslashów (\\).
Rozwiązanie: Uruchom PowerShell jako Administrator i wykonaj:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
📋 Podsumowanie komend
| Akcja | Komenda PowerShell |
|---|---|
| Inicjalizacja | terraform init |
| Nowy workspace | terraform workspace new dev |
| Deploy | terraform apply -auto-approve |
| Podgląd zmian | terraform plan |
| Destroy | terraform destroy -auto-approve |
| Outputy | terraform output |
| Formatowanie | terraform fmt |
🎯 Kiedy używać Terraform?
✅ Użyj Terraform gdy:
- Masz więcej niż jedno środowisko (dev/prod)
- Zespół współdzieli infrastrukturę
- Potrzebujesz audytowalności zmian (Git history)
- Chcesz szybkiego rollbacku (
terraform destroy) - Automatyzujesz przez CI/CD (GitHub Actions)
❌ Nie potrzebujesz Terraform gdy:
- Szybki prototyp na jeden wieczór
- Jeden developer, jedno środowisko
- Uczysz się AWS i chcesz zrozumieć usługi (najpierw Console, potem IaC)
📚 Bibliografia
- HashiCorp. (2025). Terraform Documentation. terraform.io/docs
- AWS. (2025). AWS Provider for Terraform. registry.terraform.io/providers/hashicorp/aws
- AWS. (2025). AWS Lambda Developer Guide. docs.aws.amazon.com/lambda
- Terraform Best Practices. (2025). terraform-best-practices.com
- PowerShell Documentation. (2025). Microsoft Learn. learn.microsoft.com/powershell
.\scripts\deploy.ps1 -Environment prod.