lección 11
Terraform: infraestructura como código
Instalar Terraform, HCL, plan/apply/destroy, módulos, variables, outputs y gestión de state. Define tu infraestructura AWS en archivos versionables.
⏱ 60 min
Has estado creando buckets S3, roles IAM y funciones Lambda con boto3. Funciona, pero tiene un problema fundamental: no tienes una "fuente de verdad" de tu infraestructura. Si alguien entra a la consola de AWS y cambia algo manualmente, tu código ya no refleja la realidad. Y si necesitas recrear todo el entorno desde cero (nuevo proyecto, nuevo entorno de staging, disaster recovery), no tienes un botón mágico que lo haga.
Terraform resuelve esto. Es una herramienta que te permite DECLARAR tu infraestructura en archivos de texto (HCL — HashiCorp Configuration Language), y Terraform se encarga de CREAR, MODIFICAR o DESTRUIR los recursos para que la realidad coincida con tu declaración. Es como tener un plano del edificio: si el plano dice "3 pisos", Terraform construye 3 pisos. Si cambias el plano a "5 pisos", Terraform añade los 2 que faltan sin tocar los existentes.
### Instalar Terraform
1# 🟦 Windows (PowerShell)2# Opción 1: Con Chocolatey3choco install terraform45# Opción 2: Descarga directa de HashiCorp6# https://developer.hashicorp.com/terraform/downloads → Windows AMD647# Extraer el .zip y añadir la carpeta al PATH89# Verificar:10terraform --version11# Terraform v1.7.x
Instalación en Windows — Chocolatey es el método más rápido
1# 🍎 Mac (Terminal)2brew install terraform34# Verificar:5terraform --version6# Terraform v1.7.x
Instalación en Mac — una línea con Homebrew
### HCL: el lenguaje de Terraform
HCL es declarativo: describes el ESTADO DESEADO, no los pasos para llegar. Si dices "quiero un bucket S3 llamado X", Terraform comprueba si ya existe. Si existe, no hace nada. Si no existe, lo crea. Si existe pero con configuración diferente, lo modifica. Esta idempotencia es clave.
1# main.tf — tu primer archivo Terraform2# Configurar el provider AWS apuntando a LocalStack3terraform {4 required_providers {5 aws = {6 source = "hashicorp/aws"7 version = "~> 5.0"8 }9 }10}1112provider "aws" {13 region = "eu-west-1"14 access_key = "test"15 secret_key = "test"16 s3_use_path_style = true17 skip_credentials_validation = true18 skip_metadata_api_check = true19 skip_requesting_account_id = true2021 endpoints {22 s3 = "http://localhost:4566"23 iam = "http://localhost:4566"24 lambda = "http://localhost:4566"25 stepfunctions = "http://localhost:4566"26 glue = "http://localhost:4566"27 }28}2930# Crear un bucket S3 para el data lake31resource "aws_s3_bucket" "datalake" {32 bucket = "fashionstore-datalake-tf"33}3435# Crear role IAM para Glue36resource "aws_iam_role" "glue_role" {37 name = "glue-etl-role-tf"38 assume_role_policy = jsonencode({39 Version = "2012-10-17"40 Statement = [{41 Action = "sts:AssumeRole"42 Effect = "Allow"43 Principal = { Service = "glue.amazonaws.com" }44 }]45 })46}
main.tf — provider configurado para LocalStack + recursos declarativos
### El flujo de trabajo: init → plan → apply
1# 1. Inicializar (descarga el provider AWS)2terraform init34# 2. Ver qué VA A HACER (dry run — no toca nada)5terraform plan6# Plan: 2 to add, 0 to change, 0 to destroy.78# 3. Aplicar los cambios (CREA los recursos)9terraform apply10# Apply complete! Resources: 2 added, 0 changed, 0 destroyed.1112# 4. Ver el estado actual13terraform show1415# 5. Destruir TODO (cuidado en producción!)16terraform destroy
Siempre: plan ANTES de apply. Nunca apliques sin revisar el plan primero.
### Variables y outputs: hacer tu código reutilizable
1# variables.tf — parámetros configurables2variable "environment" {3 description = "Entorno: dev, staging, prod"4 type = string5 default = "dev"6}78variable "bucket_name" {9 description = "Nombre del bucket del data lake"10 type = string11}1213variable "enable_versioning" {14 description = "Activar versionado en el bucket"15 type = bool16 default = true17}1819# Uso en main.tf:20resource "aws_s3_bucket" "datalake" {21 bucket = "${var.environment}-${var.bucket_name}"22}2324# outputs.tf — valores que puedes consultar después25output "bucket_arn" {26 value = aws_s3_bucket.datalake.arn27 description = "ARN del bucket del data lake"28}2930output "glue_role_arn" {31 value = aws_iam_role.glue_role.arn32}
Variables hacen tu código reutilizable — el mismo tf sirve para dev, staging y prod
### Módulos: organizar infraestructura compleja
Cuando tu infraestructura crece, un solo main.tf se vuelve inmanejable. Los módulos son "paquetes" de Terraform reutilizables. Piensa en ellos como funciones: defines un módulo "datalake" que crea bucket + lifecycle + versioning, y lo usas en cada entorno con parámetros diferentes.
1# Estructura de módulos:2# terraform/3# ├── main.tf (orquesta módulos)4# ├── variables.tf5# ├── outputs.tf6# └── modules/7# ├── datalake/8# │ ├── main.tf9# │ ├── variables.tf10# │ └── outputs.tf11# └── iam/12# ├── main.tf13# ├── variables.tf14# └── outputs.tf1516# En main.tf principal:17module "datalake" {18 source = "./modules/datalake"19 environment = var.environment20 bucket_name = "fashionstore-datalake"21}2223module "iam" {24 source = "./modules/iam"25 environment = var.environment26 bucket_arn = module.datalake.bucket_arn # Output de otro módulo27}
Módulos = componentes reutilizables. El main.tf solo los conecta.
### State: la memoria de Terraform
Terraform guarda el estado actual de tu infraestructura en un archivo terraform.tfstate. Este archivo es CRÍTICO: si lo pierdes, Terraform no sabe qué recursos ya existen y podría intentar crear duplicados. En equipo, el state debe estar en un backend remoto (S3 + DynamoDB para locking) para que todos compartan el mismo estado.
Consejo de senior: NUNCA commitees terraform.tfstate a Git. Contiene datos sensibles (ARNs, IDs, a veces secrets). Usa un backend S3 con encriptación y versionado. Añade *.tfstate y *.tfstate.backup a tu .gitignore desde el día uno.
terraform destroy borra TODOS los recursos gestionados por ese archivo de estado. En producción, un destroy accidental puede borrar tu data lake completo con todos los datos. Usa prevent_destroy lifecycle rules en recursos críticos y protege el acceso al comando destroy con IAM policies.
Consejo de senior: el patrón de carpetas que he visto funcionar mejor en equipos de datos es: terraform/{entorno}/main.tf. Cada entorno (dev, staging, prod) tiene su propio directorio con su propio state. Así puedes hacer "terraform apply" en dev sin riesgo de tocar prod. Los módulos se comparten entre entornos.
## ejercicios
Escribir tu primer archivo Terraform
Escribe un main.tf que cree un bucket S3, un role IAM para Glue, y la policy que conecta ambos. Genera el contenido del archivo como string Python.
Crear módulo Terraform reutilizable
Diseña un módulo Terraform para data lake que acepte variables y pueda usarse en dev, staging y prod con diferentes configuraciones.
Configuración multi-entorno con Terraform
Genera la configuración para usar el módulo datalake en tres entornos (dev, staging, prod) con diferentes parámetros.
Importar recursos existentes a Terraform
Un bucket fue creado manualmente. Genera el comando terraform import y el bloque resource necesario para que Terraform lo gestione sin recrearlo.
Regístrate para guardar tu progreso.
## comentarios
Reporta erratas, ayuda a otros o comparte tu opinión. Sé constructivo.
Inicia sesión para comentar y responder.
cargando comentarios...