Uso de Variables y Outputs para Configuraciones Dinámicas

Lectura
20 min~5 min lectura

Concepto clave

Las variables y outputs en Terraform son mecanismos fundamentales para crear configuraciones dinámicas y reutilizables. Piensa en las variables como los parámetros ajustables de una receta: en lugar de tener una receta fija para "pastel de chocolate", tienes una plantilla donde puedes especificar el tipo de harina, la cantidad de azúcar o el tipo de chocolate. Los outputs son como la etiqueta nutricional final del pastel: información valiosa que quieres extraer después de la preparación, como las calorías totales o los ingredientes utilizados.

En el contexto de DevOps, las variables te permiten crear un mismo módulo de infraestructura que puede desplegarse en diferentes entornos (desarrollo, staging, producción) simplemente cambiando valores como el tamaño de instancia o el prefijo de nombres. Los outputs te permiten exponer información crítica, como la IP pública de un balanceador de carga o el endpoint de una base de datos, que otros sistemas o equipos pueden consumir. Sin estas herramientas, estarías escribiendo código duplicado para cada variación, lo que va en contra de los principios de IaC.

Cómo funciona en la práctica

El flujo de trabajo típico involucra tres archivos principales: variables.tf (donde defines las variables), main.tf (donde usas esas variables en tus recursos), y outputs.tf (donde defines qué información quieres exportar). Terraform procesa estos archivos en un orden lógico: primero lee las definiciones de variables, luego aplica valores (ya sea desde archivos .tfvars, variables de entorno o prompts interactivos), ejecuta la configuración en main.tf, y finalmente calcula y muestra los outputs.

Por ejemplo, imagina que estás desplegando una instancia EC2 en AWS. En variables.tf, defines una variable para el tipo de instancia. En main.tf, usas var.instance_type para especificar ese tipo en el recurso aws_instance. Al ejecutar terraform apply, puedes pasar un valor como t2.micro para desarrollo o m5.large para producción. Después del despliegue, en outputs.tf, defines un output para la IP pública de la instancia, que puedes usar para conectarte o integrar con otros sistemas.

Codigo en accion

Veamos un ejemplo completo. Primero, el antes: un archivo main.tf con valores hardcodeados que no es reutilizable.

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  tags = {
    Name = "mi-instancia-fija"
  }
}

Ahora, el despues: una configuración dinámica usando variables y outputs.

# variables.tf
variable "instance_type" {
  description = "Tipo de instancia EC2"
  type        = string
  default     = "t2.micro"
}

variable "environment" {
  description = "Entorno (dev, staging, prod)"
  type        = string
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "El valor debe ser dev, staging o prod."
  }
}

# main.tf
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = var.instance_type
  tags = {
    Name        = "web-${var.environment}"
    Environment = var.environment
  }
}

# outputs.tf
output "instance_id" {
  description = "ID de la instancia EC2 creada"
  value       = aws_instance.web.id
}

output "public_ip" {
  description = "IP pública de la instancia"
  value       = aws_instance.web.public_ip
  sensitive   = false
}

Errores comunes

  • No validar variables: Definir variables sin validación puede llevar a valores incorrectos. Usa bloques validation para restringir entradas, como asegurar que un tamaño de disco sea mayor a 10 GB.
  • Exponer información sensible en outputs: Mostrar contraseñas o claves en outputs sin marcarlas como sensitive = true. Terraform ocultará estos valores en la salida, pero aún estarán en el estado; considera usar secret managers como AWS Secrets Manager.
  • Confusión entre default y required: Si una variable tiene un valor default, no es obligatoria; si no tiene default, debes proporcionar un valor. Planifica según tu caso de uso para evitar errores durante apply.
  • No usar outputs para integraciones: Olvidar definir outputs para recursos que otros módulos o sistemas necesitan, como el ARN de un rol IAM, lo que fuerza a extraer manualmente desde el estado.
  • Hardcodear valores en múltiples lugares: Repetir el mismo valor (como una región de AWS) en varios recursos en lugar de definirlo una vez en una variable y reutilizarlo.

Checklist de dominio

  1. Definir al menos una variable con tipo, descripción y valor por defecto en un archivo variables.tf.
  2. Usar variables en recursos de Terraform, por ejemplo, en un aws_instance o aws_s3_bucket.
  3. Crear un archivo outputs.tf que exponga al menos dos atributos de recursos desplegados.
  4. Aplicar validaciones a variables para restringir valores aceptables.
  5. Ejecutar terraform apply pasando valores de variables mediante un archivo .tfvars.
  6. Consumir outputs de un módulo en otro módulo o en la configuración root.
  7. Marcar outputs sensibles apropiadamente para evitar fugas de información.

Crear un módulo reutilizable para un bucket S3 con variables y outputs

En este ejercicio, crearás un módulo de Terraform para un bucket S3 en AWS que use variables para hacerlo dinámico y outputs para exponer información útil. Sigue estos pasos:

  1. Crea una carpeta llamada s3-module con los archivos variables.tf, main.tf, y outputs.tf.
  2. En variables.tf, define tres variables:
    • bucket_name: tipo string, sin valor por defecto, con una descripción.
    • environment: tipo string, con valor por defecto "dev", y una validación que acepte solo "dev", "staging", o "prod".
    • versioning_enabled: tipo bool, con valor por defecto false.
  3. En main.tf, usa las variables para crear un recurso aws_s3_bucket con las siguientes propiedades:
    • Nombre del bucket: use var.bucket_name con un sufijo del entorno, por ejemplo, ${var.bucket_name}-${var.environment}.
    • Habilitar versioning basado en var.versioning_enabled.
    • Agregar tags que incluyan el entorno.
  4. En outputs.tf, define dos outputs:
    • bucket_arn: el ARN del bucket creado.
    • bucket_domain_name: el nombre de dominio del bucket.
  5. Desde una configuración root, llama a este módulo pasando valores para las variables y ejecuta terraform apply para desplegarlo.
Pistas
  • Recuerda que los nombres de buckets S3 deben ser únicos globalmente; considera agregar un identificador aleatorio o usar tu cuenta de AWS.
  • Usa el argumento versioning dentro de aws_s3_bucket con un bloque dinámico basado en el valor booleano.
  • Puedes probar el módulo creando un archivo main.tf en otra carpeta que use module para referenciar s3-module.

Evalua tu comprension

Completa el quiz interactivo de arriba para ganar XP.