Gestionando Servidores sin Estado con Terraform y AWS Auto Scaling Groups
Este tutorial te guiará a través del proceso de aprovisionamiento y gestión de servidores sin estado utilizando AWS Auto Scaling Groups (ASG) con Terraform. Aprenderás a configurar grupos de autoescalado, políticas de escalado, balanceadores de carga y monitoreo, garantizando alta disponibilidad y escalabilidad para tus aplicaciones.
🚀 Introducción: Servidores sin Estado y Auto Scaling Groups
En el mundo de la infraestructura como código (IaC), la gestión eficiente y escalable de servidores es fundamental. Los servidores sin estado (stateless servers) son la piedra angular de muchas arquitecturas modernas, permitiendo que las aplicaciones sean resilientes, elásticas y fáciles de escalar. A diferencia de los servidores con estado, que mantienen datos o sesiones localmente, los servidores sin estado no conservan ninguna información entre solicitudes, lo que los hace ideales para ser reemplazados o escalados horizontalmente sin impacto.
AWS Auto Scaling Groups (ASG) es un servicio de AWS que ayuda a asegurar que tienes el número correcto de instancias Amazon EC2 disponibles para manejar la carga de tu aplicación. Los ASG te permiten mantener la disponibilidad de la aplicación y te proporcionan escalado automático, añadiendo o eliminando instancias según sea necesario. Combinar esto con Terraform nos permite definir, versionar y desplegar nuestra infraestructura de manera declarativa y automatizada.
¿Por qué Terraform y ASG?
La sinergia entre Terraform y AWS Auto Scaling Groups es poderosa. Terraform nos permite definir la configuración completa de nuestros ASG, incluyendo los detalles de lanzamiento de instancias, las políticas de escalado, los balanceadores de carga asociados y las métricas de monitoreo, todo como código. Esto no solo mejora la repetibilidad y reduce errores manuales, sino que también facilita la implementación de prácticas DevOps como la integración y entrega continua (CI/CD) para la infraestructura.
🎯 Objetivos del Tutorial
Al finalizar este tutorial, serás capaz de:
- Comprender los conceptos clave de los servidores sin estado y AWS Auto Scaling Groups.
- Aprovisionar un Auto Scaling Group básico con Terraform.
- Configurar un Launch Template para definir el tipo de instancias.
- Integrar un Application Load Balancer (ALB) con el ASG.
- Implementar políticas de escalado dinámicas (basadas en CPU).
- Configurar monitoreo básico y notificaciones.
🛠️ Requisitos Previos
Antes de empezar, asegúrate de tener lo siguiente:
- Una cuenta de AWS con credenciales configuradas (clave de acceso y clave secreta) en tu entorno local. Puedes configurarlas a través de variables de entorno, el archivo
~/.aws/credentials, o el comandoaws configure. - Terraform instalado en tu máquina local. Si no lo tienes, puedes descargarlo desde terraform.io.
- Conocimientos básicos de AWS EC2, VPC y Terraform.
🏗️ Estructura del Proyecto
Organizaremos nuestro proyecto Terraform de la siguiente manera:
.
├── main.tf
├── variables.tf
├── outputs.tf
└── providers.tf
Esta estructura nos permite mantener el código ordenado y modular.
📝 Configurando el Proveedor de AWS
Comenzaremos configurando el proveedor de AWS en providers.tf.
# providers.tf
provider "aws" {
region = "us-east-1" # Puedes cambiar a tu región preferida
}
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
required_version = ">= 1.0.0"
}
🌐 Creando una VPC y Subredes (Si no tienes una existente)
Para desplegar instancias EC2 y un ALB, necesitamos una Virtual Private Cloud (VPC) y al menos dos subredes públicas en diferentes zonas de disponibilidad para alta disponibilidad. Si ya tienes una VPC configurada, puedes omitir esta sección y usar tus IDs de VPC y subredes existentes.
# main.tf (parte 1: VPC y subredes)
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "terraform-asg-vpc"
}
}
resource "aws_subnet" "public_a" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-east-1a"
map_public_ip_on_launch = true
tags = {
Name = "terraform-asg-public-a"
}
}
resource "aws_subnet" "public_b" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.2.0/24"
availability_zone = "us-east-1b"
map_public_ip_on_launch = true
tags = {
Name = "terraform-asg-public-b"
}
}
resource "aws_internet_gateway" "gw" {
vpc_id = aws_vpc.main.id
tags = {
Name = "terraform-asg-igw"
}
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.gw.id
}
tags = {
Name = "terraform-asg-public-rt"
}
}
resource "aws_route_table_association" "public_a" {
subnet_id = aws_subnet.public_a.id
route_table_id = aws_route_table.public.id
}
resource "aws_route_table_association" "public_b" {
subnet_id = aws_subnet.public_b.id
route_table_id = aws_route_table.public.id
}
🛡️ Configurando Grupos de Seguridad
Necesitamos grupos de seguridad para permitir el tráfico HTTP a nuestro ALB y el tráfico entrante a nuestras instancias EC2 desde el ALB.
# main.tf (parte 2: Security Groups)
resource "aws_security_group" "alb" {
vpc_id = aws_vpc.main.id
name = "alb-sg"
description = "Allow HTTP traffic to ALB"
ingress {
from_port = 80
to_port = 80
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 = "terraform-asg-alb-sg"
}
}
resource "aws_security_group" "asg_instances" {
vpc_id = aws_vpc.main.id
name = "asg-instances-sg"
description = "Allow traffic from ALB to ASG instances"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [aws_security_group.alb.id] # Solo permite tráfico desde el ALB
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "terraform-asg-instances-sg"
}
}
📝 Definiendo un Launch Template
Un Launch Template especifica los parámetros de configuración para las instancias EC2 que el Auto Scaling Group lanzará. Esto incluye el AMI, tipo de instancia, par de claves, grupos de seguridad, y datos de usuario (user data).
# main.tf (parte 3: Launch Template)
data "aws_ami" "amazon_linux_2" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-gp2"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
resource "aws_launch_template" "web_app_template" {
name_prefix = "web-app-template-"
image_id = data.aws_ami.amazon_linux_2.id
instance_type = "t3.micro"
key_name = "your-key-pair-name" # ¡IMPORTANTE: Reemplaza con tu nombre de par de claves!
vpc_security_group_ids = [aws_security_group.asg_instances.id]
user_data = base64encode(<<EOF
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Hola desde el ASG! Instancia: $(hostname -f)</h1>" > /var/www/html/index.html
EOF
)
tag_specifications {
resource_type = "instance"
tags = {
Name = "web-app-instance"
}
}
lifecycle {
create_before_destroy = true
}
tags = {
Name = "web-app-launch-template"
}
}
El user_data es un script que se ejecuta la primera vez que la instancia arranca. En este ejemplo, instala Apache (httpd), lo inicia y crea un archivo index.html simple. Esto simula una aplicación web sin estado.
⚖️ Configurando un Application Load Balancer (ALB)
Un ALB distribuirá el tráfico entrante a las instancias en nuestro ASG, proporcionando alta disponibilidad y tolerancia a fallos. Necesitaremos un ALB, un Target Group y un Listener.
# main.tf (parte 4: ALB)
resource "aws_lb" "web_app_alb" {
name = "web-app-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = [aws_subnet.public_a.id, aws_subnet.public_b.id]
enable_deletion_protection = false # Para entornos de producción, considera true
tags = {
Name = "terraform-asg-alb"
}
}
resource "aws_lb_target_group" "web_app_tg" {
name = "web-app-tg"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.main.id
health_check {
path = "/"
protocol = "HTTP"
matcher = "200"
interval = 30
timeout = 5
healthy_threshold = 2
unhealthy_threshold = 2
}
tags = {
Name = "terraform-asg-target-group"
}
}
resource "aws_lb_listener" "http_listener" {
load_balancer_arn = aws_lb.web_app_alb.id
port = 80
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.web_app_tg.arn
}
tags = {
Name = "terraform-asg-listener"
}
}
El health check del Target Group es crucial para que el ALB sepa cuándo una instancia está disponible para recibir tráfico. Si una instancia falla el health check, el ALB dejará de enviarle tráfico hasta que se recupere (o sea reemplazada por el ASG).
🔄 Creando el Auto Scaling Group
Ahora, definiremos el Auto Scaling Group que utilizará nuestro Launch Template y se integrará con el ALB.
# main.tf (parte 5: Auto Scaling Group)
resource "aws_autoscaling_group" "web_app_asg" {
name = "web-app-asg"
max_size = 5
min_size = 2
desired_capacity = 2
vpc_zone_identifier = [aws_subnet.public_a.id, aws_subnet.public_b.id]
launch_template {
id = aws_launch_template.web_app_template.id
version = "$Latest"
}
target_group_arns = [aws_lb_target_group.web_app_tg.arn]
health_check_type = "ELB" # Usa los health checks del ALB
health_check_grace_period = 300 # Segundos para esperar antes de hacer health checks iniciales
tag {
key = "Name"
value = "web-app-instance"
propagate_at_launch = true
}
tags_all = {
Environment = "Development"
Project = "WebAppASG"
}
}
En esta configuración:
max_size,min_sizeydesired_capacitydefinen los límites y el número inicial de instancias.vpc_zone_identifierespecifica las subredes donde se lanzarán las instancias, asegurando distribución entre zonas de disponibilidad.launch_templateenlaza el ASG con nuestra configuración de instancias.target_group_arnsintegra el ASG con el Target Group del ALB.health_check_type = "ELB"indica que el ASG debe usar los health checks del Load Balancer para determinar el estado de las instancias.
📈 Configurando Políticas de Escalado Dinámico
Para que nuestro ASG escale automáticamente, necesitamos definir políticas de escalado. Usaremos una política de escalado basada en la utilización de la CPU.
# main.tf (parte 6: Scaling Policies)
resource "aws_autoscaling_policy" "cpu_utilization_scale_out" {
name = "cpu-utilization-scale-out"
autoscaling_group_name = aws_autoscaling_group.web_app_asg.name
policy_type = "TargetTrackingScaling"
target_tracking_configuration {
predefined_metric_specification {
predefined_metric_type = "ASGAverageCPUUtilization"
}
target_value = 50.0 # Mantener la CPU promedio del ASG en 50%
}
}
resource "aws_autoscaling_policy" "cpu_utilization_scale_in" {
name = "cpu-utilization-scale-in"
autoscaling_group_name = aws_autoscaling_group.web_app_asg.name
policy_type = "TargetTrackingScaling"
target_tracking_configuration {
predefined_metric_specification {
predefined_metric_type = "ASGAverageCPUUtilization"
}
target_value = 50.0
disable_scale_in = false # Permite que el ASG reduzca el número de instancias
}
}
Estas políticas de Target Tracking son muy eficientes: intentan mantener la métrica (ASGAverageCPUUtilization) lo más cerca posible del target_value (50% en este caso) ajustando el número de instancias. AWS CloudWatch y Auto Scaling se encargan de la lógica subyacente.
📤 Salidas (Outputs)
Es útil exportar ciertos valores de nuestra infraestructura, como el DNS del ALB, para un fácil acceso.
# outputs.tf
output "alb_dns_name" {
description = "The DNS name of the Application Load Balancer."
value = aws_lb.web_app_alb.dns_name
}
output "asg_name" {
description = "The name of the Auto Scaling Group."
value = aws_autoscaling_group.web_app_asg.name
}
🚀 Despliegue de la Infraestructura
Con todos los archivos .tf configurados, es hora de desplegar la infraestructura.
- Inicializar Terraform: Abre tu terminal en la carpeta del proyecto y ejecuta:
terraform init
Esto descargará los plugins necesarios para el proveedor de AWS.
2. Planificar la creación: Para ver qué recursos creará Terraform sin aplicarlos aún, ejecuta:
terraform plan
Revisa cuidadosamente el plan para asegurarte de que todo es como esperas.
3. Aplicar la configuración: Si el plan es correcto, aplica los cambios:
terraform apply
Escribe `yes` cuando se te solicite para confirmar la creación de los recursos.
Este proceso tomará varios minutos, ya que Terraform aprovisionará la VPC, subredes, grupos de seguridad, ALB, Target Group, Launch Template y finalmente el Auto Scaling Group, que a su vez lanzará las instancias EC2.
✅ Verificando el Despliegue
Una vez que terraform apply haya terminado, haz lo siguiente:
- Obtén el DNS del ALB: El valor del DNS se mostrará en la salida de Terraform. Si no, puedes ejecutar:
terraform output alb_dns_name
- Accede a la aplicación: Copia el DNS del ALB y pégalo en tu navegador web. Deberías ver un mensaje como
Hola desde el ASG! Instancia: ip-10-0-1-xxx.ec2.internal. - Monitorea las instancias: Ve a la consola de AWS > EC2 > Grupos de Auto Scaling. Verás tu ASG en estado
InServicecon las instancias lanzadas. - Prueba el escalado: Para probar el escalado, puedes sobrecargar las instancias (por ejemplo, con una herramienta como
stress-ngsi accedes vía SSH a una de ellas) y observa cómo el ASG lanza nuevas instancias para mantener la CPU por debajo del 50%. Luego, cuando la carga disminuya, verás cómo se reducen las instancias hasta elmin_size.
Ejemplo de cómo estresar una instancia (Solo para pruebas)
Para estresar una instancia EC2 (asumiendo que tienes SSH configurado con tu key pair y la instancia es accesible), puedes hacer lo siguiente:- Conéctate a una de las instancias EC2 del ASG via SSH.
ssh -i your-key-pair.pem ec2-user@<IP_PUBLICA_DE_LA_INSTANCIA>
- Instala
stress-ng:
sudo yum install -y stress-ng
- Ejecuta
stress-ngpara sobrecargar la CPU:
stress-ng --cpu 8 --timeout 300s # Estresará 8 núcleos por 5 minutos
Observa los gráficos de CloudWatch para el ASG, y cómo el número de instancias aumenta.
🧹 Limpieza de Recursos
Para evitar cargos innecesarios, es crucial destruir todos los recursos creados por Terraform una vez que hayas terminado con este tutorial.
terraform destroy
Terraform te pedirá confirmación. Escribe yes para proceder con la eliminación de todos los recursos.
💡 Consideraciones Adicionales y Buenas Prácticas
- Monitoreo Avanzado: Integra CloudWatch con alarmas y notificaciones (SNS) para métricas importantes del ASG y el ALB.
- Gestión de Logs: Implementa un sistema de gestión de logs centralizado (ej. CloudWatch Logs, Splunk, ELK) para recoger los logs de tus instancias EC2.
- CI/CD para Infraestructura: Automatiza el proceso de
terraform planyterraform applyutilizando herramientas de CI/CD como Jenkins, GitLab CI, GitHub Actions o AWS CodePipeline. - Versionado de Launch Templates: En un entorno de producción, utiliza diferentes versiones de tus Launch Templates para desplegar nuevas versiones de tu aplicación sin interrupción (despliegues blue/green o rolling updates).
- AMI Personalizadas: En lugar de instalar software en
user_data, considera crear AMIs personalizadas con tu aplicación preinstalada y configurada. Esto acelera el lanzamiento de instancias y simplifica eluser_data. - Políticas de Terminación: Los ASG tienen políticas de terminación que controlan qué instancia se elimina durante un evento de reducción de escala. Por defecto, intentan preservar la disponibilidad de las zonas de disponibilidad.
- Etiquetado (Tagging): Utiliza etiquetas consistentes para organizar y gestionar tus recursos de AWS, facilitar la facturación y el monitoreo.
📚 Recursos Adicionales
- Documentación de AWS Auto Scaling
- Documentación de Terraform AWS Provider
- Conceptos de Servidores Sin Estado
Conclusión ✨
Has completado un tutorial práctico sobre cómo aprovisionar y gestionar servidores sin estado utilizando AWS Auto Scaling Groups con Terraform. Dominar esta combinación es esencial para construir arquitecturas en la nube que sean escalables, resilientes y eficientes en costos. La capacidad de definir tu infraestructura como código te brinda un control sin precedentes y la agilidad necesaria para responder rápidamente a las demandas cambiantes de tus aplicaciones.
¡Sigue explorando las posibilidades de Terraform y AWS para llevar tus habilidades de DevOps al siguiente nivel!
Tutoriales relacionados
- Gestionando Secretos Sensibles en Terraform con HashiCorp Vault: Un Enfoque Segurointermediate25 min
- Gestionando Estado Remoto con Terraform: S3 y DynamoDB para Colaboración y Resilienciaintermediate20 min
- Gestionando Permisos de AWS con Terraform: IAM Roles, Políticas y Usuariosintermediate20 min
- Gestionando Contenedores con Terraform y Amazon ECS: Despliegue y Orquestación Escalableintermediate25 min
- Gestionando Configuración de Aplicaciones y Secrets con Terraform y AWS Parameter Storeintermediate20 min
Comentarios (0)
Aún no hay comentarios. ¡Sé el primero!