Cloud · Terraform|13 min de lectura|

Terraform para Infraestructura Empresarial

Terraform (y su fork OpenTofu) es el estándar de facto para Infrastructure as Code en empresas. No porque sea perfecto, sino porque resuelve los problemas reales de equipos que gestionan infraestructura a escala: estado compartido, módulos reutilizables, plan antes de apply, y soporte multi-cloud real. La transición de scripts de bash o ClickOps a Terraform no es solo técnica — cambia fundamentalmente cómo trabaja el equipo: los cambios se proponen, revisan y aprueban como código.

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.

text
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 compartidas

Los 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.

hcl
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.

hcl
# 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.

yaml
# 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: production
El apply siempre debe usar el binary generado en el plan, nunca generar un nuevo plan en el stage de apply. Si hay un nuevo plan en el apply, lo que el equipo aprobó y lo que se aplica pueden ser diferentes.

Policy 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
rego
# 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?
Terraform si el equipo incluye ingenieros de operaciones que no son developers de profesión — HCL es más accesible para perfiles Ops. Pulumi si el equipo de plataforma son principalmente ingenieros de software que prefieren Python, TypeScript o Go. Para la mayoría de las empresas, Terraform/OpenTofu es la elección más pragmática por el ecosistema de módulos, la documentación y la mayor disponibilidad de talento.
¿Cómo importo recursos que ya existen y no fueron creados con Terraform?
Con terraform import. El proceso: escribir la definición del recurso en HCL, ejecutar terraform import aws_instance.app i-1234567890abcdef0 para asociar el recurso existente al state, y luego terraform plan para verificar que no haya cambios no deseados. Con Terraform 1.5+, el bloque import en HCL permite hacer esto de forma declarativa como parte del código.
¿Cuánto tarda implementar Terraform en una empresa que gestiona infra manualmente?
El proceso más largo no es escribir el código — es importar la infraestructura existente y establecer el flujo de trabajo del equipo. En proyectos reales, el primer módulo crítico (cluster EKS o base de datos RDS) con pipeline funcional tarda 2-3 semanas. La cobertura completa de infraestructura es un proceso de 3-6 meses dependiendo de la complejidad.
¿Es necesario Terragrunt o se puede hacer con Terraform puro?
Terragrunt no es necesario para equipos pequeños o con poca variación entre environments. Se vuelve valioso cuando tienes 3+ environments con configuración de backend repetida, o cuando la duplicación entre environments empieza a ser un problema operacional real. Como regla: empieza con Terraform puro y añade Terragrunt cuando el dolor de la repetición sea concreto.
¿Cómo gestiono los secretos en Terraform (passwords de bases de datos, API keys)?
Nunca commitear valores de secretos en el código Terraform. Las opciones: (1) variables de entorno TF_VAR_nombre para valores que se pasan en runtime, (2) integración con AWS Secrets Manager o HashiCorp Vault mediante data sources que leen los valores en tiempo de plan/apply, (3) outputs sensibles marcados como sensitive = true para que Terraform no los muestre en logs.

¿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

Artículos relacionados

IQS

Equipo de Ingeniería — IQS

Ingenieros de software, cloud y DevOps con experiencia en proyectos empresariales.