Cómo implantar IaC con Terraform en un entorno empresarial real

Terraform es sencillo de aprender en un tutorial. Llevarlo a una empresa con años de infraestructura gestionada a mano, equipos con distintos niveles técnicos y procesos de cambio rígidos es otra historia. Estas son las fases y decisiones clave.


El problema: infraestructura gestionada "a mano" a escala

En muchas empresas la infraestructura cloud se gestiona de forma principalmente manual: consola de AWS, scripts Bash ad-hoc y documentación que casi nunca está actualizada. Eso funciona cuando el equipo es pequeño y el entorno es estable. A escala, es una fuente constante de inconsistencias, errores y "¿quién tocó esto y cuándo?".

La decisión de implantar IaC con Terraform no es solo técnica — es organizacional. Y esa es la parte más difícil.

Fase 1: Convencer antes de implementar

Antes de escribir una línea de Terraform, tuve que conseguir el buy-in del equipo y de la dirección. Los argumentos que funcionaron:

  • Reproducibilidad: cualquier entorno se puede replicar en minutos, no en días.
  • Auditoría: cada cambio de infraestructura queda registrado en git. ¿Quién cambió el security group? git log.
  • Reducción de errores: los errores humanos en la consola son inevitables; los errores en código son detectables y corregibles.
  • Velocidad: aprovisionar un entorno de staging nuevo pasa de horas a minutos.

Con la dirección, el argumento fue diferente: reducción de riesgo operacional y cumplimiento con los requisitos normativos sobre resiliencia de infraestructura.

Fase 2: Empezar pequeño — el proyecto piloto

El error clásico es intentar "terraformizar" todo a la vez. Nosotros empezamos con un proyecto piloto acotado: la infraestructura de un entorno de desarrollo no crítico. Esto nos permitió:

  • Definir las convenciones de nomenclatura y estructura de directorios antes de que hubiera demasiado código.
  • Identificar los recursos que iban a ser más complejos de importar al state.
  • Formar al equipo con código real, no con ejemplos de tutorial.
  • Detectar los problemas de permisos IAM sin afectar producción.

Fase 3: Estructura de módulos

La estructura que adoptamos separa claramente los módulos reutilizables de los entornos concretos:

infra/
├── modules/
│   ├── networking/     # VPC, subnets, route tables
│   ├── compute/        # EC2, Auto Scaling Groups
│   ├── security/       # Security Groups, IAM roles
│   └── storage/        # S3, EBS, backups
└── environments/
    ├── dev/
    ├── staging/
    └── prod/

Cada entorno llama a los mismos módulos pero con variables distintas. Esto garantiza que dev, staging y prod son estructuralmente idénticos — las diferencias están en los valores, no en la arquitectura.

Fase 4: State remoto y locking

El state de Terraform es el fichero que sabe qué recursos existen en la realidad. Guardarlo en local es un error en un equipo: dos personas aplicando cambios a la vez pueden corromperlo. Nuestra solución:

terraform {
  backend "s3" {
    bucket         = "mi-empresa-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "eu-south-2"
    encrypt        = true
    dynamodb_table = "terraform-state-lock"
  }
}

S3 para almacenar el state (con versionado activado), DynamoDB para el locking. Esto permite que varios miembros del equipo trabajen sin pisarse, y recuperar cualquier versión anterior del state si algo va mal.

Fase 5: Pipeline CI/CD para Terraform

Tener el código en git no es suficiente — hay que asegurarse de que nadie aplica cambios directamente desde su máquina en producción. El pipeline que implementamos con GitHub Actions:

  • En cada PR: terraform fmt, terraform validate y terraform plan. El plan se publica como comentario en el PR para revisión.
  • Al mergear a main: terraform apply automático en dev y staging.
  • Para producción: terraform apply requiere aprobación manual en el pipeline.
# .github/workflows/terraform.yml (fragmento)
- name: Terraform Plan
  run: terraform plan -no-color -out=tfplan
  env:
    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

- name: Comment Plan on PR
  uses: actions/github-script@v7
  with:
    script: |
      github.rest.issues.createComment({
        issue_number: context.issue.number,
        body: planOutput
      })

El reto más grande: importar recursos existentes

Cuando empiezas con Terraform en una infraestructura que ya existe, tienes que importar esos recursos al state sin destruirlos. Este proceso es lento y delicado. Lo que aprendí:

  • Importar de menos a más crítico, igual que en una migración.
  • Hacer siempre un terraform plan después de importar para confirmar que no hay drift.
  • Documentar cada importación — el terraform import no genera el código HCL, solo el state.
  • Usar terraform state list y terraform state show para inspeccionar antes de hacer cambios.

Resultados que se pueden esperar

Tras una implantación correcta de IaC con Terraform, los beneficios más habituales son:

  • La mayoría de la infraestructura cloud gestionada como código y versionada en git.
  • El tiempo de aprovisionamiento de nuevos entornos se reduce de días a minutos.
  • Reducción significativa de incidentes causados por cambios manuales no controlados.
  • Auditoría de cambios trivial: cada modificación tiene autor, fecha y motivo en el historial.
IaC no es solo una decisión técnica. Es una decisión de madurez operacional. El código es la documentación.