Terraform para laboratorios reproducibles
Artículo 1 de 7
14%
completado
Terraform y OpenTofu para laboratorios reproducibles
Base práctica para Terraform y OpenTofu en labs cloud: providers, state, plan, módulos, costos y teardown seguro.
Un laboratorio cloud tiene dos enemigos silenciosos: la configuración manual y el recurso olvidado.
Terraform y OpenTofu atacan ambos, siempre que los usemos con disciplina. No son “el botón mágico de infraestructura”. Son una forma de declarar intención, revisar cambios y repetir un entorno sin rezarle a la memoria.
Terraform define el state como el vínculo entre la configuración y los objetos remotos; OpenTofu conserva el mismo ciclo de escribir, planear y aplicar como contrato operativo. [1] [2]
Piensa en Bash como la capa que valida y orquesta; Terraform/OpenTofu describe y aplica infraestructura. La guía de scripting complementaria permanece en revisión y no es requisito para comenzar esta serie.
Objetivo
Diseñar un flujo mínimo para labs de infraestructura que puedas planificar, aplicar, verificar y destruir sin depender de pasos manuales invisibles. El resultado esperado no es “usar Terraform porque sí”, sino tener un ciclo auditable para crear recursos pequeños y cerrarlos a tiempo.
Prerrequisitos
- Terraform u OpenTofu instalado localmente.
- Credenciales cloud explícitas y acotadas al lab.
- Backend de state decidido: local para pruebas personales, remoto para trabajo colaborativo.
- Un presupuesto o límite de gasto definido antes de aplicar.
- Capacidad útil, pero no obligatoria: leer y adaptar un script Bash pequeño.
Puente al lab reproducible
La lectura desemboca en el Terraform lab network. La primera iteración no usa credenciales ni ejecuta apply: valida una allowlist de recursos, ausencia de ingress público, techo de costo y teardown declarado. Esa frontera es intencional. Primero se demuestra que el plan es revisable; después se conecta un provider real.
La evidencia mínima del lab es el JSON de guardrails. Si una futura variante crea recursos, debe sumar plan guardado, costo estimado, outputs verificables y salida de destroy.
Terraform, OpenTofu y la idea central
La idea es simple:
Modelo mental: código declarativo + estado + provider = infraestructura reproducible.
Ciclo mínimo
La evidencia de un lab IaC
Un bloque resource describe una pieza de infraestructura. El provider sabe cómo hablar con AWS, Cloudflare, GitHub u otro sistema. El state recuerda qué existe y cómo se relaciona con el código.
resource "aws_s3_bucket" "lab" {
bucket = "trautslab-lab-${var.suffix}"
}La referencia del bloque resource define el contrato declarativo que el provider interpreta; no es solo sintaxis de ejemplo. [3]
Parece pequeño, pero ahí empieza la diferencia: el bucket ya no vive como memoria tribal; vive como artefacto revisable.
El state es el contrato, no un archivo cualquiera
El terraform.tfstate u homólogo en OpenTofu no es basura generada. Es el mapa entre tu código y la realidad.
Regla de oro:
- local state para laboratorios personales y efímeros;
- remote state para trabajo colaborativo;
- nunca commitear state con secretos o identificadores sensibles;
- nunca editar state a mano salvo cirugía explícita.
En un lab local:
.terraform/
*.tfstate
*.tfstate.backupOjo: en una configuración raíz, incluida la de un laboratorio, .terraform.lock.hcl se versiona para revisar la selección y los checksums de providers. No pertenece al mismo grupo que el state ni contiene la infraestructura observada. Una biblioteca de módulos reutilizables puede dejar la selección final al root consumidor, pero este lab es una configuración ejecutable y conserva su lockfile. [4]
Flujo mínimo de laboratorio
terraform init
terraform fmt -check
terraform validate
terraform plan -out tfplan
terraform apply tfplan
terraform destroyEl plan es el momento donde el humano sigue mandando. Si no entiendes el plan, no apliques. Así de poco glamoroso, así de sano.
Estructura recomendada
labs/
terraform/
s3-minimal/
main.tf
variables.tf
outputs.tf
versions.tf
README.mdversions.tf:
terraform {
required_version = ">= 1.6.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}variables.tf:
variable "region" {
description = "AWS region for the lab."
type = string
default = "us-east-1"
}
variable "suffix" {
description = "Unique suffix to avoid bucket name collisions."
type = string
}main.tf:
provider "aws" {
region = var.region
}
resource "aws_s3_bucket" "lab" {
bucket = "trautslab-${var.suffix}"
tags = {
Project = "TrautsLab"
Lab = "s3-minimal"
}
}outputs.tf:
output "bucket_name" {
value = aws_s3_bucket.lab.bucket
}El wrapper Bash sigue siendo útil
Terraform no reemplaza el preflight. Antes de correr plan, valida contexto.
#!/usr/bin/env bash
set -Eeuo pipefail
LAB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../labs/terraform/s3-minimal" && pwd)"
command -v terraform >/dev/null || {
echo "Falta terraform u opentofu en PATH"
exit 1
}
[[ -n "${AWS_PROFILE:-}" ]] || {
echo "Define AWS_PROFILE antes de ejecutar el lab"
exit 1
}
cd "${LAB_DIR}"
terraform init
terraform fmt -check
terraform validate
terraform plan -out tfplanEl wrapper no decide infraestructura. Solo prepara una pista limpia.
Módulos: no empieces por ahí
Los módulos son útiles cuando ya repetiste un patrón dos o tres veces. Antes de eso, pueden esconder malas decisiones detrás de una interfaz bonita.
Empieza plano:
main.tf
variables.tf
outputs.tfLuego extrae:
modules/
s3-lab-bucket/Un buen módulo tiene pocas variables, outputs claros y nombres aburridos.
Cost guardrails
Todo lab debe responder:
- ¿qué crea?;
- ¿cuánto podría costar?;
- ¿cómo se destruye?;
- ¿qué pasa si falla a mitad?;
- ¿qué nombres/tags deja para encontrar recursos?
Tags mínimos:
locals {
common_tags = {
Project = "TrautsLab"
Owner = "lab"
TTL = "24h"
}
}No todos los servicios respetan tags igual, pero etiquetar es el inicio de una salida digna.
Terraform vs OpenTofu
Para TrautsLab, la regla será práctica:
- escribir HCL portable cuando sea razonable;
- no depender de features raras sin explicar por qué;
- nombrar el runtime usado en cada lab;
- validar comandos con el binario real (
terraformutofu).
En los posts podemos mostrar Terraform como lenguaje común y mencionar OpenTofu cuando el flujo aplica igual. Si una diferencia importa, se documenta ahí mismo. Nada de “es lo mismo” con la mano en el aire.
Cuándo no usarlo
No uses Terraform/OpenTofu para:
- scripts de una sola ejecución sin estado;
- cambios que requieren lógica imperativa compleja;
- datos transaccionales;
- operaciones que debes ejecutar muchas veces por minuto;
- esconder una arquitectura que todavía no entiendes.
Para eso existen Bash, SDKs, pipelines o aplicaciones. Cada herramienta con su sombrero; si no, terminamos con una navaja suiza intentando hacer café.
Validar el lab
Antes de publicar o compartir un lab IaC, valida cuatro señales:
terraform fmt -check
terraform validate
terraform plan -out tfplan
terraform show -no-color tfplanCriterios de aceptación:
- el plan no crea recursos fuera del alcance declarado;
- los nombres incluyen prefijo/sufijo de lab para evitar colisiones;
- los outputs permiten ejecutar un smoke test;
- el README explica cómo correr
destroy; - el costo esperado está escrito, aunque sea aproximado.
Fuentes útiles
- Terraform resource block reference
- Terraform state documentation
- OpenTofu provider documentation
- CloudFormation e IaC en TrautsLab
Conexiones dentro de la serie
- Después: State, backends y locking.
- Ruta completa: continúa con módulos, providers, testing, CI/CD y recuperación operacional antes de convertir estos fundamentos en automatización de producción.
Cierre
Terraform/OpenTofu no nos interesa por “automatizar clicks”. Nos interesa porque convierte laboratorios en artefactos revisables: código, plan, estado, teardown y evidencia.
El estándar TrautsLab será ese: si un lab crea algo, también debe explicar cómo lo valida y cómo lo borra. La nube perdona poco; la factura, menos.
Bibliografía académica
- [1]
HashiCorp, "State," Terraform Language Documentation.
Propósito y protección del state.
- [2]
OpenTofu, "Working with OpenTofu."
Write–Plan–Apply para individuos y equipos.
- [3]
HashiCorp, "Resource block reference," Terraform Language Documentation.
Semántica de recursos declarados.
- [4]
HashiCorp, "Dependency Lock File," Terraform Language Documentation.
Selección y checksums de providers revisables en el root module.
Rutas vecinas
Si este tema te abrió hambre, sigue por aquí.
Series y labs que comparten área o dependen de esta ruta. Pocas opciones, para no convertir la curiosidad en menú infinito.
Labs para convertir lectura en práctica
Sigue leyendo
Ideas conectadas con este artículo
Una ruta corta para continuar sin abrir veinte pestañas y perder el hilo.
Módulos Terraform: composición, contratos y límites que sí explican
Diseño de módulos Terraform/OpenTofu como contratos: inputs, outputs, providers, invariantes, compatibilidad y composición sin cajas negras.
Terraform state: backends, locking y recuperación sin superstición
Cómo razonar sobre state, backends y locking en Terraform/OpenTofu: invariantes, múltiples escritores, fallos parciales y recuperación verificable.
Testing IaC: del HCL válido al plan que una política puede aprobar
Capas de prueba para Terraform/OpenTofu: formato, validación, tests, planes guardados, políticas y evidencia sin crear infraestructura por accidente.
Terraform en CI/CD: planes revisables y credenciales que caducan
Arquitectura segura de CI/CD para Terraform/OpenTofu: plan de PR, apply protegido, OIDC, credenciales efímeras, concurrencia y artefactos sensibles.