Terraform Infrastructure Code en la práctica: el código y los comandos que realmente importan

Terraform Infrastructure Code: lo esencial en un artículo — código real, diagramas y pasos concretos, extractos de un curso de 38 lecciones.

Terraform Infrastructure Code en la práctica: el código y los comandos que realmente importan

Ni teoría interminable aquí: abrimos la terminal y practicamos. Aquí tienes lo esencial de Terraform Infrastructure Code, extraído directamente de un curso completo de 38 lecciones — con código real que puedes copiar y pegar ahora mismo.

tl;dr
  • Introducción a Terraform y la IaC
  • Instalación y Primeros Pasos
  • Lenguaje HCL, Providers, Variables y Recursos
  • Módulos y Organización del Código
  • State Backend Remoto y Workspaces
~$ cat ./parcours.md # Terraform Infrastructure Code — 10 capítulos
01
Introducción a Terraform y la IaC
→ Capítulo 00 – Lección 1 : ¿Por qué la IaC? ¿Por qué Terraform?→ Capítulo 00 – Lección 2 : El Ciclo de Vida de Terraform — init, plan, apply, destroy+ 1 más lecciones
02
Instalación y Primeros Pasos
→ Capítulo 01 – Lección 1 : Instalación de Terraform en Windows, Linux y macOS→ Capítulo 01 – Lección 2 : Primer Proyecto — Desplegar una Instancia EC2 en AWS+ 1 más lecciones
03
Lenguaje HCL Providers Variables y Recursos
→ Capítulo 02 – Lección 1a : Sintaxis HCL y Bloques Fundamentales→ Capítulo 02 – Lección 1b : Tipos, Expresiones y Variables Locales+ 4 más lecciones
04
Módulos y Organización del Código
→ Capítulo 03 – Lección 1 : Crear y Usar Módulos Locales→ Capítulo 03 – Lección 2 : Registro Terraform, Módulos Públicos y Versionado+ 2 más lecciones
05
State Backend Remoto y Workspaces
→ Capítulo 04 – Lección 1 : Gestión del Estado de Terraform — terraform.tfstate→ Capítulo 04 – Lección 2 : Backend Remoto — S3 + DynamoDB y Terraform Cloud+ 1 más lecciones
06
CICD Seguridad y Buenas Prácticas
→ Capítulo 05 – Lección 1a : Pipeline Terraform con GitHub Actions y OIDC→ Capítulo 05 – Lección 1b : Pipeline Terraform con Jenkins+ 3 más lecciones
07
Labs Guías Prácticas AWS
→ Capítulo 06 – Lab 01 : Sitio Estático S3 + CloudFront (Paso a Paso)→ Capítulo 06 – Lab 02 : Módulo VPC Reutilizable Multi-Entornos+ 2 más lecciones
08
Terraform con Microsoft Azure
→ Capítulo 07 – Lección 1 : Azure Fundamentos y Autenticación Terraform→ Capítulo 07 – Lección 2 : Primer Proyecto Azure — VNet, NSG y VM Linux+ 2 más lecciones
🏁
Proyecto final (+ 2 capítulos en camino)
→ Te vas con un proyecto concreto y demostrable

Capítulo 08 – Lección 2 : Primer Proyecto GCP — VPC, Firewall y Compute Engine

NOTEObjetivo — Desplegar una infraestructura GCP básica: una VPC en modo custom con subred regional, reglas de firewall (SSH + HTTP) y una instancia Compute Engine con servidor Nginx aprovisionado mediante script de inicio.

1. Requisitos previos

Antes de empezar, asegúrate de que todos los elementos siguientes estén en su lugar. Sin estos requisitos previos, el terraform apply fallará con errores de autenticación o API no activada.

1.1 Cuentas y herramientas

1.2 Credenciales GCP que debes obtener

Necesitarás esta información para configurar el provider de Terraform y autenticar las llamadas a la API:

