Estructura de módulos que escala con el equipo
El error más frecuente en empresas que adoptan Terraform: módulos monolíticos que definen toda la infraestructura en un directorio. Esto crea problemas de blast radius (un error afecta toda la infra), tiempos de plan/apply elevados, y dificultad para que múltiples equipos trabajen en paralelo.
infrastructure/
├── modules/
│ ├── eks-cluster/ # módulo reutilizable: cluster EKS
│ ├── rds-postgres/ # módulo reutilizable: base de datos RDS
│ ├── vpc-networking/ # módulo reutilizable: VPC, subnets, routing
│ └── monitoring-stack/ # módulo reutilizable: Prometheus + Grafana
├── environments/
│ ├── production/
│ │ ├── main.tf # invoca módulos con vars de producción
│ │ ├── variables.tf
│ │ └── backend.tf
│ └── staging/
│ ├── main.tf
│ └── backend.tf
└── global/
├── iam/ # roles y políticas cross-environment
└── dns/ # zonas DNS compartidasLos módulos son código con interfaz definida; los environments son invocaciones de esos módulos con parámetros específicos. El equipo de plataforma mantiene los módulos mientras los equipos de producto configuran sus environments de forma independiente sin acoplamiento.
Remote State: el error más costoso de Terraform en empresas
El state file local es el error de principiante con las consecuencias más graves en producción. En una empresa, múltiples personas aplican cambios. Sin state remoto y locking, dos applys simultáneos corrompen el state. Si el state se pierde o se corrompe, Terraform ya no conoce qué recursos existen y puede intentar recrearlos — en producción, eso puede ser un incidente grave.
terraform {
backend "s3" {
bucket = "empresa-terraform-state"
key = "production/eks/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
kms_key_id = "arn:aws:kms:us-east-1:123456789:key/abc-123"
}
}DynamoDB provee el locking que previene dos terraform apply simultáneos. KMS encryption es obligatoria para state files que contienen outputs sensibles (passwords de RDS, tokens de API). En GCP el equivalente es un bucket GCS con versioning y uniform bucket-level access habilitados.
Terragrunt: DRY para múltiples environments
Terraform nativo tiene el problema de la repetición entre environments: el código de staging y production es prácticamente idéntico excepto por algunos valores. Terragrunt añade una capa de configuración que permite definir el backend, providers y configuración común una sola vez.
# root terragrunt.hcl — configuración compartida por todos los environments
remote_state {
backend = "s3"
config = {
bucket = "empresa-terraform-state"
key = "${path_relative_to_include()}/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
generate = {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
}
}
generate "provider" {
path = "provider.tf"
if_exists = "overwrite_terragrunt"
contents = <<EOF
provider "aws" {
region = var.aws_region
assume_role {
role_arn = var.deploy_role_arn
}
}
EOF
}Cada environment tiene solo un terragrunt.hcl con los valores específicos del entorno. El 80% de la configuración vive en el root y se hereda automáticamente. Esto elimina la duplicación que hace que los cambios a la configuración del backend requieran modificar 4-5 archivos.
CI/CD Pipeline para Terraform: el plan como artefacto
El flujo de CI/CD correcto para Terraform empresarial: terraform plan en cada PR con los cambios comentados directamente en el PR, revisión y aprobación del equipo, y terraform apply automático (o manual con aprobación explícita) al merge. El plan file debe guardarse como artefacto del pipeline y usarse en el apply — no generar un nuevo plan — para garantizar que lo que se aprueba es exactamente lo que se aplica.
# GitLab CI — pipeline Terraform con plan como artefacto
.terraform_base:
image: hashicorp/terraform:1.9
before_script:
- terraform init -backend-config="key=${TF_STATE_KEY}"
plan:
extends: .terraform_base
script:
- terraform plan -out=tfplan.binary -no-color 2>&1 | tee plan.txt
artifacts:
paths: [tfplan.binary, plan.txt]
apply:
extends: .terraform_base
script:
- terraform apply -auto-approve tfplan.binary
needs: [plan]
when: manual
environment: productionPolicy as Code: prevenir antes del apply
En infraestructura empresarial, no todos los cambios de Terraform deben poder aplicarse sin validaciones adicionales. Open Policy Agent con Conftest permite definir políticas que se ejecutan contra el plan de Terraform antes del apply.
Políticas que implementamos típicamente en proyectos empresariales:
- No crear buckets S3/GCS sin encryption habilitada
- No permitir security groups con 0.0.0.0/0 en puertos de administración (22, 3389)
- Verificar que todos los recursos tengan tags de costo, equipo y ambiente
- Restricciones de tipo de instancia por environment (no t3.micro en producción)
- Validar que los RDS no sean publicly accessible
# OPA policy — verificar encryption en S3
package terraform.aws
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
not resource.change.after.server_side_encryption_configuration
msg := sprintf(
"S3 bucket '%v' requiere encryption configurada",
[resource.address]
)
}Workspaces vs. Directorios Separados
Los workspaces de Terraform son útiles para environments efímeros (test environments que se crean y destruyen frecuentemente). Para production y staging que tienen diferencias estructurales significativas, directorios separados son más explícitos y más seguros — eliminan el riesgo de aplicar en el workspace equivocado.
Señal de alarma: si alguien en tu equipo ha aplicado cambios a producción cuando pensaba que estaba en staging (por un workspace equivocado), es el momento de migrar a directorios separados.
Preguntas frecuentes
¿Terraform o Pulumi para una empresa nueva en IaC?
¿Cómo importo recursos que ya existen y no fueron creados con Terraform?
¿Cuánto tarda implementar Terraform en una empresa que gestiona infra manualmente?
¿Es necesario Terragrunt o se puede hacer con Terraform puro?
¿Cómo gestiono los secretos en Terraform (passwords de bases de datos, API keys)?
¿Tu equipo gestiona infraestructura cloud con scripts o ClickOps? Podemos ayudarte a migrar a Terraform con el proceso correcto, sin interrumpir la operación actual.
Habla con el equipo