Guía para gestionar infraestructura en AWS con Terraform

RESUMEN

[DevOps & Cloud] Cómo gestionar infraestructura en AWS con Terraform: Guía completa para 2026

Aprende a automatizar y provisionar tu infraestructura en Amazon Web Services (AWS) utilizando Terraform.

Keywords: Terraform, AWS, Infraestructura como Código

ÍNDICE

1. Introducción a la Infraestructura como Código y Terraform en AWS

2. Fundamentos de Terraform para AWS: Primeros Pasos

3. Conceptos Avanzados de Terraform para Escalabilidad y Reusabilidad

4. Gestión de Recursos AWS Comunes con Terraform

5. Resolución de Problemas Comunes y Mejores Prácticas

6. Aplicación Práctica: Despliegue de una Aplicación Web en AWS con Terraform

7. Conclusión y Perspectivas Futuras

CONTEXTO

Introducción a la Infraestructura como Código y Terraform en AWS

En el dinámico panorama de la tecnología de 2026, la gestión eficiente de la infraestructura en la nube se ha vuelto más crítica que nunca. La Infraestructura como Código (IaC) ha emergido como una metodología fundamental para automatizar el aprovisionamiento, la configuración y la gestión de la infraestructura, transformando la forma en que los equipos de DevOps interactúan con entornos complejos como Amazon Web Services (AWS).

Tradicionalmente, la configuración manual de servidores, bases de datos y redes era un proceso propenso a errores, lento y difícil de escalar. Con IaC, la infraestructura se define en archivos de configuración que pueden versionarse, revisarse y desplegarse de manera consistente, al igual que el código de una aplicación. Esto no solo reduce la posibilidad de errores humanos, sino que también acelera los ciclos de despliegue, mejora la colaboración entre equipos y garantiza la reproducibilidad de los entornos.

Dentro del ecosistema IaC, Terraform de HashiCorp se ha consolidado como una herramienta líder, especialmente para infraestructuras multi-cloud y, de manera destacada, para AWS. Su enfoque declarativo permite a los ingenieros especificar el estado deseado de su infraestructura, y Terraform se encarga de realizar los pasos necesarios para alcanzar ese estado. Esto significa que, en lugar de escribir scripts imperativos que dictan «cómo» hacer algo, los equipos se concentran en «qué» infraestructura quieren tener.

La combinación de Terraform y AWS ofrece una potente sinergia. AWS proporciona una vasta gama de servicios de infraestructura escalables y flexibles, mientras que Terraform ofrece un marco unificado para orquestar y gestionar estos servicios de manera programática. Desde el aprovisionamiento de máquinas virtuales EC2 y bases de datos RDS hasta la configuración de redes VPC complejas y servicios sin servidor como Lambda, Terraform simplifica enormemente la administración de la nube. Esta guía exhaustiva te llevará a través de los pasos esenciales para dominar Terraform en AWS en 2026, preparándote para construir y gestionar infraestructuras robustas y automatizadas.

PUNTO CLAVE

La Infraestructura como Código (IaC) con Terraform es esencial en 2026 para la automatización y gestión consistente de entornos AWS, reduciendo errores y acelerando los despliegues.

CONTENIDO PRINCIPAL

Fundamentos de Terraform para AWS: Primeros Pasos

Para comenzar a gestionar tu infraestructura AWS con Terraform, es fundamental entender los conceptos básicos y configurar tu entorno de desarrollo. Terraform utiliza un lenguaje de configuración llamado HashiCorp Configuration Language (HCL), que es declarativo y fácil de leer. Primero, necesitarás instalar Terraform y configurar tus credenciales de AWS.

Instalación de Terraform y Configuración de AWS CLI

La instalación de Terraform es sencilla y multiplataforma. Puedes descargar el binario directamente desde el sitio web de HashiCorp o usar un gestor de paquetes. Para macOS, por ejemplo, se usa Homebrew:

EXPLICACIÓN DEL CÓDIGO

