Terraform Associate

Deep Dive

D4 · Configuración de Terraform

Variables, locals y outputs

Las variables hacen los módulos parametrizables y reutilizables. Los outputs exponen valores hacia afuera. Los locals son valores intermedios calculados. Dominar su precedencia y comportamiento es clave para el examen.

Bloque variable: tipos y validación

# Declaración completa de una variable
variable "instance_type" {
  type        = string              # tipo de dato
  default     = "t3.micro"          # valor por defecto (hace la variable opcional)
  description = "Tipo de instancia EC2"  # documentación
  sensitive   = false               # si true, oculta el valor en los logs

  validation {
    condition     = contains(["t3.micro", "t3.small", "t3.medium"], var.instance_type)
    error_message = "instance_type debe ser t3.micro, t3.small o t3.medium."
  }
}

# Variable sin default (OBLIGATORIA — Terraform preguntará el valor)
variable "db_password" {
  type      = string
  sensitive = true
  description = "Contraseña de la base de datos"
}

# Variable con tipo complejo
variable "allowed_cidrs" {
  type    = list(string)
  default = ["10.0.0.0/8", "172.16.0.0/12"]
}

variable "tags" {
  type = map(string)
  default = {
    Environment = "dev"
    Team        = "platform"
  }
}

💡 Validación con condition

El bloque validation dentro de una variable permite validar el valor antes de que Terraform ejecute el plan. La condition debe ser una expresión booleana que use var.nombre. Si evalúa a false, Terraform muestra el error_message.

Métodos de asignación y precedencia

Terraform evalúa las variables en orden de precedencia. Los métodos de mayor número en la lista sobrescriben a los anteriores.

1 (más baja)

Valor default en el bloque variable {}

default = "us-east-1"

2

Archivo terraform.tfvars

aws_region = "us-west-2"

3

Archivo *.auto.tfvars (orden alfabético)

prod.auto.tfvars — se carga automáticamente

4

Variables de entorno TF_VAR_nombre

export TF_VAR_aws_region="eu-west-1"

5

Flag -var-file=archivo.tfvars

terraform plan -var-file=prod.tfvars

6 (más alta)

Flag -var="clave=valor"

terraform plan -var="aws_region=ap-southeast-1"

# terraform.tfvars — se carga automáticamente si existe en el directorio
aws_region    = "us-east-1"
instance_type = "t3.small"
db_password   = "super-secret"    # ⚠️ no commitear si tiene secretos

# prod.auto.tfvars — se carga automáticamente (por el .auto.)
environment = "prod"
instance_type = "t3.large"       # sobrescribe terraform.tfvars

# Referencia en código: var.nombre_variable
resource "aws_instance" "web" {
  instance_type = var.instance_type
  ami           = var.ami_id
}

🎯 Para el examen: la pregunta de precedencia

El examen suele preguntar: "Si la variable X está definida como default, en terraform.tfvars y con -var, ¿qué valor se usa?". La respuesta es -var (la mayor precedencia). Memoriza el orden: default → tfvars → auto.tfvars → TF_VAR → -var-file → -var.

Variables sensitive y estado

El atributo sensitive = true en una variable le indica a Terraform que oculte su valor en la salida del CLI (plan, apply). Sin embargo, tiene limitaciones importantes.

✅ Qué SÍ hace sensitive = true

  • • Oculta el valor en la salida de plan: muestra (sensitive value)
  • • Oculta el valor en la salida de apply
  • • Si lo usas en un output, el output hereda sensitive automáticamente
  • • Previene exposición accidental en logs de CI/CD

⚠️ Qué NO hace sensitive = true

  • NO cifra el valor en terraform.tfstate — aparece en texto plano
  • • No cifra el valor en el backend
  • • No impide que Terraform use el valor
  • • Para secretos reales, usa un backend remoto con cifrado (S3+KMS, HCP Terraform)
variable "db_password" {
  type      = string
  sensitive = true
}

# En el plan verás:
# + db_password = (sensitive value)  ← valor oculto en CLI

# PERO en terraform.tfstate verás:
# "db_password": "mi-password-secreto"  ← en texto plano ⚠️

# Por eso se recomienda:
# 1. Usar backend remoto con cifrado (S3 + KMS o HCP Terraform)
# 2. Recuperar secretos de Vault/Secrets Manager en tiempo de ejecución

Valores efímeros (ephemeral) — Terraform 1.10+