ElementoCómo obtenerloEjemplo
Project ID (cadena corta)gcloud config get-value projectmon-projet-tf-prod
Project Number (12 dígitos)gcloud projects describe PROJECT_ID --format="value(projectNumber)"123456789012
Organization ID (opcional)gcloud organizations list987654321000
Billing Account IDgcloud billing accounts list0X0X0X-0Y0Y0Y-0Z0Z0Z
Correo electrónico de la Service AccountFormato estándar de la SA de Terraformtf-sa@PROJECT_ID.iam.gserviceaccount.com
WARNINGSeguridad crítica — NUNCA hagas commit de la clave JSON de la Service Account en Git. En producción, prefiere Workload Identity Federation (OIDC) que elimina por completo la necesidad de claves estáticas. Para desarrollo local, basta con gcloud auth application-default login.

1.3 Configurar la autenticación gcloud + ADC

Una sola vez en tu máquina: te autenticas con tu cuenta de Google, fijas el proyecto, creas una Service Account dedicada a Terraform y configuras las Application Default Credentials (ADC) que Terraform lee automáticamente.

bash
# 1. Login de usuario (abre el navegador)
gcloud auth login

# 2. Seleccionar el proyecto
gcloud config set project mon-projet-tf-prod

# 3. Crear una Service Account dedicada a Terraform
gcloud iam service-accounts create tf-sa \
    --display-name="Terraform Service Account"

# 4. Asignar el rol (Editor para los ejercicios, más restringido en prod)
gcloud projects add-iam-policy-binding mon-projet-tf-prod \
    --member="serviceAccount:tf-sa@mon-projet-tf-prod.iam.gserviceaccount.com" \
    --role="roles/editor"

# 5. ADC para desarrollo local (método recomendado para Terraform)
gcloud auth application-default login

# 6. (Alternativa CI/CD) Crear una clave JSON — sensible, ¡protegerla!
gcloud iam service-accounts keys create key.json \
    --iam-account=tf-sa@mon-projet-tf-prod.iam.gserviceaccount.com
# export GOOGLE_APPLICATION_CREDENTIALS=$PWD/key.json

# 7. Verificar
gcloud auth list
gcloud config list project

1.4 Activar las APIs de GCP requeridas

GCP requiere activar explícitamente cada servicio antes de poder utilizarlo. Para esta lección solo es estrictamente necesario Compute Engine, pero conviene activar las APIs habituales de una vez:

bash
gcloud services enable \
    compute.googleapis.com \
    cloudresourcemanager.googleapis.com \
    iam.googleapis.com \
    iap.googleapis.com

# Verificar las APIs activadas
gcloud services list --enabled

1.5 Permisos IAM mínimos

Para este ejercicio, la Service Account de Terraform debe poder crear recursos de Compute Engine y leer el proyecto. El rol roles/editor (utilizado en 1.3) cubre ampliamente la necesidad. En producción se prefieren roles más específicos como roles/compute.admin + roles/iam.serviceAccountUser (least privilege).

1.6 Clave SSH para Compute Engine

Para conectarte por SSH a la VM (fuera de IAP), GCP admite dos modos: OS Login (recomendado, autenticación mediante IAM — utilizado en esta lección) o claves SSH clásicas a través de los metadatos del proyecto. Así se genera una clave dedicada a GCP:

bash
# Generar un par de claves RSA de 4096 bits dedicado a GCP
ssh-keygen -t rsa -b 4096 -f ~/.ssh/gcp_vm -C "votre-user@gcp"

# Opción A: OS Login activado en la VM (utilizado en esta lección)
# → la clave pública se gestiona mediante IAM, nada que enviar a los metadatos

# Opción B: Añadir mediante metadatos del proyecto (clave SSH clásica)
gcloud compute project-info add-metadata \
    --metadata-from-file ssh-keys=~/.ssh/gcp_vm.pub