Este comando instala Terraform en sistemas macOS usando Homebrew.

brew tap hashicorp/tap
brew install hashicorp/tap/terraform

Para interactuar con AWS, necesitarás el AWS Command Line Interface (CLI) configurado. Asegúrate de tener una cuenta de AWS activa y credenciales de usuario IAM con los permisos adecuados. Configura el CLI ejecutando aws configure y proporcionando tu Access Key ID, Secret Access Key, región por defecto y formato de salida.

EXPLICACIÓN DEL CÓDIGO

Ejemplo de configuración del AWS CLI, solicitando credenciales y región. Es crucial usar las credenciales de un usuario IAM con permisos mínimos necesarios.

$ aws configure
AWS Access Key ID [****************ABCD]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [****************ABCD]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [us-east-1]: eu-west-1
Default output format [json]: json

Creando tu Primer Recurso AWS con Terraform: Un S3 Bucket

Creemos un simple bucket de S3. Crea un archivo llamado main.tf en un directorio vacío.

EXPLICACIÓN DEL CÓDIGO

Este bloque de código define el proveedor de AWS y un bucket de S3 con una política de bloqueo de acceso público, un estándar de seguridad recomendado en 2026.

# main.tf
provider "aws" {
  region = "eu-west-1"
}

resource "aws_s3_bucket" "mi_bucket_ejemplo" {
  bucket = "kwonsejo-mi-bucket-ejemplo-2026" # Los nombres de bucket deben ser globalmente únicos
}

resource "aws_s3_bucket_acl" "mi_bucket_ejemplo_acl" {
  bucket = aws_s3_bucket.mi_bucket_ejemplo.id
  acl    = "private"
}

