Arquitectura Web en AWS
Introducción
Desplegar un servicio web en AWS requiere combinar varios servicios: VPC, EC2, Load Balancer y una buena estrategia de seguridad. Esta sección cubre los patrones de arquitectura más comunes.
Patrón 1: Arquitectura Simple
Una Instancia EC2 Pública
┌─────────────────────────────────────────────────────────────┐
│ ARQUITECTURA SIMPLE (dev/test) │
├─────────────────────────────────────────────────────────────┤
│ │
│ INTERNET │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ IGW │ │
│ └────┬─────┘ │
│ │ │
│ ┌─────────────────────┼─────────────────────┐ │
│ │ VPC │ │ │
│ │ │ │ │
│ │ ┌─────────────────▼───────────────────┐ │ │
│ │ │ SUBNET PUBLIC │ │ │
│ │ │ │ │ │
│ │ │ ┌─────────────────┐ │ │ │
│ │ │ │ EC2 │ │ │ │
│ │ │ │ Web Server │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ IP: 52.1.2.3 │ │ │ │
│ │ │ │ SG: web-server │ │ │ │
│ │ │ └─────────────────┘ │ │ │
│ │ │ │ │ │
│ │ └──────────────────────────────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ Ventajas: │
│ ✅ Fácil de desplegar │
│ ✅ Costo mínimo │
│ ✅ Ideal para dev/test │
│ │
│ Desventajas: │
│ ❌ Sin alta disponibilidad │
│ ❌ Un solo punto de falla │
│ ❌ No escalable │
│ │
└─────────────────────────────────────────────────────────────┘
Configuración
# 1. Crear un Security Group para la web
aws ec2 create-security-group \
--group-name sg-web-simple \
--description "Web server SG" \
--vpc-id vpc-xxx
# 2. Permitir HTTP y HTTPS
aws ec2 authorize-security-group-ingress \
--group-id sg-xxx \
--protocol tcp --port 80 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress \
--group-id sg-xxx \
--protocol tcp --port 443 --cidr 0.0.0.0/0
# 3. Lanzar la instancia
aws ec2 run-instances \
--image-id ami-xxx \
--instance-type t3.micro \
--subnet-id subnet-public \
--security-group-ids sg-xxx \
--associate-public-ip-address \
--user-data '#!/bin/bash
yum install -y httpd
systemctl start httpd
echo "Hello World" > /var/www/html/index.html'
Patrón 2: Arquitectura con Load Balancer
ALB + Instancias Privadas
┌─────────────────────────────────────────────────────────────────────────┐
│ ARQUITECTURA CON ALB (producción) │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ INTERNET │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ IGW │ │
│ └────┬─────┘ │
│ │ │
│ ┌────────────────────────────┼────────────────────────────────┐ │
│ │ VPC │ (10.0.0.0/16) │ │
│ │ │ │ │
│ │ ┌────────────────────────┴────────────────────────────┐ │ │
│ │ │ SUBNETS PÚBLICOS │ │ │
│ │ │ │ │ │
│ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │
│ │ │ │ Public 1a │ │ Public 1b │ │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ │ ┌───────┐ │ │ ┌───────┐ │ │ │ │
│ │ │ │ │ ALB │◄─┼──────────────┼──│ ALB │ │ │ │ │
│ │ │ │ │ node │ │ │ │ node │ │ │ │ │
│ │ │ │ └───┬───┘ │ │ └───┬───┘ │ │ │ │
│ │ │ └──────┼──────┘ └──────┼──────┘ │ │ │
│ │ │ │ │ │ │ │
│ │ └─────────┼────────────────────────────┼───────────────┘ │ │
│ │ │ │ │ │
│ │ ┌─────────┼────────────────────────────┼───────────────┐ │ │
│ │ │ │ SUBNETS PRIVADOS │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ ┌──────▼──────┐ ┌──────▼──────┐ │ │ │
│ │ │ │ Private 1a │ │ Private 1b │ │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │ │
│ │ │ │ │ EC2 │ │ │ │ EC2 │ │ │ │ │
│ │ │ │ │ Web 1 │ │ │ │ Web 2 │ │ │ │ │
│ │ │ │ └─────────┘ │ │ └─────────┘ │ │ │ │
│ │ │ └─────────────┘ └─────────────┘ │ │ │
│ │ │ │ │ │
│ │ └──────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ Ventajas: │
│ ✅ Alta disponibilidad (Multi-AZ) │
│ ✅ Escalable (agregar instancias) │
│ ✅ Terminación SSL a nivel de ALB │
│ ✅ Servidores web protegidos (subnet privado) │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Tipos de Load Balancers AWS
| Tipo | Uso | Capa OSI | Protocolos |
|---|---|---|---|
| ALB | Aplicaciones HTTP/HTTPS | Capa 7 | HTTP, HTTPS, gRPC |
| NLB | Ultra rendimiento | Capa 4 | TCP, UDP, TLS |
| CLB | Legacy | Capa 4/7 | TCP, SSL, HTTP, HTTPS |
| GWLB | Appliances de red | Capa 3 | IP |
Configuración ALB
# 1. Crear el Target Group
aws elbv2 create-target-group \
--name tg-web-servers \
--protocol HTTP \
--port 80 \
--vpc-id vpc-xxx \
--health-check-path /health \
--health-check-interval-seconds 30
# 2. Crear el Application Load Balancer
aws elbv2 create-load-balancer \
--name alb-web \
--subnets subnet-public-1a subnet-public-1b \
--security-groups sg-alb \
--scheme internet-facing \
--type application
# 3. Crear el Listener
aws elbv2 create-listener \
--load-balancer-arn arn:aws:elasticloadbalancing:...:alb-web \
--protocol HTTP \
--port 80 \
--default-actions Type=forward,TargetGroupArn=arn:aws:...:tg-web-servers
# 4. Registrar las instancias
aws elbv2 register-targets \
--target-group-arn arn:aws:...:tg-web-servers \
--targets Id=i-web1 Id=i-web2
Patrón 3: Arquitectura 3-Tiers
Web + App + Base de Datos
┌─────────────────────────────────────────────────────────────────────────┐
│ ARQUITECTURA 3-TIERS │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ INTERNET │
│ │ │
│ ┌──────▼──────┐ │
│ │ IGW │ │
│ └──────┬──────┘ │
│ │ │
│ ┌──────────────────────────────┼──────────────────────────────┐ │
│ │ VPC │ │ │
│ │ │ │ │
│ │ ╔══════════════════════════╧════════════════════════════╗ │ │
│ │ ║ TIER 1 : PRESENTACIÓN ║ │ │
│ │ ║ (Subnet Público) ║ │ │
│ │ ║ ║ │ │
│ │ ║ ┌─────────────────────────┐ ║ │ │
│ │ ║ │ Application Load │ ║ │ │
│ │ ║ │ Balancer (ALB) │ ║ │ │
│ │ ║ └───────────┬─────────────┘ ║ │ │
│ │ ╚═══════════════════════╪═══════════════════════════════╝ │ │
│ │ │ │ │
│ │ ╔═══════════════════════╪═══════════════════════════════╗ │ │
│ │ ║ TIER 2 : APLICACIÓN ║ │ │
│ │ ║ (Subnet Privado App) ║ │ │
│ │ ║ │ ║ │ │
│ │ ║ ┌────────────────────┼────────────────────┐ ║ │ │
│ │ ║ │ │ │ ║ │ │
│ │ ║ ┌───▼───┐ ┌─────▼─────┐ ┌─────▼───┐ ║ │ │
│ │ ║ │ EC2 │ │ EC2 │ │ EC2 │ ║ │ │
│ │ ║ │ App 1 │ │ App 2 │ │ App 3 │ ║ │ │
│ │ ║ └───┬───┘ └─────┬─────┘ └────┬────┘ ║ │ │
│ │ ║ │ │ │ ║ │ │
│ │ ╚══════╪════════════════════╪═══════════════════╪═══════╝ │ │
│ │ │ │ │ │ │
│ │ ╔══════╪════════════════════╪═══════════════════╪═══════╗ │ │
│ │ ║ │ TIER 3 : DATOS │ │ ║ │ │
│ │ ║ │ (Subnet Privado DB) │ ║ │ │
│ │ ║ │ │ │ ║ │ │
│ │ ║ └────────────────────┼───────────────────┘ ║ │ │
│ │ ║ │ ║ │ │
│ │ ║ ┌──────▼──────┐ ║ │ │
│ │ ║ │ RDS │ ║ │ │
│ │ ║ │ MySQL │ ║ │ │
│ │ ║ │ Multi-AZ │ ║ │ │
│ │ ║ └─────────────┘ ║ │ │
│ │ ║ ║ │ │
│ │ ╚════════════════════════════════════════════════════════╝ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Security Groups para 3-Tiers
┌─────────────────────────────────────────────────────────────┐
│ SECURITY GROUPS 3-TIERS │
├─────────────────────────────────────────────────────────────┤
│ │
│ sg-alb (Load Balancer) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Inbound: HTTP/443 from 0.0.0.0/0 │ │
│ │ Outbound: HTTP/80 to sg-app │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ sg-app (Application Servers) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Inbound: HTTP/80 from sg-alb │ │
│ │ Inbound: SSH/22 from sg-bastion │ │
│ │ Outbound: MySQL/3306 to sg-db │ │
│ │ Outbound: HTTPS/443 to 0.0.0.0/0 (APIs externas) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ sg-db (Database) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Inbound: MySQL/3306 from sg-app │ │
│ │ Outbound: Ninguno (o mínimo) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ Principio: Cada tier acepta SOLO el tráfico del tier │
│ anterior │
│ │
└─────────────────────────────────────────────────────────────┘
Health Checks
Configuración Health Check ALB
┌─────────────────────────────────────────────────────────────┐
│ HEALTH CHECKS ALB │
├─────────────────────────────────────────────────────────────┤
│ │
│ Parámetros importantes: │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Protocol : HTTP │ │
│ │ Path : /health o /api/health │ │
│ │ Port : traffic-port (80) │ │
│ │ Healthy threshold : 2 (éxitos consecutivos) │ │
│ │ Unhealthy threshold : 3 (fallos consecutivos) │ │
│ │ Timeout : 5 seconds │ │
│ │ Interval : 30 seconds │ │
│ │ Success codes : 200-299 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ Endpoint /health típico: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ HTTP 200 OK │ │
│ │ { │ │
│ │ "status": "healthy", │ │
│ │ "database": "connected", │ │
│ │ "cache": "connected" │ │
│ │ } │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
DNS con Route 53
┌─────────────────────────────────────────────────────────────┐
│ ROUTE 53 + ALB │
├─────────────────────────────────────────────────────────────┤
│ │
│ Usuario escribe: www.monsite.com │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Route 53 │ │
│ │ DNS │ │
│ └──────┬───────┘ │
│ │ │
│ │ Alias Record │
│ │ www.monsite.com │
│ │ → alb-web-xxx.elb.amazonaws.com│
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ ALB │ │
│ └──────────────┘ │
│ │
│ Tipos de registros: │
│ • A (Alias): Apunta a recurso AWS (ALB, CF, S3) │
│ • CNAME : Apunta a otro nombre de dominio │
│ │
│ Ventaja Alias: │
│ ✅ Gratis para consultas a recursos AWS │
│ ✅ Responde con las IPs directamente │
│ │
└─────────────────────────────────────────────────────────────┘
Resumen de los Patrones
| Patrón | Complejidad | Costo | HA | Caso de uso |
|---|---|---|---|---|
| EC2 Simple | ⭐ | $ | ❌ | Dev/Test |
| ALB + EC2 | ⭐⭐ | $$ | ✅ | Producción simple |
| 3-Tiers | ⭐⭐⭐ | $$$ | ✅✅ | Producción |
| Microservicios | ⭐⭐⭐⭐ | $$$$ | ✅✅✅ | Gran escala |
Próxima sección: Lab: Publicación Web