El problema: Terraform en solitario vs en equipo
Terraform es genial cuando trabajas solo. El problema aparece cuando tu equipo crece y empiezan las preguntas:
- “¿Quién tiene el state?”
- “¿Por qué mi plan muestra cambios que no hice?”
- “¿Cómo evitamos que dos personas apliquen al mismo tiempo?”
Remote State con S3 + DynamoDB
La primera regla de Terraform en equipo: nunca guardes el state local.
# backend.tf
terraform {
backend "s3" {
bucket = "mi-empresa-terraform-state"
key = "production/networking/terraform.tfstate"
region = "eu-west-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
# Crear la tabla de locks
resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
tags = {
Name = "terraform-state-locks"
Environment = "shared"
}
}
Estructura de proyecto escalable
infrastructure/
├── modules/
│ ├── networking/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ ├── outputs.tf
│ │ └── README.md
│ ├── eks-cluster/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── monitoring/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── environments/
│ ├── production/
│ │ ├── main.tf
│ │ ├── backend.tf
│ │ ├── variables.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ │ ├── main.tf
│ │ ├── backend.tf
│ │ └── terraform.tfvars
│ └── dev/
│ ├── main.tf
│ └── terraform.tfvars
└── .github/
└── workflows/
└── terraform.yml
Pipeline de CI/CD para Terraform
# .github/workflows/terraform.yml
name: Terraform CI/CD
on:
pull_request:
paths:
- 'infrastructure/**'
push:
branches: [main]
paths:
- 'infrastructure/**'
jobs:
plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.7.0
- name: Terraform Init
run: terraform init
working-directory: infrastructure/environments/production
- name: Terraform Plan
run: terraform plan -out=tfplan -no-color
working-directory: infrastructure/environments/production
- name: Comment PR with Plan
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const output = `#### Terraform Plan 📖
\`\`\`
${process.env.PLAN}
\`\`\`
*Pushed by: @${{ github.actor }}*`;
apply:
needs: plan
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- name: Terraform Apply
run: terraform apply -auto-approve tfplan
working-directory: infrastructure/environments/production
Buenas prácticas
- Usa módulos para código reutilizable
- Versiona tus módulos con tags de Git
- No hardcodees valores — usa variables y tfvars
- State por componente: separa networking, compute, databases
- Policy as Code: usa
terraform-complianceoOPA
Conclusión
Terraform en equipo requiere disciplina, pero con la estructura correcta se convierte en una herramienta poderosa para gestionar infraestructura de forma colaborativa y segura.
¿Tienes tu propio setup de Terraform? Cuéntame en Twitter.