Terraform Associate

Deep Dive

Practicar ahora
D3 · Núcleo de Terraform

Resources, data sources y dependencias

Los recursos son el elemento central de Terraform: definen la infraestructura que quieres gestionar. Las data sources permiten leer infraestructura existente. Entender dependencias y el bloque lifecycle es clave para el examen.

Sintaxis del bloque resource

El bloque resource tiene dos etiquetas obligatorias: el tipo (determinado por el provider) y el nombre local (identificador dentro de Terraform).

# resource "<TIPO>" "<NOMBRE_LOCAL>" { ... }
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"

  tags = {
    Name = "web-server"
  }
}

# Dirección del recurso: aws_instance.web
# Atributo: aws_instance.web.id
# Atributo: aws_instance.web.public_ip

# Módulo raíz:       aws_instance.web
# Módulo hijo:       module.app.aws_instance.web
# Módulo anidado:    module.app.module.compute.aws_instance.web
ConceptoDescripciónEjemplo
TipoDefine qué API se llama (determinado por el provider)aws_instance, azurerm_virtual_machine
Nombre localIdentificador único dentro del módulo (no en la nube)web, database, main — solo letras, números, _
DirecciónTipo + nombre = dirección completa del recursoaws_instance.web
ArgumentosParámetros que configuran el recurso (definidos por el provider)ami, instance_type, tags
AtributosValores calculados tras la creación (export values).id, .arn, .public_ip

Data sources: leer sin crear

Las data sources permiten consultar información de infraestructura existente (creada por otro módulo, otra herramienta, o manualmente) sin que Terraform la gestione.

# data "<TIPO>" "<NOMBRE_LOCAL>" { ... }
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"]   # Canonical

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-*-22.04-amd64-server-*"]
  }
}

# Usar el resultado de la data source
resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id   # data.<tipo>.<nombre>.<attr>
  instance_type = "t3.micro"
}

# Otros ejemplos de data sources
data "aws_vpc" "existing" {
  id = "vpc-12345678"                # buscar por ID exacto
}

data "aws_availability_zones" "available" {
  state = "available"                # todas las AZs disponibles
}

💡 Data sources se leen en terraform plan

Las data sources se consultan durante el terraform plan (o al inicio del apply). Si la infraestructura consultada no existe, el plan fallará con un error. A diferencia de los recursos, Terraform no crea ni destruye nada al usar data sources.

Resource vs data source

Característicaresource {}data {}
¿Crea infra?✅ Sí — Terraform crea/gestiona el recurso❌ No — solo lee infra existente
¿Aparece en state?✅ Sí — trackea su estado en tfstate❌ No — no guarda estado (relee en cada plan)
¿Terraform puede destruirlo?✅ Sí — con destroy❌ No — nunca lo destruye
Prefijo en referenciastipo.nombre.atrib (sin prefijo)data.tipo.nombre.atrib
Cuándo usarloCuando Terraform debe ser el dueño del recursoCuando la infra ya existe y solo necesitas sus atributos
Sintaxisresource "aws_vpc" "main" {}data "aws_vpc" "existing" {}

Dependencias implícitas y explícitas

Terraform construye automáticamente un grafo de dependencias basado en las referencias entre recursos. También puedes declarar dependencias explícitas con depends_on.

# DEPENDENCIA IMPLÍCITA (recomendada)
# Terraform detecta que aws_subnet.main depende de aws_vpc.main
# porque referencia su atributo .id
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "main" {
  vpc_id     = aws_vpc.main.id     # <-- crea dependencia implícita
  cidr_block = "10.0.1.0/24"
}

# DEPENDENCIA EXPLÍCITA (usar solo cuando no hay referencia directa)
# Por ejemplo: la app depende de que la DB exista, pero no referencia ningún attr
resource "aws_db_instance" "main" {
  # ... configuración de la DB
}

resource "aws_instance" "app" {
  ami           = "ami-abc123"
  instance_type = "t3.micro"

  depends_on = [aws_db_instance.main]   # espera a que DB esté lista
}

💡 Cuándo usar depends_on

Usa depends_on solo cuando hay una dependencia real que Terraform no puede detectar automáticamente (por ejemplo, cuando un recurso necesita que otro esté listo, pero no usa ningún atributo suyo). El uso innecesario de depends_on puede hacer el plan más lento al añadir dependencias que Terraform podría paralelizar.

Meta-argumentos lifecycle

El bloque lifecycle dentro de un recurso controla cómo Terraform gestiona el ciclo de vida del recurso: creación, actualización y destrucción.

resource "aws_db_instance" "prod" {
  identifier = "prod-db"
  # ... otros argumentos

  lifecycle {
    # Evita que Terraform destruya este recurso (error si intenta hacerlo)
    prevent_destroy = true

    # Crea el nuevo recurso ANTES de destruir el viejo (zero downtime)
    create_before_destroy = true

    # Ignora cambios en estos argumentos (no genera diff en plan)
    ignore_changes = [
      engine_version,   # la DB puede auto-actualizarse sin que Terraform lo revierta
      tags["LastModified"],
    ]

    # Terraform destruye y recrea el recurso si este otro recurso cambia
    replace_triggered_by = [
      aws_launch_template.app.id,
    ]
  }
}
ArgumentoTipoEfecto
prevent_destroyboolSi true, cualquier plan que destruya el recurso generará un error. Protege recursos críticos.
create_before_destroyboolSi true, crea el reemplazo antes de destruir el actual. Requiere que el proveedor lo soporte.
ignore_changeslist(attr)Ignora cambios en los atributos listados. Usar "all" para ignorar todos (caso extremo).
replace_triggered_bylist(ref)Fuerza el reemplazo de este recurso cuando cambian los recursos/atributos referenciados.

⚠️ prevent_destroy no protege contra terraform destroy

prevent_destroy = true impide que Terraform destruya el recurso como parte de un cambio de configuración (ej: cambiar el nombre de una DB que requiere reemplazo). Sin embargo, si alguien elimina el bloque resource del código y ejecuta apply, el recurso se destruirá igualmente porque ya no existe la regla prevent_destroy.

¿Entendiste este tema?

Pon a prueba lo que acabas de aprender

Un equipo tiene una base de datos de producción definida con resource 'aws_db_instance' 'prod'. Quieren que si alguien cambia el parámetro engine_version, Terraform NO lo revierta (la DB gestiona sus propias actualizaciones de motor). ¿Qué configuración lifecycle es correcta?