provision-infrastructure-terraform
About
This skill provisions and manages cloud infrastructure using Terraform with HCL modules, remote state backends, and plan/apply workflows. It implements infrastructure-as-code patterns for team collaboration, including state locking and output management. Use it for provisioning new cloud resources, migrating from ClickOps/CloudFormation to declarative IaC, or managing multi-environment infrastructure with reusable modules.
Quick Install
Claude Code
Recommendednpx skills add pjt222/agent-almanac -a claude-code/plugin add https://github.com/pjt222/agent-almanacgit clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/provision-infrastructure-terraformCopy and paste this command in Claude Code to install this skill
Documentation
name: provision-infrastructure-terraform description: > Provisiona y gestiona infraestructura en la nube usando Terraform con módulos HCL, backends de estado remoto, espacios de trabajo y flujo de trabajo plan/apply. Implementa patrones de infraestructura como código con gestión de variables, valores de salida y bloqueo de estado para colaboración en equipo. Útil al aprovisionar nueva infraestructura en la nube, migrar de ClickOps o CloudFormation a IaC declarativa, gestionar infraestructura multientorno, versionar cambios de infraestructura junto al código de aplicación, o aplicar estándares mediante módulos reutilizables. locale: es source_locale: en source_commit: 6f65f316 translator: claude-opus-4-6 translation_date: 2026-03-16 license: MIT allowed-tools: Read Write Edit Bash Grep Glob metadata: author: Philipp Thoss version: "1.0" domain: devops complexity: advanced language: multi tags: terraform, iac, infrastructure, hcl, state-management
Aprovisionar Infraestructura con Terraform
Implementa infraestructura como código usando Terraform para aprovisionar, versionar y gestionar recursos en la nube en AWS, Azure, GCP y otros proveedores.
Cuándo Usar
- Al aprovisionar nueva infraestructura en la nube (VPCs, cómputo, almacenamiento, bases de datos)
- Al migrar de ClickOps o CloudFormation a IaC declarativa
- Al gestionar infraestructura multientorno (dev, staging, producción)
- Al implementar patrones de infraestructura reproducibles entre equipos
- Al versionar cambios de infraestructura junto al código de aplicación
- Al aplicar estándares de infraestructura mediante módulos reutilizables
Entradas
- Requerido: CLI de Terraform instalado (
terraform --version) - Requerido: Credenciales del proveedor de nube (cuentas de servicio AWS, Azure, GCP)
- Requerido: Configuración del backend de estado remoto (S3, Azure Storage, Terraform Cloud)
- Opcional: Infraestructura existente para importar o migrar
- Opcional: Terraform Cloud/Enterprise para colaboración en equipo
- Opcional: Hooks de pre-commit para validación y formateo
Procedimiento
Consulta Ejemplos Extendidos para archivos de configuración completos y plantillas.
Paso 1: Inicializar la Estructura del Proyecto Terraform
Crea una estructura de directorios organizada con configuración del backend y configuración del proveedor.
# Create project structure
mkdir -p terraform/{modules,environments/{dev,staging,prod}}
cd terraform
# Create backend configuration
cat > backend.tf <<'EOF'
terraform {
required_version = ">= 1.6"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "my-terraform-state"
key = "infrastructure/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-lock"
# Workspace-specific state files
workspace_key_prefix = "env"
}
}
provider "aws" {
region = var.aws_region
default_tags {
tags = {
ManagedBy = "Terraform"
Environment = terraform.workspace
Project = var.project_name
}
}
}
EOF
# Create variables file
cat > variables.tf <<'EOF'
variable "aws_region" {
description = "AWS region for resources"
type = string
default = "us-east-1"
}
variable "project_name" {
description = "Project name for resource naming and tagging"
type = string
validation {
condition = length(var.project_name) > 0 && length(var.project_name) <= 32
error_message = "Project name must be 1-32 characters"
}
}
variable "environment" {
description = "Environment name (dev, staging, prod)"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod"
}
}
EOF
# Initialize Terraform
terraform init
Esperado: Terraform se inicializa exitosamente, descarga plugins del proveedor, configura el backend remoto. El directorio .terraform/ se crea con los binarios del proveedor. Se verifica la conexión al backend de estado.
En caso de fallo: Si la inicialización del backend falla, verifica que el bucket S3 existe y que los permisos IAM permiten s3:GetObject, s3:PutObject, dynamodb:GetItem, dynamodb:PutItem. Para fallos de descarga del proveedor, comprueba la conectividad de red y la configuración de proxy corporativo. Ejecuta terraform init -upgrade para actualizar los proveedores.
Paso 2: Crear Módulos de Infraestructura Reutilizables
Construye módulos componibles para VPC, cómputo e infraestructura de datos con validación de entradas.
# modules/vpc/main.tf
variable "vpc_cidr" {
description = "CIDR block for VPC"
type = string
default = "10.0.0.0/16"
}
variable "availability_zones" {
description = "List of AZs to use"
type = list(string)
}
variable "project_name" {
description = "Project name for resource naming"
type = string
}
variable "environment" {
description = "Environment name"
type = string
}
locals {
common_tags = {
Project = var.project_name
Environment = var.environment
Module = "vpc"
}
}
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = merge(local.common_tags, {
Name = "${var.project_name}-${var.environment}-vpc"
})
}
resource "aws_subnet" "public" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index)
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true
tags = merge(local.common_tags, {
Name = "${var.project_name}-${var.environment}-public-${var.availability_zones[count.index]}"
Type = "public"
})
}
resource "aws_subnet" "private" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index + 100)
availability_zone = var.availability_zones[count.index]
tags = merge(local.common_tags, {
Name = "${var.project_name}-${var.environment}-private-${var.availability_zones[count.index]}"
Type = "private"
})
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = merge(local.common_tags, {
Name = "${var.project_name}-${var.environment}-igw"
})
}
resource "aws_eip" "nat" {
count = length(var.availability_zones)
domain = "vpc"
tags = merge(local.common_tags, {
Name = "${var.project_name}-${var.environment}-nat-eip-${var.availability_zones[count.index]}"
})
depends_on = [aws_internet_gateway.main]
}
resource "aws_nat_gateway" "main" {
count = length(var.availability_zones)
allocation_id = aws_eip.nat[count.index].id
subnet_id = aws_subnet.public[count.index].id
tags = merge(local.common_tags, {
Name = "${var.project_name}-${var.environment}-nat-${var.availability_zones[count.index]}"
})
depends_on = [aws_internet_gateway.main]
}
# modules/vpc/outputs.tf
output "vpc_id" {
description = "VPC ID"
value = aws_vpc.main.id
}
output "public_subnet_ids" {
description = "List of public subnet IDs"
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
description = "List of private subnet IDs"
value = aws_subnet.private[*].id
}
output "nat_gateway_ips" {
description = "List of NAT Gateway public IPs"
value = aws_eip.nat[*].public_ip
}
Esperado: El módulo crea una VPC con subredes públicas/privadas en múltiples AZs, una puerta de enlace de internet y puertas de enlace NAT con EIPs. Los valores de salida exponen los IDs de recursos para módulos descendentes.
En caso de fallo: Para errores de superposición de CIDR, ajusta el cálculo de cidrsubnet() o valida que el CIDR de la VPC no entre en conflicto con redes existentes. Para errores de dependencia, verifica que los bloques depends_on garantizan el orden correcto de creación de recursos. Usa terraform graph | dot -Tpng > graph.png para visualizar las dependencias.
Paso 3: Implementar Configuraciones Específicas por Entorno
Crea espacios de trabajo de entorno con anulaciones de variables y fuentes de datos.
# environments/prod/main.tf
terraform {
required_version = ">= 1.6"
}
# Import shared backend and provider config
# ... (see EXAMPLES.md for complete configuration)
Esperado: La configuración específica del entorno crea infraestructura de tamaño productivo con 3 AZs, tipos de instancias más grandes y configuraciones de seguridad de producción. Las fuentes de datos resuelven la última AMI. Los archivos de plantilla se renderizan con variables de entorno.
En caso de fallo: Para errores de espacio de trabajo, crea el espacio de trabajo con terraform workspace new prod. Para fallos de fuente de datos, verifica que las credenciales AWS tengan permisos ec2:DescribeImages. Para errores de renderizado de plantillas, valida que los tipos de variables coincidan con las expectativas de la plantilla.
Paso 4: Ejecutar el Flujo de Trabajo Plan y Apply
Ejecuta el plan de Terraform, revisa los cambios y aplica con flujo de aprobación.
# Format code
terraform fmt -recursive
# Validate configuration
terraform validate
# ... (see EXAMPLES.md for complete configuration)
Para integración automatizada de CI/CD:
# .github/workflows/terraform.yml
name: Terraform
on:
pull_request:
paths:
# ... (see EXAMPLES.md for complete configuration)
Esperado: El plan muestra adiciones/cambios/eliminaciones de recursos. No se detecta desvío. Apply crea/actualiza recursos sin errores. Las salidas contienen los valores esperados. El flujo de trabajo CI comenta el plan en los PRs y aplica automáticamente en fusiones a la rama main.
En caso de fallo: Para fallos del plan, ejecuta terraform validate para detectar errores de sintaxis. Para errores de bloqueo de estado, identifica al titular del bloqueo con aws dynamodb get-item --table-name terraform-lock --key '{"LockID":{"S":"terraform-state-bucket/key"}}' y fuerza el desbloqueo si está obsoleto. Para fallos de apply, comprueba los registros de CloudWatch para errores específicos del proveedor. Usa terraform show para inspeccionar el estado actual.
Paso 5: Gestionar el Estado e Implementar Detección de Desvío
Configura el bloqueo de estado, la copia de seguridad y la detección automatizada de desvío.
# Create DynamoDB table for state locking
cat > state-backend.tf <<'EOF'
resource "aws_dynamodb_table" "terraform_lock" {
name = "terraform-lock"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
# ... (see EXAMPLES.md for complete configuration)
Para detección automatizada de desvío:
# Create drift detection script
cat > scripts/detect-drift.sh <<'EOF'
#!/bin/bash
set -euo pipefail
cd terraform
# ... (see EXAMPLES.md for complete configuration)
Esperado: El backend de estado configurado con versionado y cifrado. La detección de desvío identifica cambios fuera de banda. Las operaciones de estado (list, show, mv, import) se ejecutan sin errores. Las verificaciones automáticas de desvío se ejecutan según programación y envían alertas.
En caso de fallo: Para tiempos de espera de bloqueo de estado, verifica que la tabla DynamoDB existe y tiene el esquema de clave correcto. Para problemas de versionado, comprueba el estado del versionado del bucket S3 con aws s3api get-bucket-versioning --bucket bucket-name. Para fallos de importación, verifica que el recurso existe y que la configuración de Terraform coincide con los atributos reales del recurso.
Paso 6: Implementar Pruebas y Documentación de Módulos
Agrega pruebas automatizadas con Terratest y genera documentación.
// test/vpc_test.go
package test
import (
"testing"
# ... (see EXAMPLES.md for complete configuration)
Generar documentación:
# Install terraform-docs
go install github.com/terraform-docs/terraform-docs@latest
# Generate module documentation
terraform-docs markdown table modules/vpc > modules/vpc/README.md
# ... (see EXAMPLES.md for complete configuration)
Esperado: Terratest valida que el módulo crea los recursos esperados con la configuración correcta. La documentación se genera automáticamente a partir de descripciones de variables y definiciones de salidas. Los hooks de pre-commit aplican el formateo y la validación antes de los commits.
En caso de fallo: Para fallos de Terratest, verifica las credenciales AWS y las cuotas. Para pruebas de larga duración, implementa ejecución paralela con t.Parallel(). Para errores de generación de documentación, verifica que todas las variables tienen atributos description. Para fallos de pre-commit, ejecuta terraform fmt manualmente y corrige los errores de validación.
Validación
- Backend configurado con cifrado, versionado y bloqueo de estado
- Todos los módulos tienen validación de entradas y valores de salida
- Los espacios de trabajo aíslan el estado específico del entorno
-
terraform planno muestra cambios inesperados después del apply - La detección de desvío se ejecuta automáticamente y alerta sobre cambios
- Los módulos se prueban con Terratest o un marco similar
- La documentación se genera automáticamente y se mantiene actualizada
- Los secretos se gestionan a través de AWS Secrets Manager, no codificados
- La estimación de costos está integrada (Infracost o similar)
- El radio de explosión se minimiza con estado separado por entorno
Errores Comunes
-
Valores codificados: Evita codificar IDs de AMI, AZs o valores específicos de cuenta. Usa fuentes de datos y variables.
-
Bloques lifecycle faltantes: Los recursos se recrean inesperadamente. Agrega
lifecycle { create_before_destroy = true }para prevenir tiempo de inactividad durante las actualizaciones. -
Sin bloqueo de estado: Los applies concurrentes corrompen el estado. Siempre usa una tabla DynamoDB para el bloqueo con el backend S3.
-
IAM demasiado permisivo: La cuenta de servicio de Terraform tiene acceso de administrador completo. Implementa políticas de mínimo privilegio limitadas a los recursos gestionados.
-
Sin restricciones de versión: Las actualizaciones del proveedor rompen la infraestructura. Fija las versiones del proveedor con restricciones
version = "~> 5.0". -
Secretos en el estado: Los valores sensibles se almacenan en texto plano en el archivo de estado. Usa
sensitive = trueen las salidas, almacena los secretos en AWS Secrets Manager y referencialos mediante fuentes de datos. -
Sin estrategia de copia de seguridad: El archivo de estado se pierde o corrompe sin un plan de recuperación. Habilita el versionado S3, implementa copias de seguridad regulares del estado y prueba los procedimientos de recuperación.
-
Configuración monolítica: Un único archivo de estado gestiona toda la infraestructura. Divídelo en límites lógicos (redes, cómputo, datos) para reducir el radio de explosión.
Habilidades Relacionadas
configure-git-repository- Control de versiones para código Terraformbuild-ci-cd-pipeline- Flujos de trabajo automatizados de Terraform con GitHub Actionsimplement-gitops-workflow- Integración de ArgoCD/Flux con Terraformmanage-kubernetes-secrets- Gestión de secretos en clústeres aprovisionados por Terraformdeploy-to-kubernetes- Uso del proveedor Kubernetes de Terraform
GitHub Repository
Related Skills
executing-plans
DesignUse the executing-plans skill when you have a complete implementation plan to execute in controlled batches with review checkpoints. It loads and critically reviews the plan, then executes tasks in small batches (default 3 tasks) while reporting progress between each batch for architect review. This ensures systematic implementation with built-in quality control checkpoints.
requesting-code-review
DesignThis skill dispatches a code-reviewer subagent to analyze code changes against requirements before proceeding. It should be used after completing tasks, implementing major features, or before merging to main. The review helps catch issues early by comparing the current implementation with the original plan.
connect-mcp-server
DesignThis skill provides a comprehensive guide for developers to connect MCP servers to Claude Code using HTTP, stdio, or SSE transports. It covers installation, configuration, authentication, and security for integrating external services like GitHub, Notion, and custom APIs. Use it when setting up MCP integrations, configuring external tools, or working with Claude's Model Context Protocol.
web-cli-teleport
DesignThis skill helps developers choose between Claude Code Web and CLI interfaces based on task analysis, then enables seamless session teleportation between these environments. It optimizes workflow by managing session state and context when switching between web, CLI, or mobile. Use it for complex projects requiring different tools at various stages.
