Terraform Associate
Deep Dive
El flujo de trabajo central de Terraform consta de tres fases que debes entender en profundidad para el examen: qué ocurre internamente en cada una, qué archivos se generan y cómo gestionar el directorio de trabajo.
Contenido
✏️
1. Write
Escribes archivos .tf en HCL describiendo el estado deseado de la infraestructura.
🔍
2. Plan
Terraform compara el estado deseado (código) con el estado actual (tfstate) y calcula las diferencias.
🚀
3. Apply
Ejecuta las llamadas a API cloud necesarias y actualiza el archivo de estado con los resultados.
Durante la fase de escritura, solo editas archivos de texto. Terraform no se comunica con ninguna API cloud en esta fase. Lo importante es que el código sea válido sintácticamente (lo verifica terraform validate) y bien formateado (terraform fmt).
# main.tf — describes el estado DESEADO
resource "aws_s3_bucket" "data" {
bucket = "mi-empresa-datos-prod"
}
resource "aws_s3_bucket_versioning" "data" {
bucket = aws_s3_bucket.data.id # referencia crea dependencia implícita
versioning_configuration {
status = "Enabled"
}
}💡 Antes del primer init
Después de escribir la configuración, debes ejecutar terraform init para descargar los providers y módulos. Sin init, plan y apply fallarán porque no existen los plugins.
terraform plan es la fase más importante para el examen. Internamente realiza varios pasos:
Carga la configuración
Lee todos los archivos .tf del directorio de trabajo y los parsea.
Carga el estado actual
Lee terraform.tfstate (local o remoto) para conocer el estado real conocido.
Refresca el estado
Consulta las APIs cloud para verificar que el estado en tfstate aún coincide con la realidad (puede detectar drift).
Construye el grafo
Genera un DAG (grafo acíclico dirigido) con las dependencias entre recursos.
Calcula el diff
Compara configuración deseada vs estado actual y determina: + crear, - destruir, ~ modificar, -/+ reemplazar.
Muestra el plan
Imprime los cambios en pantalla y/o guarda el plan binario (-out=plan.out).
| Símbolo | Significado | Ejemplo |
|---|---|---|
| + | Crear recurso nuevo | aws_vpc.main will be created |
| - | Destruir recurso existente | aws_vpc.old will be destroyed |
| ~ | Modificar recurso in-place | aws_instance.web will be updated in-place |
| -/+ | Destruir y recrear (reemplazar) | aws_instance.web must be replaced |
| <= | Leer data source | data.aws_ami.ubuntu will be read |
Apply ejecuta las llamadas a API definidas en el plan. Si se pasa un archivo de plan (terraform apply plan.out), Terraform usa exactamente ese plan sin recalcular. Si no se pasa, genera un nuevo plan y pide confirmación.
# Flujo recomendado en producción: terraform plan -out=tfplan # guarda el plan exacto terraform apply tfplan # aplica exactamente ese plan (sin confirmación manual) # Flujo rápido (desarrollo): terraform apply # genera plan + pide "yes" terraform apply -auto-approve # genera plan + aplica sin preguntar
⚠️ Apply modifica infraestructura real
Usa -auto-approve solo en pipelines de CI/CD donde ya revisaste el plan en el paso anterior. Nunca en producción desde tu máquina sin revisar el plan primero.
Después de terraform init, se crea el directorio .terraform/ con todo lo necesario para ejecutar plan y apply.
.terraform/providers/
Binarios de los providers descargados desde el registry. Pesados, no se cometen al VCS.
.terraform/modules/
Módulos descargados de fuentes remotas (registry, GitHub, S3…).
.terraform/terraform.tfstate
Estado del backend (solo si usas backend remoto). No es el tfstate principal.
terraform.tfstate
El estado principal (backend local). Contiene el estado real de la infra gestionada.
terraform.tfstate.backup
Copia de seguridad automática del tfstate anterior a cada apply.
.terraform.lock.hcl
Lock file de versiones de providers. SÍ se commitea al VCS.
El archivo .terraform.lock.hcl fija las versiones exactas de los providers instalados para que todos los miembros del equipo usen exactamente las mismas versiones.
# .terraform.lock.hcl (generado por terraform init)
provider "registry.terraform.io/hashicorp/aws" {
version = "5.31.0"
constraints = "~> 5.0"
hashes = [
"h1:ABC123...", # hash del binario para verificación de integridad
"zh:XYZ789...",
]
}| Archivo / Directorio | ¿Commitear? | Motivo |
|---|---|---|
| *.tf | ✅ Sí | Es el código fuente de la infraestructura |
| .terraform.lock.hcl | ✅ Sí | Fija versiones exactas de providers para reproducibilidad |
| terraform.tfstate | ❌ No | Datos sensibles en texto plano; usar backend remoto |
| terraform.tfstate.backup | ❌ No | Mismo motivo que tfstate |
| .terraform/ | ❌ No | Binarios pesados regenerables con terraform init |
| *.tfvars con secretos | ❌ No | Credenciales, tokens, contraseñas |
| *.auto.tfvars sin secretos | ✅ Sí | Variables de entorno no sensibles (región, tamaños, etc.) |
¿Entendiste este tema?
Pon a prueba lo que acabas de aprender
Un desarrollador ejecuta terraform plan y observa que un recurso aws_instance aparece marcado con -/+. ¿Qué significa esto y qué ocurrirá en el siguiente apply?