resource "aws_s3_bucket_public_access_block" "mi_bucket_ejemplo_public_access_block" {
  bucket = aws_s3_bucket.mi_bucket_ejemplo.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

output "bucket_name" {
  description = "El nombre del bucket S3 creado."
  value       = aws_s3_bucket.mi_bucket_ejemplo.bucket
}

output "bucket_arn" {
  description = "El ARN del bucket S3 creado."
  value       = aws_s3_bucket.mi_bucket_ejemplo.arn
}

El Ciclo de Vida de Terraform: Init, Plan, Apply

Una vez que tienes tu archivo main.tf, sigue estos pasos:

1

Inicializar Terraform

Ejecuta terraform init. Esto descarga los plugins del proveedor de AWS necesarios para interactuar con sus servicios y configura el backend.

2

Planificar el Despliegue

Ejecuta terraform plan. Este comando genera un plan de ejecución que muestra qué acciones (crear, modificar, destruir) realizará Terraform para alcanzar el estado deseado. Es crucial revisar este plan para evitar sorpresas.

3

Aplicar los Cambios

Ejecuta terraform apply. Terraform te pedirá confirmación antes de ejecutar el plan. Una vez confirmado, creará el bucket de S3 en tu cuenta de AWS.

4

Destruir la Infraestructura

Para eliminar los recursos creados, ejecuta terraform destroy. Esto eliminará todos los recursos gestionados por este archivo main.tf, lo que es útil para entornos de prueba o para limpiar recursos no deseados.

Diagrama del flujo de trabajo de Terraform: init, plan, apply, destroy y gestión del archivo de estado

PUNTO CLAVE

El ciclo de vida de Terraform (init, plan, apply) es fundamental para una gestión controlada y predecible de la infraestructura en AWS. Siempre revisa el plan antes de apply.

CONTENIDO PRINCIPAL

Conceptos Avanzados de Terraform para Escalabilidad y Reusabilidad

Para construir infraestructuras complejas y mantenibles, es crucial ir más allá de los conceptos básicos. Terraform ofrece varias características avanzadas que promueven la modularidad, la reusabilidad y la colaboración en equipos grandes.

Variables, Outputs y Data Sources

Las variables permiten parametrizar tus configuraciones, haciendo que tus módulos sean más flexibles y reusables. Los outputs exponen información sobre los recursos creados, que puede ser consumida por otros módulos o por el usuario final. Los data sources permiten a Terraform leer información de recursos existentes en AWS que no fueron creados por Terraform.

EXPLICACIÓN DEL CÓDIGO

Este ejemplo muestra cómo definir una variable para la región de AWS, usarla en el proveedor y luego exponer el ARN del bucket como una salida. También se usa un data source para obtener información sobre las zonas de disponibilidad de AWS.

# variables.tf
variable "aws_region" {
  description = "La región de AWS donde se desplegarán los recursos."
  type        = string
  default     = "eu-west-1"
}

# main.tf (modificado)
provider "aws" {
  region = var.aws_region
}

resource "aws_s3_bucket" "mi_bucket_ejemplo" {
  bucket = "kwonsejo-mi-bucket-ejemplo-con-var-2026"
}

data "aws_availability_zones" "disponibles" {
  state = "available"
}

output "bucket_id_con_var" {
  description = "El ID del bucket S3 creado usando una variable."
  value       = aws_s3_bucket.mi_bucket_ejemplo.id
}

output "available_azs" {
  description = "Zonas de disponibilidad disponibles en la región."
  value       = data.aws_availability_zones.disponibles.names
}

Módulos: La Clave de la Reusabilidad

Los módulos son la forma en que Terraform organiza y reutiliza el código. Permiten encapsular un conjunto de recursos relacionados en una unidad lógica que puede ser instanciada múltiples veces con diferentes parámetros. Esto es ideal para componentes comunes como VPCs, grupos de seguridad o configuraciones de bases de datos.

Puedes crear tus propios módulos locales o utilizar módulos de registro públicos, como los del Terraform Registry, que ofrecen soluciones predefinidas y bien probadas para una amplia gama de servicios AWS.

EXPLICACIÓN DEL CÓDIGO

Este ejemplo muestra cómo se define y se consume un módulo local simple para crear un bucket S3. La estructura de directorios sería ./modules/s3_bucket/main.tf y luego se llama desde el root.

# modules/s3_bucket/main.tf
resource "aws_s3_bucket" "this" {
  bucket = var.bucket_name
}

resource "aws_s3_bucket_acl" "this" {
  bucket = aws_s3_bucket.this.id
  acl    = "private"
}

resource "aws_s3_bucket_public_access_block" "this" {
  bucket = aws_s3_bucket.this.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

output "bucket_id" {
  value = aws_s3_bucket.this.id
}

output "bucket_arn" {
  value = aws_s3_bucket.this.arn
}

# modules/s3_bucket/variables.tf
variable "bucket_name" {
  description = "Nombre único del bucket S3."
  type        = string
}

# root/main.tf
provider "aws" {
  region = "eu-west-1"
}

module "app_bucket" {
  source      = "./modules/s3_bucket"
  bucket_name = "kwonsejo-app-bucket-2026"
}

module "logs_bucket" {
  source      = "./modules/s3_bucket"
  bucket_name = "kwonsejo-logs-bucket-2026"
}

output "app_bucket_arn" {
  value = module.app_bucket.bucket_arn
}

Gestión de Estados Remotos y Workspaces

El archivo de estado de Terraform (terraform.tfstate) es crucial, ya que mapea los recursos reales de la nube con tu configuración. En un entorno de equipo o de producción, almacenar este archivo localmente es arriesgado. Se recomienda usar un backend remoto, como un bucket S3 de AWS, para almacenar el estado de forma segura y habilitar el bloqueo de estado para evitar conflictos.

EXPLICACIÓN DEL CÓDIGO

Configuración de un backend S3 para el estado de Terraform. Es crucial tener un bucket S3 ya creado para este propósito, preferiblemente con versionado habilitado y cifrado. También se recomienda un DynamoDB para el bloqueo de estado.

# backend.tf (o main.tf)
terraform {
  backend "s3" {
    bucket         = "kwonsejo-terraform-state-2026" # Asegúrate de que este bucket exista
    key            = "path/to/my/app/terraform.tfstate"
    region         = "eu-west-1"
    encrypt        = true
    dynamodb_table = "kwonsejo-terraform-locks-2026" # Asegúrate de que esta tabla DynamoDB exista
  }
}

Los workspaces de Terraform (terraform workspace) permiten gestionar múltiples instancias de la misma configuración, por ejemplo, para entornos de desarrollo, staging y producción. Cada workspace tiene su propio archivo de estado, lo que permite mantenerlos aislados.

EXPLICACIÓN DEL CÓDIGO

Estos comandos muestran cómo crear, seleccionar y listar workspaces. Esto es ideal para entornos como dev, staging y prod.

# Crear un nuevo workspace
terraform workspace new dev

# Listar los workspaces existentes
terraform workspace list

# Seleccionar un workspace
terraform workspace select prod

Diagrama mostrando el archivo de estado de Terraform almacenado en un bucket S3 con DynamoDB para el bloqueo

PUNTO CLAVE

La modularización con modules, la parametrización con variables y la gestión de estados remotos con backends son pilares para construir infraestructuras AWS escalables y colaborativas con Terraform.

CONTENIDO PRINCIPAL

Gestión de Recursos AWS Comunes con Terraform

Terraform es capaz de gestionar prácticamente cualquier servicio de AWS. Aquí cubriremos algunos de los recursos más utilizados y cómo definirlos en HCL.

Redes: VPC, Subredes y Grupos de Seguridad

Una Virtual Private Cloud (VPC) es tu red aislada en AWS. Dentro de la VPC, defines subredes para segmentar tu red y grupos de seguridad (Security Groups) para actuar como firewalls virtuales a nivel de instancia.

EXPLICACIÓN DEL CÓDIGO

Este fragmento crea una VPC con un bloque CIDR específico, dos subredes (pública y privada) y un grupo de seguridad que permite tráfico HTTP/S y SSH. La etiqueta Name es crucial para la identificación.

# main.tf
resource "aws_vpc" "main" {
  cidr_block       = "10.0.0.0/16"
  instance_tenancy = "default"

  tags = {
    Name = "kwonsejo-vpc-2026"
  }
}

resource "aws_subnet" "public" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "eu-west-1a" # Asegúrate de que esta AZ esté disponible en tu región

  tags = {
    Name = "kwonsejo-public-subnet-2026"
  }
}

resource "aws_subnet" "private" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.2.0/24"
  availability_zone = "eu-west-1b" # Asegúrate de que esta AZ esté disponible en tu región

  tags = {
    Name = "kwonsejo-private-subnet-2026"
  }
}

