Terraform Best Practices — Módulos, State y Workspaces
Guía práctica de mejores prácticas de Terraform: diseño de módulos, gestión de estado remoto, workspaces y seguridad para infraestructura como código de grado productivo.
Nota para desarrolladores hispanohablantes: Esta guía incluye ejemplos y convenciones de nomenclatura adaptadas a equipos que trabajan en español. Cuando existen diferencias significativas en terminología técnica entre el inglés y el español, se indican explícitamente para facilitar la comunicación en equipos multiculturales.
Overview
Terraform es la herramienta de infrastructure-as-code más usada, permitiendo a equipos definir, provisionar y gestionar recursos cloud a través de archivos de configuración declarativos. Mientras empezar con Terraform es sencillo, construir infraestructura de grado productivo requiere disciplina en diseño de módulos, gestión de estado, seguridad y flujos de colaboración. Esta guía cubre las prácticas que separan código Terraform de prototipo de infraestructura enterprise-ready.
When to Use
- Gestionas infraestructura cloud que cambia frecuentemente
- Múltiples miembros del equipo necesitan colaborar en infraestructura
- Necesitas ambientes reproducibles (dev, staging, producción)
- Quieres version control para tus definiciones de infraestructura
Diseño de Módulos
Root Module vs Child Modules
terraform/
├── modules/
│ ├── vpc/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── database/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── environments/
│ ├── dev/
│ │ └── main.tf
│ ├── staging/
│ │ └── main.tf
│ └── prod/
│ └── main.tf
Interfaz de Módulo
Mantén inputs explícitos y outputs mínimos.
# modules/vpc/variables.tf
variable "vpc_cidr" {
description = "Bloque CIDR para la VPC"
type = string
default = "10.0.0.0/16"
}
variable "availability_zones" {
description = "Lista de AZs a usar"
type = list(string)
}
# modules/vpc/outputs.tf
output "vpc_id" {
description = "ID de la VPC creada"
value = aws_vpc.main.id
}
output "private_subnet_ids" {
description = "Lista de IDs de subnets privadas"
value = aws_subnet.private[*].id
}
Composición Sobre Herencia
Construye módulos pequeños y componibles en lugar de monolíticos.
# environments/prod/main.tf
module "vpc" {
source = "../../modules/vpc"
vpc_cidr = "10.0.0.0/16"
availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"]
}
module "database" {
source = "../../modules/database"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnet_ids
instance_class = "db.r6g.xlarge"
}
Gestión de Estado
Estado Remoto con Locking
Nunca almacenes estado en version control. Usa backends remotos con locking.
# backend.tf
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
# Crear los recursos del backend
aws s3api create-bucket --bucket my-terraform-state --region us-east-1
aws s3api put-bucket-versioning --bucket my-terraform-state --versioning-configuration Status=Enabled
aws dynamodb create-table \
--table-name terraform-locks \
--attribute-definitions AttributeName=LockID,AttributeType=S \
--key-schema AttributeName=LockID,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
Aislamiento de Estado
Usa archivos de estado separados por ambiente y por componente.
| Enfoque | Mejor Para |
|---|---|
| Workspaces | Ambientes simples (dev/staging/prod) |
| Directorios separados | Ambientes complejos con diferentes configuraciones |
| Backends separados | Máximo aislamiento, diferentes cuentas cloud |
Workspaces
Los workspaces de Terraform permiten múltiples archivos de estado dentro de la misma configuración.
# Crear y cambiar a un workspace
terraform workspace new prod
terraform workspace select prod
# Usar workspace en configuración
locals {
environment = terraform.workspace
instance_count = {
dev = 1
staging = 2
prod = 3
}[terraform.workspace]
}
Precaución: Los workspaces comparten la misma configuración de backend. Para aislamiento fuerte, usa configuraciones de backend separadas o incluso cuentas cloud separadas.
Prácticas de Seguridad
Nunca Commitees Secrets
# .gitignore
*.tfstate
*.tfstate.*
.terraform/
.terraform.lock.hcl
*.auto.tfvars
secrets.tfvars
Usa Variables para Datos Sensibles
variable "db_password" {
description = "Password de administrador de base de datos"
type = string
sensitive = true
}
Least Privilege para CI/CD
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["ec2:*", "rds:*", "s3:*"],
"Resource": "*",
"Condition": {
"StringEquals": {"aws:RequestedRegion": "us-east-1"}
}
},
{
"Effect": "Deny",
"Action": ["ec2:DeleteVpc", "rds:DeleteDBInstance"],
"Resource": "*"
}
]
}
Testing y Validación
Análisis Estático
# Chequeo de formato
terraform fmt -check -recursive
# Validar sintaxis
terraform validate
# Escaneo de seguridad con Checkov
checkov -d .
Flujo de Revisión de Plan
# Generar un archivo de plan
terraform plan -out=tfplan
# Revisar el plan
terraform show tfplan
# Aplicar solo el plan revisado
terraform apply tfplan
Errores Comunes
- Almacenar estado en Git — usa backends remotos con encryption y versioning
- Hardcodear credenciales — usa variables, environment variables o IAM roles
- Módulos monolíticos — divide en módulos pequeños, reutilizables y testeables
- No usar archivos de plan — siempre revisa planes antes de aplicar
- Ignorar pinning de versiones de provider — pin versions para prevenir breaking changes
- Sin state locking — múltiples engineers ejecutando terraform simultáneamente corrompen el estado
FAQ
¿Debería usar Terraform Cloud? Terraform Cloud/Enterprise provee estado remoto, colaboración de equipo y policy-as-code. Para equipos pequeños, backend S3 + DynamoDB es suficiente.
¿Cómo gestiono secrets en Terraform?
Usa environment variables (TF_VAR_*), HashiCorp Vault o secret managers cloud (AWS Secrets Manager, Azure Key Vault, GCP Secret Manager). Marca variables como sensitive = true.
¿Cuándo debería usar módulos vs workspaces? Los módulos son para componentes de infraestructura reutilizables. Los workspaces son para aislamiento de estado por ambiente. Usa ambos: módulos para código DRY, workspaces (o directorios separados) para separación de ambientes.
Recursos Relacionados
AWS Basics — Core Services for Developers
A practical guide to AWS core services for developers: compute, storage, databases, networking, and security fundamentals with hands-on examples.
GuideAzure Basics — Core Services for Developers
A practical guide to Microsoft Azure core services for developers: compute, storage, databases, networking, and identity with hands-on examples.
GuideGCP Basics — Core Services for Developers
A practical guide to Google Cloud Platform core services for developers: compute, storage, databases, networking, and data analytics with hands-on examples.
GuideKubernetes Advanced — Beyond the Basics
An advanced guide to Kubernetes: operators, custom resources, admission controllers, multi-cluster management, and production hardening for experienced users.