# Restringir los permisos de la clave privada (obligatorio)
chmod 400 ~/.ssh/gcp_vm
WARNINGClave JSON SA ≠ clave SSH — No confundas la clave JSON de la Service Account (autenticación de Terraform ante las APIs de GCP) con la clave SSH (autenticación del usuario ante la VM). La primera es extremadamente sensible: su filtración da acceso a todos los recursos del proyecto. Cifrarla siempre en reposo, rotarla periódicamente y revocarla en cuanto deje de ser necesaria.

2. Estructura del proyecto

Esta es la estructura de carpetas típica de esta lección. El código está organizado en varios archivos .tf según su responsabilidad, más un script Bash externo inyectado en la VM mediante metadata_startup_script.

bash
# Estructura recomendada para este proyecto
premier-projet-gcp/
├── versions.tf        # Configuración Terraform + provider google
├── variables.tf       # Variables de entrada (project_id, region, zone, ...)
├── main.tf            # VPC + subnet + firewall rules + VM Compute Engine
├── outputs.tf         # IP pública, comando SSH IAP, URL HTTP
├── startup-script.sh  # Script Bash ejecutado al arrancar la VM (Nginx)
├── terraform.tfvars   # Valores específicos (project_id, ...) — NO COMMITTEADO
└── .gitignore         # Excluir .tfstate, .tfvars, .terraform/, key.json

2.1 Función de cada archivo

ArchivoFunción¿Lo lee Terraform?
versions.tfBloque terraform { required_providers } + bloque provider "google"
variables.tfVariables de entrada con type, default, description
main.tfTodas las resource y data sources de GCP
outputs.tfOutputs expuestos tras apply (IP, URL, comando SSH IAP)
startup-script.shScript Bash inyectado en la VM mediante la función file()Leído por file()
terraform.tfvarsValores concretos de las variables (project_id = "...")Cargado automáticamente
.gitignoreExcluir *.tfstate, *.tfvars, .terraform/, key.jsonNo (Git)

2.2 Cómo carga Terraform los archivos

Capítulo 08 – Lección 1 : Fundamentos de GCP y Autenticación de Terraform

NOTEObjetivo — Comprender la jerarquía de GCP (Organization, Folder, Project), instalar y configurar la CLI gcloud, crear una Service Account, activar las APIs necesarias y configurar el provider google de Terraform.
TIPRequisitos previos — Haber completado los Capítulos 00 a 04. Disponer de una cuenta GCP (300 USD gratuitos durante 90 días: cloud.google.com/free).

1. Jerarquía de GCP vs AWS y Azure

NivelAWSAzureGCP
Top-levelOrganizationTenantOrganization
Contenedor intermedioOUManagement GroupFolder
Cuenta de facturaciónAccountSubscriptionProject (con Billing Account vinculada)
RegiónRegionLocationRegion (us-central1, europe-west1, northamerica-northeast1...)
ZonaAZAvailability ZoneZone (us-central1-a, -b, -c)
Identidad de servicioIAM RoleService Principal / MIService Account
WARNINGDiferencia principal — En GCP, cada recurso pertenece a un Project. El Project es la unidad fundamental de facturación, IAM y cuotas. La gran mayoría de los recursos de GCP requieren un project explícito.

2. Instalar gcloud CLI

Windows (PowerShell)

Descarga y ejecución del instalador oficial de Google Cloud SDK para Windows. Una vez lanzado, el instalador configura gcloud, gsutil y bq, y ofrece inicializar la conexión con tu cuenta de GCP.

bash
(New-Object Net.WebClient).DownloadFile("https://dl.google.com/dl/cloudsdk/channels/rapid/GoogleCloudSDKInstaller.exe", "$env:Temp\GoogleCloudSDKInstaller.exe")
& $env:Temp\GoogleCloudSDKInstaller.exe

macOS

Instalación de gcloud mediante Homebrew (el gestor de paquetes de macOS más utilizado). El cask instala el SDK completo y lo añade automáticamente al PATH.

bash
brew install --cask google-cloud-sdk

