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
validationpara 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 duranteapply. - 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
- Definir al menos una variable con tipo, descripción y valor por defecto en un archivo
variables.tf. - Usar variables en recursos de Terraform, por ejemplo, en un
aws_instanceoaws_s3_bucket. - Crear un archivo
outputs.tfque exponga al menos dos atributos de recursos desplegados. - Aplicar validaciones a variables para restringir valores aceptables.
- Ejecutar
terraform applypasando valores de variables mediante un archivo.tfvars. - Consumir outputs de un módulo en otro módulo o en la configuración root.
- 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:
- Crea una carpeta llamada
s3-modulecon los archivosvariables.tf,main.tf, youtputs.tf. - 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.
- En
main.tf, usa las variables para crear un recursoaws_s3_bucketcon las siguientes propiedades:- Nombre del bucket: use
var.bucket_namecon un sufijo del entorno, por ejemplo,${var.bucket_name}-${var.environment}. - Habilitar versioning basado en
var.versioning_enabled. - Agregar tags que incluyan el entorno.
- Nombre del bucket: use
- En
outputs.tf, define dos outputs:bucket_arn: el ARN del bucket creado.bucket_domain_name: el nombre de dominio del bucket.
- Desde una configuración root, llama a este módulo pasando valores para las variables y ejecuta
terraform applypara desplegarlo.
- 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
versioningdentro deaws_s3_bucketcon un bloque dinámico basado en el valor booleano. - Puedes probar el módulo creando un archivo
main.tfen otra carpeta que usemodulepara referenciars3-module.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.