Los valores efímeros son valores que Terraform utiliza en memoria durante el plan/apply pero no persiste en el state ni en los logs. Diseñados para manejar secretos reales (contraseñas, tokens) de forma segura.

# Variable efímera — no se escribe en el state
variable "db_password" {
  type      = string
  ephemeral = true    # nuevo en Terraform 1.10+
}

# Ephemeral resource — datos que no persisten en state
ephemeral "aws_secretsmanager_secret_version" "db_creds" {
  secret_id = "prod/db/password"
}

# Argument write-only — acepta valor efímero en un recurso
resource "aws_db_instance" "main" {
  identifier = "prod-db"
  engine     = "postgres"
  password   = ephemeral.aws_secretsmanager_secret_version.db_creds.secret_string
  # password tiene write_only = true: se envía a la API pero no se guarda en state
}

variable ephemeral

Valor de entrada que no se guarda en state. Ideal para passwords y tokens que solo se necesitan durante el apply.

ephemeral resource

Bloque ephemeral {} para datos externos (Vault, Secrets Manager) cuyo valor no debe persistir en state.

write-only argument

Atributo de recurso que Terraform envía a la API del proveedor pero no almacena en el state ni muestra en el plan.

🎯 Para el examen (004)

  • sensitive = true oculta el valor en la salida del CLI pero sigue guardándose en el state
  • ephemeral = true (Terraform 1.10+) hace que el valor no se persista en el state en absoluto — seguridad real para secrets
  • • Los ephemeral resources pueden usarse con proveedores de secretos (Vault, AWS Secrets Manager)

Bloque output

Los outputs exponen valores del módulo al exterior: al usuario (se muestran en el apply), al módulo padre (accesibles como module.nombre.output), y como datos del estado (accesibles via terraform output).

# Declaración de outputs
output "vpc_id" {
  value       = aws_vpc.main.id
  description = "ID de la VPC principal"
}

output "db_endpoint" {
  value       = aws_db_instance.main.endpoint
  description = "Endpoint de conexión a la base de datos"
  sensitive   = true           # oculto en CLI, pero disponible para módulos padres
}

output "subnet_ids" {
  value       = aws_subnet.public[*].id   # lista de IDs con splat expression
  description = "IDs de las subnets públicas"
}

# Acceso desde módulo padre:
# module.networking.vpc_id
# module.networking.subnet_ids

# Acceso desde CLI:
# terraform output vpc_id
# terraform output -json
ArgumentoRequeridoDescripción
value✅ SíLa expresión cuyo resultado se expone como output
description❌ NoDocumentación del output (buena práctica, recomendado siempre)
sensitive❌ NoSi true, oculta el valor en CLI. Se hereda si value referencia una variable sensitive.
depends_on❌ NoDeclara dependencias explícitas cuando el valor no las tiene implícitas

Bloque locals

Los locals son valores calculados dentro del módulo que puedes reutilizar en múltiples lugares. A diferencia de las variables, no pueden ser sobreescritos desde fuera del módulo.

# Bloque locals (plural: el bloque se llama "locals")
locals {
  # Combinar variables para crear un nombre estándar
  name_prefix = "${var.project}-${var.environment}"

  # Tags comunes aplicados a todos los recursos
  common_tags = {
    Project     = var.project
    Environment = var.environment
    ManagedBy   = "terraform"
    Owner       = var.team
  }

  # Cálculo complejo
  is_production = var.environment == "prod"
  instance_type = local.is_production ? "t3.large" : "t3.micro"
}

# Acceso: local.nombre (singular: "local")
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  tags = merge(local.common_tags, {
    Name = "${local.name_prefix}-vpc"
  })
}
Característicavariable {}locals {}
¿Configurable desde fuera?✅ Sí — eso es su propósito❌ No — son internos al módulo
¿Puede contener expresiones?Solo en default y validation✅ Sí — cualquier expresión HCL
Prefijo de accesovar.nombrelocal.nombre (singular)
Bloque de declaraciónvariable "nombre" {}locals {} (único bloque con varias claves)
Cuándo usarParámetro que el usuario defineValor derivado/calculado interno del módulo

¿Entendiste este tema?

Pon a prueba lo que acabas de aprender

Un ingeniero define una variable db_password con sensitive = true y la usa como argumento en un recurso aws_db_instance. Después ejecuta terraform apply con éxito. ¿Dónde aparecerá la contraseña en texto plano?