resource "aws_security_group" "web_sg" {
  vpc_id      = aws_vpc.main.id
  name        = "kwonsejo-web-sg-2026"
  description = "Permitir tráfico web y SSH"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # Restringir en producción
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "kwonsejo-web-sg-2026"
  }
}

Instancias EC2 y Auto Scaling Groups

Las instancias EC2 son los servidores virtuales de AWS. Para alta disponibilidad y escalabilidad, se suelen desplegar dentro de un Auto Scaling Group (ASG) detrás de un Load Balancer.

EXPLICACIÓN DEL CÓDIGO

Este código define una configuración de lanzamiento para EC2 y un Auto Scaling Group que mantiene al menos una instancia t2.micro en una subred pública. Se usa un user_data para instalar Nginx al iniciar la instancia.

# main.tf (continuación)
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"] # Canonical
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}

resource "aws_launch_configuration" "web_lc" {
  name_prefix          = "kwonsejo-web-lc-2026-"
  image_id             = data.aws_ami.ubuntu.id
  instance_type        = "t2.micro"
  security_groups      = [aws_security_group.web_sg.id]
  key_name             = "tu-clave-ssh" # Reemplaza con tu clave SSH
  associate_public_ip_address = true

  user_data = <<-EOF
              #!/bin/bash
              sudo apt update -y
              sudo apt install -y nginx
              sudo systemctl start nginx
              sudo systemctl enable nginx
              echo "<h1>Hola desde Kwonsejo en $(hostname -f)</h1>" | sudo tee /var/www/html/index.nginx-debian.html
              EOF
}

