Terraform de la zero: HCL, Furnizor și ciclul Plan-Apply-Destroy
În 2026, piața infrastructurii ca cod a atins o asemenea maturitate încât ignorarea Terraform este echivalentă cu a scrie SQL fără a cunoaște tranzacțiile: posibil din punct de vedere tehnic, dar riscant din punct de vedere profesional. Terraform lui HashiCorp deține astăzi 32,8% cota de piata printre instrumentele IaC, cu peste 4 milioane de instalații lunare ale furnizorului pe registry.terraform.io. Acest ghid te duce de la zero la o configurație de lucru pe AWS și Azure, cu o înțelegere solidă a ciclului Plan-Apply-Destroy ceea ce va evita erorile costisitoare în producție.
Întrebarea pe care o aud cel mai des de la dezvoltatorii care abordează IaC este: „Pentru că nu folosesc doar scripturi bash sau consola AWS?”. Răspunsul este în conceptul de infrastructura declarativă: nu-i spui lui Terraform ca creează resursele, spui tu care stare vrei sa realizezi. Terraform este preocupat de înțelegerea succesiunii operațiunilor, gestionarea dependențelor dintre resurse și asigurarea idempotității.
Ce vei învăța
- Instalați Terraform și configurați tfenv pentru a gestiona mai multe versiuni
- Sintaxa HCL: blocuri, atribute, expresii și funcții încorporate
- Configurați furnizorul AWS și furnizorul Azure cu autentificare securizată
- Ciclul de viață complet:
terraform init,plan,apply,destroy - Înțelegerea fișierului de stat: ce este, unde locuiește, de ce nu ar trebui niciodată modificat manual
- Structurați un proiect Terraform de la început într-un mod scalabil
- Variabile, localuri și ieșire: organizați configurația într-un mod profesionist
Cerințe preliminare și instalare
Înainte de a scrie prima linie a HCL, să configuram mediul profesional. Cea mai frecventă greșeală pentru începători este instalarea Terraform la nivel global cu un manager de pachete și apoi să te trezești blocat pe o anumită versiune. Soluția corectă este tfenv, managerul de versiuni pentru Terraform (echivalentul nvm pentru Node.js).
# Installa tfenv (macOS/Linux)
git clone https://github.com/tfutils/tfenv.git ~/.tfenv
echo 'export PATH="$HOME/.tfenv/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# Installa l'ultima versione stabile di Terraform
tfenv install latest
tfenv use latest
# Verifica installazione
terraform version
# Output: Terraform v1.9.x on linux_amd64
# Installa una versione specifica se il progetto la richiede
tfenv install 1.8.5
tfenv use 1.8.5
# Lista versioni installate
tfenv list
Pentru Windows, abordarea recomandată în 2026 și WSL2 cu Ubuntu sau Chocolatey:
# Windows con Chocolatey
choco install terraform
# Oppure scarica il binario da releases.hashicorp.com
# e aggiungilo al PATH manualmente
Instalați, de asemenea, pluginul VS Code HashiCorp Terraform (id: hashicorp.terraform):
oferă evidențiere de sintaxă, completare automată, definire continuă pentru furnizori și integrare
cu terraform fmt. Este cea mai robustă experiență IDE disponibilă pentru HCL.
HCL: Limbajul de configurare HashiCorp
HCL (HashiCorp Configuration Language) este un limbaj declarativ special conceput
pentru configurarea infrastructurilor. Nu este un limbaj de programare de uz general:
nu are buclă imperativă (utilizați for_each e count), nu are excepții,
Nu are I/O asincron. Acesta este un Caracteristici, nu o limită: simplitatea reduce
complexitatea accidentală a configuraţiilor.
Fișierul fundamental al fiecărui proiect Terraform e main.tf. Convenția comună
și separați configurația în aceste fișiere:
progetto-terraform/
├── main.tf # Risorse principali
├── variables.tf # Dichiarazione variabili
├── outputs.tf # Output values
├── versions.tf # Required providers e terraform block
├── locals.tf # Valori locali computati
└── terraform.tfvars # Valori delle variabili (non committare se contiene segreti)
Iată structura de bază a HCL cu tipurile de bloc de bază:
# versions.tf — blocco terraform: configura il comportamento del core
terraform {
required_version = ">= 1.8.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.100"
}
}
}
# variables.tf — dichiarazione variabili di input
variable "environment" {
description = "Nome dell'ambiente (dev, staging, prod)"
type = string
default = "dev"
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "L'ambiente deve essere dev, staging o prod."
}
}
variable "aws_region" {
description = "AWS Region dove deployare le risorse"
type = string
default = "eu-west-1"
}
variable "instance_count" {
description = "Numero di istanze EC2 da creare"
type = number
default = 2
}
variable "tags" {
description = "Tag comuni da applicare a tutte le risorse"
type = map(string)
default = {
ManagedBy = "Terraform"
Project = "demo"
}
}
# locals.tf — valori computati a partire da variabili
locals {
# Naming convention uniforme
name_prefix = "${var.environment}-${var.tags["Project"]}"
# Merge tag comuni con tag specifici per risorsa
common_tags = merge(var.tags, {
Environment = var.environment
CreatedAt = timestamp()
})
}
Configurați furnizorul AWS
I furnizor sunt pluginuri care permit Terraform să interacționeze cu API-uri externe: AWS, Azure, GCP, Kubernetes, GitHub, Datadog — practic fiecare serviciu are un furnizor Terraform. Furnizorul AWS este cel mai matur, cu peste 1200 de tipuri de resurse acceptate.
Pentru autentificarea AWS, nu utilizați niciodată cheia de acces codificată în codul HCL. Furnizorul AWS acceptă următoarele moduri, în ordinea priorităților:
# main.tf — configurazione provider AWS
provider "aws" {
region = var.aws_region
# NON fare questo in produzione:
# access_key = "AKIA..." # MAI
# secret_key = "..." # MAI
# Metodo consigliato 1: assume role (best practice per CI/CD)
# assume_role {
# role_arn = "arn:aws:iam::123456789:role/TerraformRole"
# }
# I tag di default vengono applicati a tutte le risorse
default_tags {
tags = local.common_tags
}
}
# Configurazione autenticazione (fuori da main.tf)
# La best practice e usare il file ~/.aws/credentials oppure
# variabili di ambiente:
# export AWS_ACCESS_KEY_ID="..."
# export AWS_SECRET_ACCESS_KEY="..."
# export AWS_DEFAULT_REGION="eu-west-1"
#
# In produzione: IAM Instance Profile o OIDC con GitHub Actions
Acum să creăm primele resurse AWS: un VPC cu subrețele publice și private:
# main.tf — prime risorse AWS
# Data source: recupera gli AZ disponibili nella region
data "aws_availability_zones" "available" {
state = "available"
}
# VPC principale
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${local.name_prefix}-vpc"
}
}
# Subnet pubblica (una per AZ)
resource "aws_subnet" "public" {
count = min(length(data.aws_availability_zones.available.names), 2)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = {
Name = "${local.name_prefix}-public-${count.index + 1}"
Tier = "Public"
}
}
# Subnet privata
resource "aws_subnet" "private" {
count = min(length(data.aws_availability_zones.available.names), 2)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index + 10)
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "${local.name_prefix}-private-${count.index + 1}"
Tier = "Private"
}
}
# Internet Gateway per le subnet pubbliche
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${local.name_prefix}-igw"
}
}
# Route table pubblica
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
tags = {
Name = "${local.name_prefix}-rt-public"
}
}
# Associazione route table - subnet pubblica
resource "aws_route_table_association" "public" {
count = length(aws_subnet.public)
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}
# outputs.tf — valori di output
output "vpc_id" {
description = "ID della VPC creata"
value = aws_vpc.main.id
}
output "public_subnet_ids" {
description = "IDs delle subnet pubbliche"
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
description = "IDs delle subnet private"
value = aws_subnet.private[*].id
}
Ciclul Plan-Aplica-Distruge
Ciclul de viață Terraform constă din patru comenzi fundamentale. Înțelege-le bine Este esențial să se evite cele mai frecvente accidente în producție.
terraform init
# Inizializza il working directory:
# - Scarica i provider (plugin binaries)
# - Configura il backend per lo state
# - Installa i moduli referenziati
terraform init
# Output atteso:
# Initializing the backend...
# Initializing provider plugins...
# - Finding hashicorp/aws versions matching "~> 5.0"...
# - Installing hashicorp/aws v5.54.1...
# Terraform has been successfully initialized!
# Upgrade dei provider all'ultima versione compatibile
terraform init -upgrade
# Ricrea il .terraform.lock.hcl (file di lock dei provider)
terraform providers lock -platform=linux_amd64 -platform=darwin_amd64
Fișierul .terraform.lock.hcl
Dosarul .terraform.lock.hcl trebuie să fie trimis în depozit.
Se asigură că toți membrii echipei și conducta CI folosesc exact aceeași
versiunea furnizorilor, evitând „funcționează pe mașina mea” pentru infrastructură.
Directorul .terraform/ în schimb intră în .gitignore.
plan de terraformă
# Genera il piano di esecuzione (DRY RUN)
terraform plan
# Salva il piano in un file binario (consigliato per CI/CD)
terraform plan -out=tfplan
# Specifica le variabili inline
terraform plan -var="environment=staging" -var="instance_count=3"
# Usa un file di variabili
terraform plan -var-file="staging.tfvars"
# Output tipico di plan:
# Terraform will perform the following actions:
#
# # aws_vpc.main will be created
# + resource "aws_vpc" "main" {
# + arn = (known after apply)
# + cidr_block = "10.0.0.0/16"
# + enable_dns_hostnames = true
# ...
# }
#
# Plan: 8 to add, 0 to change, 0 to destroy.
Simbolul + indică creație, ~ editare in loc,
-/+ distrugeți și recreați (forțați timpul de oprire), - distrugere.
Citiți întotdeauna cu atenție blocurile marcate -/+:
ele înseamnă că resursa trebuie recreată, ceea ce cauzează adesea timpi de nefuncționare sau pierderi de date.
se aplică terraform
# Applica le modifiche (chiede conferma interattiva)
terraform apply
# Applica il piano salvato (NON chiede conferma - usare in CI/CD)
terraform apply tfplan
# Auto-approve per ambienti non critici (attento in prod!)
terraform apply -auto-approve
# Apply con variabili
terraform apply -var="environment=prod" -var-file="prod.tfvars"
# Output dopo apply:
# Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
#
# Outputs:
# vpc_id = "vpc-0123456789abcdef0"
# public_subnet_ids = [
# "subnet-0abc123def456gh78",
# "subnet-0def456abc789ij01",
# ]
distruge terraforma
# Distrugge TUTTE le risorse gestite dallo state corrente
terraform destroy
# Destroy con auto-approve (ATTENZIONE: irreversibile)
terraform destroy -auto-approve
# Distrugge solo una risorsa specifica (con grande cautela)
terraform destroy -target=aws_subnet.public[0]
# In produzione, preferisci eliminare le risorse dal codice
# e fare terraform apply: Terraform le distruggerà correttamente
Anti-Pattern: distrugerea teraformei în producție
Nu fugi niciodată terraform destroy fără un plan de recuperare.
Cea mai bună practică este să eliminați resursa din codul HCL și să rulați terraform apply:
obțineți același rezultat, dar cu un plan explicit pe care îl puteți revizui mai întâi.
Unele organizații blochează capacitatea de a executa distrugere la nivel de politică IAM
pe medii de producție.
Configurați furnizorul Azure
Furnizorul azurerm gestionează resursele Azure. Spre deosebire de AWS, Azure folosește Service Principal sau Managed Identity pentru autentificare.
# versions.tf aggiornato con provider Azure
terraform {
required_version = ">= 1.8.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.100"
}
}
}
# Configurazione provider Azure
provider "azurerm" {
features {
resource_group {
prevent_deletion_if_contains_resources = true
}
key_vault {
purge_soft_delete_on_destroy = false
recover_soft_deleted_key_vaults = true
}
}
# Autenticazione via variabili d'ambiente (consigliato)
# ARM_CLIENT_ID, ARM_CLIENT_SECRET, ARM_TENANT_ID, ARM_SUBSCRIPTION_ID
# oppure Azure CLI: az login
}
# Risorse Azure di base
resource "azurerm_resource_group" "main" {
name = "${local.name_prefix}-rg"
location = "West Europe"
tags = local.common_tags
}
resource "azurerm_virtual_network" "main" {
name = "${local.name_prefix}-vnet"
address_space = ["10.1.0.0/16"]
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
tags = local.common_tags
}
resource "azurerm_subnet" "public" {
name = "public-subnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.1.1.0/24"]
}
resource "azurerm_subnet" "private" {
name = "private-subnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.1.2.0/24"]
}
Variabile, localuri și surse de date
Buna utilizare a variabilelor, localităților și surselor de date distinge o configurație Terraform profesionist dintr-un scenariu ad-hoc. Iată modelele de bază:
# Tipi di variabili in HCL
# Stringa semplice
variable "app_name" {
type = string
default = "myapp"
}
# Numero con validazione
variable "min_instances" {
type = number
default = 1
validation {
condition = var.min_instances >= 1 && var.min_instances <= 10
error_message = "Il numero di istanze deve essere tra 1 e 10."
}
}
# Lista di stringhe
variable "allowed_cidr_blocks" {
type = list(string)
default = ["10.0.0.0/8"]
}
# Map di stringhe
variable "database_config" {
type = map(string)
default = {
engine = "postgres"
version = "15.4"
size = "db.t3.medium"
}
}
# Oggetto con schema tipizzato
variable "network_config" {
type = object({
vpc_cidr = string
subnet_count = number
enable_nat = bool
})
default = {
vpc_cidr = "10.0.0.0/16"
subnet_count = 2
enable_nat = false
}
}
# Locals: valori computati (non input dall'utente)
locals {
# Concatenazioni
full_name = "${var.environment}-${var.app_name}"
# Condizionale ternario
instance_type = var.environment == "prod" ? "t3.medium" : "t3.micro"
# Ciclo su lista (for expression)
subnet_cidrs = [
for i in range(var.network_config.subnet_count) :
cidrsubnet(var.network_config.vpc_cidr, 8, i)
]
# Map transformation
tag_map = {
for k, v in var.database_config :
"db_${k}" => v
}
}
# Data sources: recuperano informazioni da risorse esistenti
# non gestite da questo state
# AMI Amazon Linux 2023 piu recente
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# Account ID corrente (utile per ARN)
data "aws_caller_identity" "current" {}
# Uso nei resource:
# ami = data.aws_ami.amazon_linux.id
# account_id = data.aws_caller_identity.current.account_id
Dosarul de stat: Inima Terraformului
Dosarul terraform.tfstate este „sursa adevărului” Terraform: cartografiază fiecare bun
definit în HCL cu omologul său din lumea reală din cloud. Înțelegerea modului în care funcționează este esențială
evita cele mai grave probleme.
// Struttura semplificata di terraform.tfstate
{
"version": 4,
"terraform_version": "1.9.0",
"serial": 42,
"lineage": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"outputs": {
"vpc_id": {
"value": "vpc-0123456789abcdef0",
"type": "string"
}
},
"resources": [
{
"mode": "managed",
"type": "aws_vpc",
"name": "main",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"id": "vpc-0123456789abcdef0",
"cidr_block": "10.0.0.0/16",
"enable_dns_hostnames": true,
...
}
}
]
}
]
}
Reguli de aur pentru dosarul de stat
- Nu editați niciodată
terraform.tfstatemanual - Nu te angajezi niciodată menționați-l în depozitul dvs. Git (adăugați-l la
.gitignore) - În echipe, folosiți întotdeauna un backend la distanță cu blocare (a se vedea articolul 03 din serie)
- Statul o poate contine secrete la vedere (parolă RDS, acreditări): tratați acest lucru ca date sensibile
- Înainte de operațiuni riscante, efectuați o copie de rezervă manuală:
terraform state pull > backup.tfstate
Comenzile de inspecție de stat
# Lista tutte le risorse gestite dallo state
terraform state list
# Mostra i dettagli di una risorsa specifica
terraform state show aws_vpc.main
# Rinomina una risorsa nello state (senza toccare l'infrastruttura)
terraform state mv aws_subnet.public aws_subnet.public_new
# Rimuove una risorsa dallo state (Terraform non la gestirà piu)
# La risorsa rimane nel cloud ma non è piu "owned" da Terraform
terraform state rm aws_subnet.private[0]
# Importa una risorsa esistente nello state
# (vedi articolo 03 per dettagli)
terraform import aws_vpc.main vpc-0123456789abcdef0
# Mostra l'output senza fare apply
terraform output vpc_id
terraform output -json # tutti gli output in formato JSON
Structura recomandată a proiectului
Pentru proiectele reale, structura unică a directoarelor devine rapid imposibil de gestionat. Iată două modele comune pentru organizarea unei infrastructuri Terraform în producție:
# Pattern 1: Organizzazione per ambiente
infra/
├── modules/ # Moduli riusabili
│ ├── networking/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── compute/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── environments/
│ ├── dev/
│ │ ├── main.tf # Usa i moduli
│ │ ├── variables.tf
│ │ ├── terraform.tfvars # Valori specifici per dev
│ │ └── versions.tf
│ ├── staging/
│ │ └── ...
│ └── prod/
│ └── ...
└── .gitignore # Esclude .terraform/, *.tfstate
# Pattern 2: Terragrunt (wrapper per DRY)
infra/
├── terragrunt.hcl # Config globale
├── modules/
│ └── networking/
├── live/
│ ├── dev/
│ │ └── networking/
│ │ └── terragrunt.hcl
│ └── prod/
│ └── networking/
│ └── terragrunt.hcl
Cele mai bune practici pentru început
După ce am văzut teoria, iată regulile de bază care îi disting pe cei care folosesc Terraform corect de către cei care creează datorii tehnice din prima zi:
# 1. Formatta sempre prima di committare
terraform fmt -recursive
# 2. Valida la sintassi
terraform validate
# 3. Usa tflint per linting avanzato (trova deprecazioni, pattern errati)
tflint --init
tflint
# 4. Esegui checkov per security scanning
pip install checkov
checkov -d .
# 5. Pre-commit hooks per automatizzare tutto
# .pre-commit-config.yaml
# repos:
# - repo: https://github.com/antonbabenko/pre-commit-terraform
# hooks:
# - id: terraform_fmt
# - id: terraform_validate
# - id: terraform_tflint
# - id: terraform_checkov
.gitignore pentru Terraform
# .gitignore per progetti Terraform
.terraform/
*.tfstate
*.tfstate.backup
*.tfstate.*.backup
.terraform.tfstate.lock.info
*.tfvars # Se contengono segreti (crea terraform.tfvars.example)
override.tf
override.tf.json
*_override.tf
*_override.tf.json
crash.log
.terraformrc
terraform.rc
Exemplu complet: aplicație web pe AWS
Să punem totul împreună într-un exemplu real: o instanță EC2 cu grup de securitate, echilibrator de încărcare și bază de date RDS, structurate corect.
# main.tf — infrastruttura web app completa
# Security Group per le istanze web
resource "aws_security_group" "web" {
name = "${local.name_prefix}-sg-web"
description = "Security group per istanze web"
vpc_id = aws_vpc.main.id
ingress {
description = "HTTP dal load balancer"
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = { Name = "${local.name_prefix}-sg-web" }
}
# Security Group per ALB
resource "aws_security_group" "alb" {
name = "${local.name_prefix}-sg-alb"
description = "Security group per Application Load Balancer"
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# Launch Template per le istanze EC2
resource "aws_launch_template" "web" {
name_prefix = "${local.name_prefix}-lt-"
image_id = data.aws_ami.amazon_linux.id
instance_type = local.instance_type
network_interfaces {
associate_public_ip_address = false
security_groups = [aws_security_group.web.id]
}
user_data = base64encode(<<-EOF
#!/bin/bash
dnf update -y
dnf install -y nginx
systemctl enable nginx
systemctl start nginx
echo "Deploy Terraform - ${var.environment}
" > /usr/share/nginx/html/index.html
EOF
)
tag_specifications {
resource_type = "instance"
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-web"
})
}
}
# Auto Scaling Group
resource "aws_autoscaling_group" "web" {
name = "${local.name_prefix}-asg"
vpc_zone_identifier = aws_subnet.private[*].id
target_group_arns = [aws_lb_target_group.web.arn]
health_check_type = "ELB"
min_size = var.environment == "prod" ? 2 : 1
max_size = var.environment == "prod" ? 6 : 2
desired_capacity = var.environment == "prod" ? 2 : 1
launch_template {
id = aws_launch_template.web.id
version = "$Latest"
}
tag {
key = "Name"
value = "${local.name_prefix}-web"
propagate_at_launch = true
}
}
# Application Load Balancer
resource "aws_lb" "main" {
name = "${local.name_prefix}-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = aws_subnet.public[*].id
enable_deletion_protection = var.environment == "prod"
tags = local.common_tags
}
resource "aws_lb_target_group" "web" {
name = "${local.name_prefix}-tg-web"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.main.id
health_check {
enabled = true
healthy_threshold = 2
unhealthy_threshold = 3
timeout = 5
interval = 30
path = "/health"
}
}
resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.main.arn
port = "80"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.web.arn
}
}
Concluzii și pașii următori
Acum aveți o bază solidă pentru a lucra cu Terraform profesional: cunoașteți sintaxa HCL, știți cum să configurați furnizorii AWS și Azure, înțelegeți ciclul Plan-Apply-Destroy și regulile esențial pentru a gestiona în siguranță fișierul de stare.
Următorul pas natural în creșterea ta cu Terraform este să înveți să-ți organizezi codul in module reutilizabile: Odată ce infrastructura dvs. depășește 200-300 de linii de HCL, modularizarea devine esențială pentru menținere.
Seria completă: Terraform și IaC
- Articolul 01 (acest) — Terraform de la zero: HCL, Provider și Plan-Apply-Destroy
- Articolul 02 — Proiectarea modulelor Terraform reutilizabile: Structură, I/O și Registry
- Articolul 03 — Stare Terraform: Backend la distanță cu S3/GCS, Blocare și Import
- Articolul 04 — Terraform în CI/CD: Flux de lucru GitHub Actions, Atlantis și Pull Request
- Articolul 05 — Testarea IaC: Terratest, Terraform Native Test și Contract Testing
- Articolul 06 — Securitatea IaC: Politica Checkov, Trivy și OPA ca cod
- Articolul 07 — Terraform Multi-Cloud: AWS + Azure + GCP cu module partajate
- Articolul 08 — GitOps pentru Terraform: Controler Flux TF, Spacelift și Detecție Drift
- Articolul 09 – Terraform vs Pulumi vs OpenTofu: Comparație finală 2026
- Articolul 10 — Modele Terraform Enterprise: Spațiu de lucru, Sentinel și scalarea echipei
Resurse oficiale
- Documentația oficială Terraform
- Registrul Terraform — furnizori, module și politici
- HashiCorp Learn — Tutoriale interactive