Linux (apt)

Procedimiento oficial Debian/Ubuntu: añadir el repositorio APT de Google, importar la clave GPG firmada e instalar google-cloud-cli. Este método permite beneficiarse de las actualizaciones automáticas a través de apt.

bash
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" \
    | sudo tee /etc/apt/sources.list.d/google-cloud-sdk.list

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg \
    | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg

sudo apt update && sudo apt install -y google-cloud-cli

Validación rápida de la instalación: el comando muestra las versiones del SDK, de bq (BigQuery) y gsutil (Storage). Una salida vacía indica un problema de PATH que hay que corregir antes de continuar.

bash
# Verificar
gcloud --version
# Google Cloud SDK 488.x.x
# bq 2.x.x
# gsutil 5.x.x

3. Crear y configurar un Project de GCP

Bootstrap completo de un proyecto GCP desde la CLI:

bash
# 1. Conexión (abre el navegador)
gcloud auth login

# 2. Crear un project (project_id debe ser globalmente único)
PROJECT_ID="monprojet-tf-$(date +%s)"
gcloud projects create $PROJECT_ID --name="Mon Projet Terraform"

# 3. Vincular a la billing account (obligatorio para la mayoría de recursos)
BILLING_ID=$(gcloud billing accounts list --format="value(ACCOUNT_ID)" --limit=1)
gcloud billing projects link $PROJECT_ID --billing-account=$BILLING_ID

# 4. Definir el project activo
gcloud config set project $PROJECT_ID
gcloud config set compute/region us-central1
gcloud config set compute/zone us-central1-a

# 5. Verificar
gcloud config list
# [compute]
# region = us-central1
# zone = us-central1-a
# [core]
# project = monprojet-tf-1714234567

4. Activar las APIs necesarias

WARNINGGCP exige la activación explícita de las APIs — A diferencia de AWS, donde los servicios están disponibles de inmediato, en GCP hay que activar cada API antes de usarla. Los primeros errores de Terraform casi siempre se deben a una API no activada.

Activación en lote de las APIs de GCP más habituales necesarias para Compute, Storage, IAM, Cloud SQL, Cloud Run y Secret Manager. El segundo comando (gcloud services list --enabled) permite comprobar qué está ya activado en el proyecto.

bash
# Activar las APIs habituales
gcloud services enable \
    compute.googleapis.com           `# Compute Engine` \
    storage.googleapis.com           `# Cloud Storage` \
    cloudresourcemanager.googleapis.com `# Resource Manager` \
    iam.googleapis.com               `# IAM` \
    iamcredentials.googleapis.com    `# IAM Credentials (para tokens de SA)` \
    sqladmin.googleapis.com          `# Cloud SQL Admin` \
    run.googleapis.com               `# Cloud Run` \
    secretmanager.googleapis.com     `# Secret Manager` \
    --project=$PROJECT_ID

# Listar las APIs activadas
gcloud services list --enabled --project=$PROJECT_ID

Capítulo 03 – Lección 4 : Proyecto Serverless — Lambda, API Gateway y VPC con Módulos

NOTEObjetivo — Desplegar una arquitectura serverless completa en AWS con Terraform: una VPC, una función Lambda y un API Gateway — todo organizado en módulos reutilizables. Este proyecto muestra cómo se ensamblan los módulos de Terraform para formar una infraestructura de producción.

1. Requisitos previos

Este proyecto despliega 3 módulos de Terraform que orquestan juntos una VPC, una función Lambda y un API Gateway. Antes de ejecutar terraform apply, verifica que todos los elementos siguientes estén en su lugar — de lo contrario obtendrás errores de IAM, timeouts de invocación de Lambda o errores 500 en la API.

1.1 Cuentas y herramientas

1.2 Credenciales AWS que debes obtener

Necesitarás estas 3 informaciones desde la consola de AWS para autenticar Terraform:

