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.
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.
- 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
Capítulo 08 – Lección 2 : Primer Proyecto GCP — VPC, Firewall y Compute Engine
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:
| Elemento | Cómo obtenerlo | Ejemplo |
|---|---|---|
| Project ID (cadena corta) | gcloud config get-value project | mon-projet-tf-prod |
| Project Number (12 dígitos) | gcloud projects describe PROJECT_ID --format="value(projectNumber)" | 123456789012 |
| Organization ID (opcional) | gcloud organizations list | 987654321000 |
| Billing Account ID | gcloud billing accounts list | 0X0X0X-0Y0Y0Y-0Z0Z0Z |
| Correo electrónico de la Service Account | Formato estándar de la SA de Terraform | tf-sa@PROJECT_ID.iam.gserviceaccount.com |
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.
# 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 project1.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:
gcloud services enable \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
iam.googleapis.com \
iap.googleapis.com
# Verificar las APIs activadas
gcloud services list --enabled1.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:
# 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_vm2. 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.
# 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
| Archivo | Función | ¿Lo lee Terraform? |
|---|---|---|
versions.tf | Bloque terraform { required_providers } + bloque provider "google" | Sí |
variables.tf | Variables de entrada con type, default, description | Sí |
main.tf | Todas las resource y data sources de GCP | Sí |
outputs.tf | Outputs expuestos tras apply (IP, URL, comando SSH IAP) | Sí |
startup-script.sh | Script Bash inyectado en la VM mediante la función file() | Leído por file() |
terraform.tfvars | Valores concretos de las variables (project_id = "...") | Cargado automáticamente |
.gitignore | Excluir *.tfstate, *.tfvars, .terraform/, key.json | No (Git) |
2.2 Cómo carga Terraform los archivos
Capítulo 08 – Lección 1 : Fundamentos de GCP y Autenticación de Terraform
gcloud, crear una Service Account, activar las APIs necesarias y configurar el provider google de Terraform.1. Jerarquía de GCP vs AWS y Azure
| Nivel | AWS | Azure | GCP |
|---|---|---|---|
| Top-level | Organization | Tenant | Organization |
| Contenedor intermedio | OU | Management Group | Folder |
| Cuenta de facturación | Account | Subscription | Project (con Billing Account vinculada) |
| Región | Region | Location | Region (us-central1, europe-west1, northamerica-northeast1...) |
| Zona | AZ | Availability Zone | Zone (us-central1-a, -b, -c) |
| Identidad de servicio | IAM Role | Service Principal / MI | Service Account |
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.
(New-Object Net.WebClient).DownloadFile("https://dl.google.com/dl/cloudsdk/channels/rapid/GoogleCloudSDKInstaller.exe", "$env:Temp\GoogleCloudSDKInstaller.exe")
& $env:Temp\GoogleCloudSDKInstaller.exemacOS
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.
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.
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-cliValidació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.
# 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:
# 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
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.
# 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_IDCapítulo 03 – Lección 4 : Proyecto Serverless — Lambda, API Gateway y VPC con Módulos
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:
| Elemento | Dónde encontrarlo | Ejemplo |
|---|---|---|
| Account ID (12 dígitos) | Consola AWS → arriba a la derecha, haz clic en tu nombre → Mi cuenta | 123456789012 |
| Access Key ID | IAM → Users → tu usuario → Security credentials → Create access key | AKIAIOSFODNN7EXAMPLE |
| Secret Access Key | Se muestra UNA SOLA VEZ al crearla (si no, crea una nueva clave) | wJalrXUt...EXAMPLEKEY |
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).
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 AWS | Por qué |
|---|---|
AWSLambda_FullAccess | Crear/modificar la función Lambda y los aws_lambda_permission |
AmazonAPIGatewayAdministrator | Crear la REST API, los métodos, las integraciones y el despliegue |
IAMFullAccess | Crear el rol de ejecución de Lambda y adjuntar las políticas |
AmazonVPCFullAccess | Crear la VPC, las subredes y el Security Group del módulo vpc |
CloudWatchLogsFullAccess | Crear el aws_cloudwatch_log_group de la Lambda |
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 »:
# 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
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.
# 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, stage2.1 Función de cada archivo
| Archivo | Función | Nivel |
|---|---|---|
providers.tf | Versiones de Terraform + providers (aws, archive) | Raíz |
variables.tf | Variables globales compartidas entre todos los módulos | Raíz |
main.tf (raíz) | Instancia los módulos y pasa los outputs de uno como inputs de otro | Raí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.tf | Lógica de negocio del módulo (recursos AWS) | Módulo |
modules/<m>/variables.tf | Interfaz pública del módulo — lo que un consumidor puede configurar | Módulo |
modules/<m>/outputs.tf | Valores expuestos por el módulo (consumibles por la raíz u otro módulo) | Módulo |
src/lambda/index.py | Código de aplicación Python — comprimido automáticamente por data "archive_file" | App |
environments/*.tfvars | Valores concretos por entorno (pasados mediante -var-file) | Config |
2.2 Cómo carga Terraform los archivos — NO existe un "punto de entrada"
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.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 CodeFAQ
¿Cuánto tiempo se necesita para aprender Terraform Infrastructure Code?
¿Se necesitan requisitos previos?
¿Por dónde empezar concretamente?
📬 ¿Quieres recibir este tipo de guía cada semana? Suscríbete gratis — código real, cero palabrería.