resource "aws_autoscaling_group" "web_asg" {
  launch_configuration = aws_launch_configuration.web_lc.name
  vpc_zone_identifier  = [aws_subnet.public.id] # Asocia con la subred pública
  min_size             = 1
  max_size             = 3
  desired_capacity     = 1

  tag {
    key                 = "Name"
    value               = "kwonsejo-web-instance-2026"
    propagate_at_launch = true
  }
}

Bases de Datos RDS

Amazon RDS (Relational Database Service) facilita la configuración, operación y escalado de bases de datos relacionales. Puedes aprovisionar diferentes motores de base de datos como MySQL, PostgreSQL, etc.

EXPLICACIÓN DEL CÓDIGO

Este ejemplo crea un grupo de subredes para RDS (que abarca múltiples AZs para alta disponibilidad) y una instancia de base de datos MySQL pequeña. Es crucial almacenar las credenciales de la base de datos de forma segura, no directamente en el código HCL (por ejemplo, usando AWS Secrets Manager).

# main.tf (continuación)
resource "aws_db_subnet_group" "rds_subnet_group" {
  name       = "kwonsejo-rds-subnet-group-2026"
  subnet_ids = [aws_subnet.private.id, aws_subnet.public.id] # Incluye subredes en diferentes AZs

  tags = {
    Name = "kwonsejo-rds-subnet-group-2026"
  }
}

resource "aws_db_instance" "mysql_db" {
  allocated_storage    = 20
  storage_type         = "gp2"
  engine               = "mysql"
  engine_version       = "8.0.28"
  instance_class       = "db.t3.micro"
  name                 = "kwonsejodb"
  username             = "admin"
  password             = "SuperSecretPassword2026" # ¡Usar Secrets Manager en producción!
  port                 = 3306
  vpc_security_group_ids = [aws_security_group.web_sg.id] # Asocia un SG para el acceso a la DB
  db_subnet_group_name = aws_db_subnet_group.rds_subnet_group.name
  skip_final_snapshot  = true
  publicly_accessible  = false # Mantener la DB privada es una buena práctica de seguridad

  tags = {
    Name = "kwonsejo-mysql-db-2026"
  }
}

Diagrama conceptual de una arquitectura de aplicación web AWS típica desplegada con Terraform (VPC, Subredes, EC2, RDS, ALB)

Tabla Comparativa: Herramientas IaC para AWS (2026)

Aunque Terraform es una opción excelente, no es la única herramienta de IaC. Aquí hay una comparación rápida con otras opciones populares en el entorno AWS.

Comparación de Herramientas IaC

Terraform — Multi-cloud, declarativo, HCL. Gran ecosistema y comunidad. Ideal para entornos híbridos y complejos.

AWS CloudFormation — Específico de AWS, declarativo, YAML/JSON. Integración nativa con AWS, control de versiones de plantillas, StackSets.

AWS CDK (Cloud Development Kit) — Específico de AWS, imperativo/declarativo (construye CloudFormation), lenguajes de programación (Python, TypeScript, Java, etc.). Permite usar lógica de programación para definir la infraestructura.

Ansible — Multi-cloud, imperativo, YAML. Más orientado a la configuración de servidores y despliegue de software que al aprovisionamiento de infraestructura base.

PUNTO CLAVE

Terraform destaca por su capacidad multi-cloud y su lenguaje declarativo HCL, lo que lo hace versátil para gestionar una amplia gama de recursos AWS, desde redes básicas hasta servicios de cómputo y bases de datos.

RESOLUCIÓN DE PROBLEMAS

Resolución de Problemas Comunes y Mejores Prácticas