ElementoDónde encontrarloEjemplo
Account ID (12 dígitos)Consola AWS → arriba a la derecha, haz clic en tu nombre → Mi cuenta123456789012
Access Key IDIAM → Users → tu usuario → Security credentials → Create access keyAKIAIOSFODNN7EXAMPLE
Secret Access KeySe muestra UNA SOLA VEZ al crearla (si no, crea una nueva clave)wJalrXUt...EXAMPLEKEY
WARNINGSeguridad crítica — NUNCA hagas commit de estas claves en Git. Configúralas siempre mediante aws configure (almacenadas en ~/.aws/credentials) o variables de entorno. Añade *.tfvars, *.tfstate*, .terraform/ y dist/ a tu .gitignore.

1.3 Configurar la autenticación de AWS CLI

Una sola vez en tu máquina: ejecuta aws configure y pega tus claves. Se crea el archivo ~/.aws/credentials y Terraform lo leerá automáticamente (el provider AWS y el provider archive no necesitan ningún token específico).

bash
aws configure
# AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
# AWS Secret Access Key [None]: wJalrXUt...EXAMPLEKEY
# Default region name [None]: ca-central-1
# Default output format [None]: json

# Verificar que funciona
aws sts get-caller-identity
# {
#   "UserId": "AIDA...EXAMPLE",
#   "Account": "123456789012",        ← Tu Account ID
#   "Arn": "arn:aws:iam::123456789012:user/tu-usuario"
# }

1.4 Permisos IAM mínimos

El usuario (o rol) utilizado debe poder crear Lambda, API Gateway, IAM (roles de ejecución), VPC y CloudWatch Logs. Para este ejercicio, adjunta las siguientes políticas gestionadas al usuario IAM:

Política gestionada de AWSPor qué
AWSLambda_FullAccessCrear/modificar la función Lambda y los aws_lambda_permission
AmazonAPIGatewayAdministratorCrear la REST API, los métodos, las integraciones y el despliegue
IAMFullAccessCrear el rol de ejecución de Lambda y adjuntar las políticas
AmazonVPCFullAccessCrear la VPC, las subredes y el Security Group del módulo vpc
CloudWatchLogsFullAccessCrear el aws_cloudwatch_log_group de la Lambda
TIPEn producción — Se restringirán estos permisos según el principio de least privilege (ver Capítulo 05). Para una cuenta de aprendizaje, PowerUserAccess + IAMFullAccess también es suficiente.

1.5 Código fuente de Lambda

El módulo data "archive_file" (utilizado en el main.tf raíz) comprime automáticamente tu código Python en cada plan. Debes crear la carpeta de origen antes del primer terraform plan, de lo contrario Terraform fallará con « source_dir does not exist »:

bash
# Crear la estructura esperada por data "archive_file"
mkdir -p src/lambda
touch src/lambda/index.py        # El contenido se verá en la sección 8

# No se necesita SSH/.pem aquí — Lambda se invoca mediante API Gateway, no por SSH
NOTEDiferencia con EC2 — A diferencia del proyecto EC2 del Capítulo 01, este laboratorio no requiere ningún par de claves SSH. Lambda es un servicio gestionado: se despliega código y AWS se encarga del servidor.

2. Estructura del proyecto

Esta es la estructura completa del proyecto, pensada para la modularidad. El main.tf raíz actúa como director de orquesta: instancia los 3 módulos y conecta sus outputs/inputs. Cada módulo dentro de modules/ es autosuficiente (tiene sus propios variables.tf y outputs.tf) y podría reutilizarse en otro proyecto.