Trabajar con IaC y Terraform, aunque poderoso, puede presentar desafíos. Conocer los problemas comunes y sus soluciones es clave para una operación fluida.

Desafíos Técnicos y Soluciones

PROBLEMA 01

Drift de Configuración (Configuration Drift)

El drift de configuración ocurre cuando los cambios se realizan manualmente en la consola de AWS o a través de scripts externos, haciendo que el estado real de la infraestructura difiera del estado definido en tus archivos de Terraform.

SOLUCIÓN — Regularmente, ejecuta terraform plan para detectar diferencias. Considera usar terraform refresh (aunque plan lo hace implícitamente) o herramientas de auditoría. Implementa políticas de IAM estrictas para restringir cambios manuales.

terraform plan
terraform refresh # Actualiza el estado local con la infraestructura real sin aplicar cambios

PROBLEMA 02

Gestión de Estados Concurrentes y Bloqueos

Cuando varios desarrolladores intentan aplicar cambios simultáneamente, pueden ocurrir conflictos en el archivo de estado de Terraform, llevando a corrupción del estado o a despliegues inconsistentes.

SOLUCIÓN — Utiliza un backend remoto que soporte bloqueo de estado, como S3 con una tabla DynamoDB. Esto garantiza que solo una operación de Terraform pueda modificar el estado a la vez, previniendo la corrupción. Terraform Cloud/Enterprise ofrece gestión de estado y bloqueos avanzados.

# Configuración del backend S3 con DynamoDB para bloqueo
terraform {
  backend "s3" {
    bucket         = "mi-bucket-estado-terraform"
    key            = "prod/terraform.tfstate"
    region         = "eu-west-1"
    dynamodb_table = "terraform-state-locks" # Tabla DynamoDB para el bloqueo
  }
}

PROBLEMA 03

Errores de Aprovisionamiento o Dependencias

Los errores pueden ocurrir si un recurso intenta referenciar a otro que aún no ha sido creado, o si hay un problema con los permisos de AWS o la configuración del recurso.

SOLUCIÓN — Terraform gestiona las dependencias implícitamente la mayoría de las veces. Si un error persiste, puedes usar la propiedad depends_on para forzar un orden de creación explícito. Revisa los logs de Terraform y AWS CloudTrail para identificar la causa raíz. Asegúrate de que las políticas de IAM de tu usuario o rol tengan los permisos correctos para todos los recursos que intentas gestionar.

resource "aws_instance" "web" {
  # ...
  depends_on = [aws_s3_bucket.logs] # Forzar que el bucket de logs se cree primero
}

Diagrama ilustrando el drift de configuración y cómo Terraform lo detecta y resuelve

PUNTO CLAVE

La adopción de buenas prácticas como el uso de backends remotos con bloqueo de estado, la revisión constante de los planes de ejecución y una gestión granular de permisos de IAM son fundamentales para mitigar los problemas comunes en la gestión de infraestructura AWS con Terraform.

APLICACIÓN PRÁCTICA

Aplicación Práctica: Despliegue de una Aplicación Web en AWS con Terraform

Vamos a consolidar lo aprendido desplegando una aplicación web simple en AWS utilizando Terraform. Esta arquitectura incluirá una VPC, subredes, un Application Load Balancer (ALB) y un Auto Scaling Group de instancias EC2 con Nginx.

Arquitectura de Despliegue

La arquitectura consistirá en:

  • VPC Personalizada: Una red aislada.
  • Subredes Públicas: Para el ALB e instancias EC2 accesibles desde internet.
  • Internet Gateway (IGW): Para permitir la comunicación de la VPC con internet.
  • Application Load Balancer (ALB): Distribuye el tráfico entrante a las instancias EC2.
  • Auto Scaling Group (ASG): Gestiona un grupo de instancias EC2 para escalabilidad y alta disponibilidad.
  • Instancias EC2: Ejecutando Nginx como servidor web.
  • Grupos de Seguridad: Para controlar el tráfico de red.

Diagrama de arquitectura detallado para el despliegue de una aplicación web en AWS usando Terraform, mostrando todos los componentes y sus conexiones

Paso a Paso con Terraform

1

Configuración Inicial y VPC

Define el proveedor de AWS, la VPC, las subredes públicas y el Internet Gateway para permitir la conectividad a internet.

EXPLICACIÓN DEL CÓDIGO

Este código establece la base de red para nuestra aplicación, incluyendo la VPC, subredes en dos Zonas de Disponibilidad (AZs) y un Internet Gateway para la conectividad externa. También define las tablas de ruteo.

# main.tf
provider "aws" {
  region = "eu-west-1"
}

resource "aws_vpc" "app_vpc" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "kwonsejo-app-vpc-2026"
  }
}

resource "aws_internet_gateway" "app_igw" {
  vpc_id = aws_vpc.app_vpc.id
  tags = {
    Name = "kwonsejo-app-igw-2026"
  }
}

data "aws_availability_zones" "available" {
  state = "available"
}

resource "aws_subnet" "public_subnets" {
  count             = 2
  vpc_id            = aws_vpc.app_vpc.id
  cidr_block        = cidrsubnet(aws_vpc.app_vpc.cidr_block, 8, count.index) # 10.0.0.0/24, 10.0.1.0/24
  availability_zone = data.aws_availability_zones.available.names[count.index]
  map_public_ip_on_launch = true

  tags = {
    Name = "kwonsejo-public-subnet-${count.index + 1}-2026"
  }
}

resource "aws_route_table" "public_rt" {
  vpc_id = aws_vpc.app_vpc.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.app_igw.id
  }
  tags = {
    Name = "kwonsejo-public-rt-2026"
  }
}

resource "aws_route_table_association" "public_rt_assoc" {
  count          = 2
  subnet_id      = aws_subnet.public_subnets[count.index].id
  route_table_id = aws_route_table.public_rt.id
}

2

Grupos de Seguridad para ALB y EC2

Configura los grupos de seguridad para permitir el tráfico necesario hacia el ALB y desde el ALB hacia las instancias EC2.

EXPLICACIÓN DEL CÓDIGO

Definimos dos grupos de seguridad: uno para el ALB que permite tráfico HTTP/S desde cualquier lugar, y otro para las instancias EC2 que solo permite tráfico HTTP/S desde el ALB y SSH para administración (restringir en producción).

# main.tf (continuación)
resource "aws_security_group" "alb_sg" {
  vpc_id      = aws_vpc.app_vpc.id
  name        = "kwonsejo-alb-sg-2026"
  description = "Permitir tráfico HTTP/S hacia el ALB"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name = "kwonsejo-alb-sg-2026"
  }
}

resource "aws_security_group" "ec2_sg" {
  vpc_id      = aws_vpc.app_vpc.id
  name        = "kwonsejo-ec2-sg-2026"
  description = "Permitir tráfico desde el ALB y SSH"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    security_groups = [aws_security_group.alb_sg.id] # Solo desde el ALB
  }
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    security_groups = [aws_security_group.alb_sg.id] # Solo desde el ALB
  }
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # ¡Restringir en producción!
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name = "kwonsejo-ec2-sg-2026"
  }
}

3

Application Load Balancer (ALB)

Configura el ALB para distribuir el tráfico entrante a un grupo de destino de instancias EC2.

EXPLICACIÓN DEL CÓDIGO

Este bloque crea un ALB, un grupo de destino para nuestras instancias Nginx y un listener HTTP que reenvía el tráfico al grupo de destino. El ALB se despliega en las subredes públicas.

# main.tf (continuación)
resource "aws_lb" "app_alb" {
name = "kwonsejo-app-alb-2026"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb_sg.id]
subnets = [for subnet in aws_subnet.public_subnets : subnet.id]

tags = {
Name = "kwonsejo-app-alb-2026"
}
}

resource "aws_lb_target_group" "app_tg" {
name = "kwonsejo-app