bash
# Estructura completa del proyecto serverless
project-serverless/
├── providers.tf               # Versiones de Terraform + provider AWS + archive
├── variables.tf               # Variables globales (project_name, environment, region)
├── main.tf                    # Orquestación: llamadas a module.vpc, module.lambda, module.api_gateway
├── outputs.tf                 # Outputs raíz (api_url, lambda_name, lambda_arn)
├── terraform.tfvars           # Valores concretos (NO COMMITTEADO)
├── .gitignore                 # *.tfstate, *.tfvars, .terraform/, dist/
├── README.md
│
├── src/
│   └── lambda/
│       └── index.py           # Código Python de la Lambda
│
├── dist/                      # ZIP generado por data "archive_file" (NO COMMITTEADO)
│   └── lambda.zip
│
├── environments/              # Valores específicos por entorno
│   ├── dev.tfvars
│   └── prod.tfvars
│
└── modules/
    ├── vpc/                   # Módulo de red reutilizable
    │   ├── main.tf            # aws_vpc, aws_subnet, aws_security_group
    │   ├── variables.tf       # prefix, cidr, environment
    │   └── outputs.tf         # vpc_id, private_subnets, lambda_sg_id
    │
    ├── lambda/                # Módulo de función Lambda + IAM
    │   ├── main.tf            # aws_lambda_function, aws_cloudwatch_log_group
    │   ├── iam.tf             # Rol de ejecución + adjuntos de políticas
    │   ├── variables.tf       # function_name, runtime, handler, vpc_id...
    │   └── outputs.tf         # function_name, function_arn, invoke_arn
    │
    └── api_gateway/           # Módulo de API REST
        ├── main.tf            # aws_api_gateway_rest_api, methods, deployment
        ├── variables.tf       # api_name, lambda_arn, lambda_name
        └── outputs.tf         # api_id, api_url, stage

2.1 Función de cada archivo

ArchivoFunciónNivel
providers.tfVersiones de Terraform + providers (aws, archive)Raíz
variables.tfVariables globales compartidas entre todos los módulosRaíz
main.tf (raíz)Instancia los módulos y pasa los outputs de uno como inputs de otroRaíz
outputs.tf (raíz)Vuelve a exponer los outputs de los módulos a nivel de proyecto (ej. api_url)Raíz
modules/<m>/main.tfLógica de negocio del módulo (recursos AWS)Módulo
modules/<m>/variables.tfInterfaz pública del módulo — lo que un consumidor puede configurarMódulo
modules/<m>/outputs.tfValores expuestos por el módulo (consumibles por la raíz u otro módulo)Módulo
src/lambda/index.pyCódigo de aplicación Python — comprimido automáticamente por data "archive_file"App
environments/*.tfvarsValores concretos por entorno (pasados mediante -var-file)Config

2.2 Cómo carga Terraform los archivos — NO existe un "punto de entrada"

NOTEConcepto clave — Terraform no lee main.tf primero. Fusiona automáticamente TODOS los archivos .tf de la carpeta actual en un único conjunto. Los nombres main.tf, iam.tf, variables.tf son una convención, no una obligación técnica. En el módulo lambda/, separar iam.tf de main.tf mejora la legibilidad — para Terraform es estrictamente equivalente a un único archivo grande.
va-plus-loin

Este artículo cubre los extractos más útiles — el curso completo Terraform Infrastructure Code (10 capítulos, 38 lecciones, ejercicios corregidos y proyecto final) te lleva hasta el final.

./acceder-al-curso-completo curso gratuito: Dominar Claude Code

FAQ

¿Cuánto tiempo se necesita para aprender Terraform Infrastructure Code?
Con una progresión estructurada (10 capítulos, 38 lecciones cortas y prácticas), se alcanza un nivel operativo en unas semanas dedicando 30 a 60 minutos al día. Lo importante es practicar cada concepto de inmediato.
¿Se necesitan requisitos previos?
Es mejor estar cómodo con los fundamentos del dominio: este contenido profundiza, con casos reales.
¿Por dónde empezar concretamente?
Reproduce los comandos de este artículo y sigue el curso completo Terraform Infrastructure Code: encadena las 38 lecciones en orden, con ejercicios y proyecto final.

📬 ¿Quieres recibir este tipo de guía cada semana? Suscríbete gratis — código real, cero palabrería.