En la lección 02-01 dimensionamos el grupo de Auto Scaling asg-mercadofresco-tienda para el pico de los viernes: mínimo 2, deseado 2, máximo 4, con la política cpu-objetivo-60 y la acción programada pico-viernes-tarde. Los números salían: el pico de los viernes de 17:00 a 21:00 son 900 pedidos por hora, cada instancia aguanta 600 pedidos por hora, y con dos instancias hay capacidad de sobra. En 03-01 y 03-02 les hemos dado una red propia y un cortafuegos que las protege.

Y sin embargo, MercadoFresco sigue cayéndose los viernes. Porque el ASG puede lanzar cuatro instancias, pero nadie envía tráfico a las tres últimas. El dominio apunta a una IP concreta, la de la primera máquina, y las demás se quedan encendidas y ociosas mientras esa se ahoga. Falta la pieza central: algo que reciba todo el tráfico y lo reparta.

Eso es un balanceador de carga. En esta lección Marta monta alb-mercadofresco-tienda, lo conecta al grupo de Auto Scaling y termina de resolver el problema 1 del curso: las caídas de los viernes. Por el camino aparecen las comprobaciones de estado, que son la parte que más aplicaciones ha tumbado por estar mal configuradas.

Contenido

  1. Por qué hace falta un balanceador
  2. Los tipos de balanceador: ALB, NLB, GWLB y el CLB heredado
  3. Anatomía de un ALB: escuchadores, reglas y grupos de destino
  4. Comprobaciones de estado: la parte peligrosa
  5. Integración con el grupo de Auto Scaling
  6. Drenaje de conexiones y despliegues sin cortes
  7. Enrutamiento avanzado por ruta y por host
  8. Redirecciones y respuestas fijas
  9. HTTPS en el balanceador: ACM, políticas TLS y SNI
  10. Sesiones pegajosas y por qué es mejor no necesitarlas
  11. Registros de acceso y métricas
  12. Creación completa por CLI
  13. Coste del ALB y limpieza
  14. El tráfico del viernes, de extremo a extremo

Por qué hace falta un balanceador

Un balanceador de carga es un servicio gestionado que se coloca delante de un conjunto de servidores, recibe todas las peticiones y las distribuye entre ellos. Lo que aporta va bastante más allá del reparto:

  • Una única puerta de entrada. El dominio mercadofresco.example apunta al balanceador, no a ninguna instancia. Las instancias pueden crearse, morir o cambiar de IP sin que nadie se entere.
  • Comprobaciones de estado. El balanceador pregunta periódicamente a cada instancia si está bien, y deja de enviarle tráfico si no responde. Un fallo deja de ser una caída.
  • Alta disponibilidad entre zonas. Al estar en las dos subredes públicas, si eu-west-1a cae entera, el tráfico sigue entrando por eu-west-1b.
  • Terminación de TLS. El certificado vive en el balanceador, no en cada instancia. Un solo sitio que renovar.
  • Escalado elástico real. El ASG registra las instancias nuevas automáticamente, así que la capacidad añadida a las 17:00 del viernes empieza a recibir tráfico sola.
  • Aislamiento. Las instancias pasan a subredes privadas sin IP pública: solo el balanceador habla con ellas.

Sin balanceador, cada uno de esos seis puntos hay que resolverlo a mano, y ninguno se resuelve bien.

Los tipos de balanceador: ALB, NLB, GWLB y el CLB heredado

AWS ofrece tres balanceadores modernos y uno heredado. Elegir mal no rompe nada, pero cuesta dinero o funcionalidad.

ALB
Application LB
NLB
Network LB
GWLB
Gateway LB
CLB
(heredado)
Capa OSI 7 (aplicación) 4 (transporte) 3 (red) 4 y 7, a medias
Protocolos HTTP, HTTPS, gRPC, WebSocket TCP, UDP, TLS IP (GENEVE) HTTP, HTTPS, TCP, SSL
Enruta por Ruta, host, cabecera, método, cadena de consulta, IP de origen Puerto y protocolo Todo el tráfico Puerto
Latencia añadida ~milisegundos ~microsegundos Baja Milisegundos
IP estática No (nombre DNS) , una IP elástica por AZ No aplica No
Destinos Instancias, IP, Lambda, ALB anidado Instancias, IP, ALB Aplicaciones virtuales Instancias
Termina TLS No
Conserva la IP de origen En la cabecera X-Forwarded-For Sí, de forma nativa En la cabecera
Rendimiento Millones de peticiones/s Millones de conexiones/s Alto Limitado
Caso de uso Aplicaciones web y APIs Juegos, IoT, MQTT, latencia extrema, IP fija Cortafuegos e IDS de terceros Nada nuevo

La elección de MercadoFresco es el ALB, y las razones son concretas:

  1. El tráfico es HTTP/HTTPS. Es exactamente para lo que existe el ALB.
  2. Hará falta enrutar por ruta: /api/* hacia el servicio de pedidos y el resto hacia la tienda. Un NLB no puede hacerlo porque no lee la petición HTTP.
  3. Se necesita redirección automática de HTTP a HTTPS, que el ALB hace de forma nativa.
  4. Los milisegundos de latencia adicional son irrelevantes para una tienda; para un videojuego en tiempo real no lo serían, y entonces la respuesta sería NLB.

Sobre el CLB: es la primera generación, sigue existiendo por compatibilidad y no debe usarse en nada nuevo. Si te encuentras uno, la migración a ALB es casi siempre directa.

Un patrón que conviene conocer aunque no lo usemos: NLB delante de ALB. Sirve para obtener una IP fija (por ejemplo, porque un proveedor de pagos exige una lista blanca de IP) manteniendo el enrutamiento por ruta del ALB.

Anatomía de un ALB: escuchadores, reglas y grupos de destino

Un ALB tiene cuatro piezas y hay que tenerlas claras porque la CLI las crea una a una:

flowchart TB
    NET["Internet"]
    subgraph ALB["alb-mercadofresco-tienda (subredes públicas de 1a y 1b)"]
        L80["Escuchador HTTP :80<br/>acción por defecto: redirigir a HTTPS"]
        L443["Escuchador HTTPS :443<br/>certificado ACM"]
        R1["Regla 10: ruta = /api/*"]
        R2["Regla 20: host = admin.mercadofresco.example"]
        RD["Acción por defecto"]
    end
    subgraph TGS["Grupos de destino"]
        TG1["tg-mercadofresco-tienda<br/>protocolo HTTPS :443"]
        TG2["tg-mercadofresco-api<br/>protocolo HTTPS :443"]
        TG3["tg-mercadofresco-admin"]
    end
    E1["Instancias del ASG<br/>snet-app-a"]
    E2["Instancias del ASG<br/>snet-app-b"]

    NET --> L80
    NET --> L443
    L443 --> R1 --> TG2
    L443 --> R2 --> TG3
    L443 --> RD --> TG1
    TG1 --> E1
    TG1 --> E2
Pieza Qué es Detalle importante
Balanceador El recurso en sí, con su nombre DNS Debe estar en al menos dos subredes de AZ distintas
Escuchador (listener) Un puerto y protocolo a la escucha Cada uno tiene una acción por defecto obligatoria
Regla Condición + acción, dentro de un escuchador Se evalúan por prioridad ascendente
Grupo de destino (target group) El conjunto de destinos y su comprobación de estado Aquí vive el health check, no en el balanceador

Dos conceptos que la gente confunde:

  • El grupo de destino tiene su propio protocolo y puerto, independientes del escuchador. El escuchador puede recibir HTTPS en el 443 y reenviar a las instancias en HTTP por el 8080. Eso es la terminación TLS.
  • La comprobación de estado se define en el grupo de destino, no en el balanceador. Un mismo balanceador puede tener grupos con comprobaciones muy distintas.

Los tipos de destino disponibles:

Tipo Qué registra Cuándo se usa
instance ID de instancia EC2 Lo habitual con un ASG
ip IP privadas concretas Contenedores, destinos on-premise por VPN
lambda Una función Lambda APIs sin servidor detrás de un ALB
alb Otro ALB Solo desde un NLB, para el patrón de IP fija

Y los algoritmos de reparto de un grupo de destino:

Algoritmo Cómo reparte Cuándo
round_robin Uno a cada destino por turnos Por defecto; peticiones homogéneas
least_outstanding_requests Al destino con menos peticiones en curso Recomendado cuando las peticiones duran tiempos muy distintos
weighted_random Aleatorio con pesos Con anomaly mitigation activada

Para MercadoFresco, least_outstanding_requests: no dura lo mismo cargar la portada que confirmar un pedido con pasarela de pago.

Comprobaciones de estado: la parte peligrosa

El balanceador envía periódicamente una petición a cada destino registrado. Si responde bien un número de veces seguidas, lo marca sano (healthy) y le envía tráfico. Si falla, lo marca no sano (unhealthy) y deja de enviárselo.

Parámetros y valores recomendados para MercadoFresco:

Parámetro Qué es Por defecto MercadoFresco Razón
HealthCheckPath Ruta que se solicita / /salud Un endpoint dedicado, no la portada
HealthCheckProtocol HTTP o HTTPS HTTP HTTPS Coherente con el grupo de destino
HealthCheckIntervalSeconds Cada cuánto se pregunta 30 s 15 s Detectar fallos antes
HealthCheckTimeoutSeconds Cuánto se espera la respuesta 5 s 5 s Menor que el intervalo, siempre
HealthyThresholdCount Aciertos para declararlo sano 5 2 Reincorporar rápido
UnhealthyThresholdCount Fallos para declararlo no sano 2 3 Tolerar un pico puntual
Matcher Códigos HTTP aceptados 200 200 Explícito y estricto

Con estos valores, una instancia caída tarda como máximo 3 × 15 = 45 segundos en dejar de recibir tráfico.

Qué pasa realmente cuando una instancia se marca como no sana

Esta es la secuencia exacta, y merece detallarse porque hay un efecto en cadena que sorprende:

  1. El ALB deja de enviarle peticiones nuevas. Las que ya estaban en curso se completan.
  2. La instancia sigue encendida y sigue costando dinero. El ALB no la apaga.
  3. La métrica HealthyHostCount del grupo de destino baja en uno.
  4. Todo el tráfico se reparte entre las instancias restantes. Si eran dos y queda una, esa recibe el doble.
  5. Si el ASG tiene la comprobación de estado del balanceador activada (--health-check-type ELB), el ASG termina la instancia y lanza una nueva.

El paso 4 es el peligro. Imagina un /salud que consulta la base de datos. Si la base de datos se pone lenta un momento, todas las instancias fallan la comprobación a la vez, el ALB las marca todas como no sanas y responde 503 Service Unavailable a todos los clientes. La aplicación funcionaba; el health check la ha tumbado.

Peor aún con el ASG en modo ELB: el ASG termina todas las instancias y lanza otras nuevas, que también fallan porque la base de datos sigue lenta, y entra en un bucle de reemplazo perpetuo.

Cómo escribir un health check que no tumbe la aplicación

La regla: la comprobación de estado debe verificar que ESTA instancia puede servir tráfico, no que todo el sistema funciona.

# En la aplicación de la tienda: dos endpoints distintos y con propósitos distintos.

@app.route("/salud")
def salud():
    """Comprobación para el balanceador. Debe ser rápida, local y NO tocar dependencias.
    Solo responde: ¿este proceso está vivo y listo para atender peticiones?"""
    if not app.config.get("ARRANQUE_COMPLETADO"):
        return {"estado": "arrancando"}, 503
    return {"estado": "ok", "version": app.config["VERSION"]}, 200


@app.route("/salud/profunda")
def salud_profunda():
    """Comprobación para la monitorización (CloudWatch, 05-01). Sí consulta dependencias,
    pero NUNCA la usa el balanceador: sirve para alertar, no para retirar instancias."""
    resultado = {"base_datos": "ok", "s3": "ok", "efs": "ok"}
    codigo = 200
    try:
        with obtener_conexion() as conn:
            conn.execute("SELECT 1")
    except Exception as e:
        resultado["base_datos"] = f"error: {type(e).__name__}"
        codigo = 503
    return resultado, codigo

La diferencia entre los dos endpoints es toda la lección:

  • /salud responde en microsegundos, no depende de nada externo y solo puede fallar si esta instancia está rota. Si falla, retirarla es siempre la decisión correcta.
  • /salud/profunda sí comprueba dependencias, pero su fallo debe generar una alarma para que alguien mire, no la retirada automática de servidores sanos.

El 503 durante el arranque es igualmente importante: hace que el ALB no envíe tráfico a una instancia que todavía está descargando la aplicación en el user-data-tienda.sh.

Integración con el grupo de Auto Scaling

Conectar asg-mercadofresco-tienda con el grupo de destino se hace con un solo comando, y a partir de ahí todo es automático:

aws autoscaling attach-load-balancer-target-groups \
  --profile mercadofresco-dev --region eu-west-1 \
  --auto-scaling-group-name asg-mercadofresco-tienda \
  --target-group-arns "$TG_ARN"

Lo que ocurre a partir de ese momento:

Evento Qué hace el ASG Qué hace el ALB
La política cpu-objetivo-60 lanza una instancia La crea desde lt-mercadofresco-tienda La registra en el grupo, estado initial
La instancia arranca y /salud responde 200 dos veces Pasa a healthy y empieza a recibir tráfico
El pico pasa y el ASG reduce capacidad Marca la instancia para terminar La pone en draining
Terminan las conexiones en curso Espera al deregistration_delay La quita del grupo
El ALB marca una instancia unhealthy Con --health-check-type ELB, la reemplaza Deja de enviarle tráfico

El segundo cambio importante es el tipo de comprobación de estado del ASG:

aws autoscaling update-auto-scaling-group \
  --profile mercadofresco-dev --region eu-west-1 \
  --auto-scaling-group-name asg-mercadofresco-tienda \
  --health-check-type ELB \
  --health-check-grace-period 300
Tipo Qué comprueba el ASG Problema
EC2 (por defecto) Solo el estado del hipervisor y del sistema Una instancia con la aplicación muerta figura como sana
ELB El estado del hipervisor y el del grupo de destino Detecta aplicaciones caídas, no solo máquinas caídas

El --health-check-grace-period 300 es tan importante como el tipo: son los segundos que el ASG espera desde que la instancia arranca antes de hacerle caso al balanceador. El user-data-tienda.sh de MercadoFresco tarda unos dos minutos en instalar y arrancar la aplicación; sin margen de gracia, el ASG mataría la instancia justo antes de que terminara de arrancar, y lo haría en bucle. Cinco minutos dan holgura suficiente.

Drenaje de conexiones y despliegues sin cortes

Cuando una instancia se da de baja, el ALB no corta las conexiones abiertas de golpe: la pone en estado draining. Durante el retraso de baja de registro (deregistration_delay.timeout_seconds, 300 segundos por defecto) no recibe peticiones nuevas, pero termina las que tenía en curso.

aws elbv2 modify-target-group-attributes \
  --profile mercadofresco-dev --region eu-west-1 \
  --target-group-arn "$TG_ARN" \
  --attributes \
    Key=deregistration_delay.timeout_seconds,Value=60 \
    Key=load_balancing.algorithm.type,Value=least_outstanding_requests \
    Key=stickiness.enabled,Value=false

Cómo elegir el valor: el tiempo de la petición más larga que sirve tu aplicación, más un margen.

Tipo de aplicación Valor recomendado
API con respuestas de milisegundos 15-30 s
Tienda con confirmación de pedido y pasarela de pago 60 s
Subida de ficheros grandes 180-300 s
WebSocket de larga duración Hasta 3600 s

Los 60 segundos de MercadoFresco cubren el peor caso: un cliente que ha pulsado «confirmar pedido» y está esperando la respuesta de la pasarela. Con el valor por defecto de 300 s, reducir capacidad tras el pico del viernes tardaría cinco minutos de más pagando instancias ociosas; con 5 s, se cortaría un pago a medias.

Enrutamiento avanzado por ruta y por host

Aquí es donde el ALB se gana su nombre: lee la petición HTTP y decide en función de su contenido. MercadoFresco necesita tres destinos distintos bajo el mismo balanceador.

# Regla 10: todo lo que empiece por /api/ va al grupo de la API
aws elbv2 create-rule --profile mercadofresco-dev --region eu-west-1 \
  --listener-arn "$LISTENER_443" \
  --priority 10 \
  --conditions '[{"Field":"path-pattern","Values":["/api/*"]}]' \
  --actions "[{\"Type\":\"forward\",\"TargetGroupArn\":\"$TG_API\"}]"

# Regla 20: el panel de administración, por host
aws elbv2 create-rule --profile mercadofresco-dev --region eu-west-1 \
  --listener-arn "$LISTENER_443" \
  --priority 20 \
  --conditions '[{"Field":"host-header","Values":["admin.mercadofresco.example"]}]' \
  --actions "[{\"Type\":\"forward\",\"TargetGroupArn\":\"$TG_ADMIN\"}]"

Las condiciones disponibles y un ejemplo de cada una:

Condición Ejemplo Uso en MercadoFresco
path-pattern /api/* Separar la API de la web
host-header admin.mercadofresco.example Panel interno en su subdominio
http-header X-Canario: si Pruebas dirigidas antes de un despliegue
http-request-method POST Enrutar escrituras a un grupo distinto
query-string version=beta Activar una versión nueva con un parámetro
source-ip 81.45.20.7/32 Restringir /admin a la oficina

Reglas de evaluación que hay que conocer:

  • Las reglas se evalúan por prioridad ascendente y se aplica la primera que coincida. Deja huecos entre prioridades (10, 20, 30) para poder insertar.
  • Si ninguna coincide, se aplica la acción por defecto del escuchador.
  • Los patrones de ruta distinguen mayúsculas y minúsculas y admiten * y ?.
  • Una regla puede combinar hasta 5 condiciones, y todas deben cumplirse (AND).
  • Un ALB admite hasta 100 reglas por escuchador.

Redirecciones y respuestas fijas

Además de reenviar, un escuchador puede responder por sí mismo, sin tocar ninguna instancia.

Redirección de HTTP a HTTPS, la configuración estándar del escuchador del puerto 80:

aws elbv2 create-listener --profile mercadofresco-dev --region eu-west-1 \
  --load-balancer-arn "$ALB_ARN" \
  --protocol HTTP --port 80 \
  --default-actions '[{
    "Type": "redirect",
    "RedirectConfig": {
      "Protocol": "HTTPS",
      "Port": "443",
      "Host": "#{host}",
      "Path": "/#{path}",
      "Query": "#{query}",
      "StatusCode": "HTTP_301"
    }
  }]'

Los marcadores #{host}, #{path} y #{query} conservan lo que pidió el cliente: quien entre en http://mercadofresco.example/producto/tomate?origen=email acaba en la misma página por HTTPS. Un 301 es permanente y el navegador lo cachea, con lo que la segunda visita ya no pasa por el puerto 80. Si estuvieras probando y no quisieras que se cacheara, usarías HTTP_302.

Respuesta fija, útil para bloquear rutas o dar mantenimiento:

aws elbv2 create-rule --profile mercadofresco-dev --region eu-west-1 \
  --listener-arn "$LISTENER_443" --priority 5 \
  --conditions '[{"Field":"path-pattern","Values":["/.env","/.git/*","/wp-admin/*"]}]' \
  --actions '[{
    "Type": "fixed-response",
    "FixedResponseConfig": {
      "StatusCode": "403",
      "ContentType": "text/plain",
      "MessageBody": "Prohibido"
    }
  }]'

Esa regla, con prioridad 5 (la más alta), corta en el balanceador los intentos automatizados de leer ficheros de configuración. No llegan ni a tocar una instancia. Es un filtrado tosco: el filtrado serio de peticiones maliciosas es AWS WAF, en 04-05.

HTTPS en el balanceador: ACM, políticas TLS y SNI

MercadoFresco todavía sirve por HTTP. Ponerle HTTPS con AWS es gratis y son dos pasos.

AWS Certificate Manager (ACM) emite certificados TLS públicos sin coste y los renueva automáticamente mientras estén asociados a un recurso de AWS. Eso elimina de golpe el problema clásico del certificado que caduca un domingo.

aws acm request-certificate --profile mercadofresco-dev --region eu-west-1 \
  --domain-name mercadofresco.example \
  --subject-alternative-names "*.mercadofresco.example" \
  --validation-method DNS \
  --tags Key=Proyecto,Value=mercadofresco Key=Entorno,Value=produccion \
         Key=Componente,Value=tienda Key=Propietario,Value=marta \
         Key=CentroCoste,Value=operaciones

Dos detalles:

  • El comodín *.mercadofresco.example cubre www, admin, api y cualquier subdominio futuro con un solo certificado.
  • La región importa: para un ALB, el certificado debe estar en la misma región que el ALB (eu-west-1). Para CloudFront tiene que estar en us-east-1, una trampa que veremos en 03-04.

El certificado queda en estado PENDING_VALIDATION hasta que se demuestre que el dominio es tuyo creando un registro CNAME que ACM indica. Esa validación por DNS se completa en la lección 03-05, cuando tengamos la zona alojada de Route 53. Hasta entonces, para practicar puedes crear el escuchador HTTPS con un certificado autofirmado importado, o trabajar solo con el puerto 80.

El escuchador HTTPS, una vez emitido el certificado:

LISTENER_443=$(aws elbv2 create-listener --profile mercadofresco-dev --region eu-west-1 \
  --load-balancer-arn "$ALB_ARN" \
  --protocol HTTPS --port 443 \
  --certificates CertificateArn="$CERT_ARN" \
  --ssl-policy ELBSecurityPolicy-TLS13-1-2-2021-06 \
  --default-actions "Type=forward,TargetGroupArn=$TG_TIENDA" \
  --query 'Listeners[0].ListenerArn' --output text)

Las políticas de seguridad TLS definen qué versiones y cifrados se aceptan:

Política TLS admitido Comentario
ELBSecurityPolicy-TLS13-1-2-2021-06 1.2 y 1.3 Recomendada: segura y compatible con todo navegador actual
ELBSecurityPolicy-TLS13-1-3-2021-06 Solo 1.3 Máxima seguridad; rompe clientes antiguos
ELBSecurityPolicy-FS-1-2-Res-2020-10 1.2 con forward secrecy obligatorio Entornos con requisitos de cumplimiento
ELBSecurityPolicy-2016-08 1.0, 1.1, 1.2 No usar: admite TLS 1.0

Terminación TLS significa que el ALB descifra el tráfico y decide qué hacer con la petición ya en claro. Es la única forma de enrutar por ruta o por cabecera: para leer /api/* hay que poder leer la petición. Del ALB a las instancias, el tráfico puede ir en claro (más rápido, y viaja por la red privada de AWS dentro de tu VPC) o volver a cifrarse. MercadoFresco lo re-cifra: el grupo de destino usa HTTPS en el 443, porque la política interna exige cifrado extremo a extremo aunque el tramo sea privado.

SNI (Server Name Indication) permite alojar varios certificados en un mismo escuchador: el cliente indica qué dominio quiere en el saludo TLS y el ALB presenta el certificado adecuado. Así, un único ALB puede servir mercadofresco.example y, en el futuro, mercadofresco.pt con certificados distintos, sin balanceadores adicionales.

# Añadir un segundo certificado al mismo escuchador
aws elbv2 add-listener-certificates --profile mercadofresco-dev --region eu-west-1 \
  --listener-arn "$LISTENER_443" \
  --certificates CertificateArn="$CERT_ARN_PT"

Sesiones pegajosas y por qué es mejor no necesitarlas

Las sesiones pegajosas (stickiness) hacen que un mismo cliente vaya siempre a la misma instancia. El ALB inserta una cookie (AWSALB, o una propia de la aplicación) y la usa para dirigir las peticiones siguientes.

aws elbv2 modify-target-group-attributes --profile mercadofresco-dev --region eu-west-1 \
  --target-group-arn "$TG_TIENDA" \
  --attributes \
    Key=stickiness.enabled,Value=true \
    Key=stickiness.type,Value=lb_cookie \
    Key=stickiness.lb_cookie.duration_seconds,Value=3600

Sirve cuando la aplicación guarda el estado de la sesión en la memoria del servidor: el carrito de la compra, por ejemplo. Y trae cuatro problemas serios:

Problema Consecuencia real en MercadoFresco
Reparto desigual El viernes, las instancias nuevas arrancan vacías y las viejas siguen con todos los clientes pegados. Se paga capacidad que no descarga a nadie
Pérdida de sesión Si el ASG termina esa instancia al bajar el pico, el cliente pierde el carrito
Despliegues destructivos Cada actualización expulsa a todos los usuarios de la instancia sustituida
Escalado inútil Añadir instancias no ayuda a los usuarios ya conectados

Por eso MercadoFresco tiene stickiness.enabled=false y la aplicación es sin estado (stateless): la sesión se guarda fuera de la instancia. Las opciones:

Dónde guardar la sesión Ventaja Inconveniente
ElastiCache (Redis) Rápido, milisegundos, el estándar de la industria Un servicio más que operar — se estudia en 06-05
DynamoDB Sin servidor, sin operación, TTL automático Latencia algo mayor — se estudia en 06-02
Cookie firmada en el cliente Cero infraestructura Tamaño limitado, datos viajan en cada petición
Base de datos relacional Ya existe Carga innecesaria en RDS

MercadoFresco acabará usando ElastiCache. Mientras tanto, las sesiones pegajosas son un parche aceptable si se documenta como deuda técnica; lo que no es aceptable es activarlas y olvidar por qué.

Registros de acceso y métricas

Registros de acceso. El ALB puede volcar en S3 una línea por petición, con la IP del cliente, la ruta, el código de respuesta, los tiempos de procesamiento y el destino que la atendió. Están desactivados por defecto.

aws elbv2 modify-load-balancer-attributes --profile mercadofresco-dev --region eu-west-1 \
  --load-balancer-arn "$ALB_ARN" \
  --attributes \
    Key=access_logs.s3.enabled,Value=true \
    Key=access_logs.s3.bucket,Value=mercadofresco-registros-web \
    Key=access_logs.s3.prefix,Value=alb \
    Key=idle_timeout.timeout_seconds,Value=60 \
    Key=routing.http.drop_invalid_header_fields.enabled,Value=true

El bucket mercadofresco-registros-web necesita una política que autorice al servicio a escribir en él; sin ella el comando parece funcionar pero no aparece ningún fichero. Un aviso de coste discreto: en una tienda con tráfico, estos registros crecen deprisa. Aplica la regla de ciclo de vida que vimos en 02-03 para moverlos a Glacier a los 30 días.

Métricas clave del ALB en CloudWatch:

Métrica Qué mide Por qué importa en MercadoFresco
RequestCount Peticiones atendidas Confirma con datos el pico de los viernes de 17:00 a 21:00
TargetResponseTime Tiempo que tardan las instancias Si sube antes que la CPU, el cuello de botella está en RDS
HTTPCode_Target_5XX_Count Errores generados por la aplicación La aplicación falla
HTTPCode_ELB_5XX_Count Errores generados por el balanceador No hay destinos sanos: el 503 clásico
HealthyHostCount Destinos sanos por AZ Si baja de 2, se ha perdido redundancia
UnHealthyHostCount Destinos no sanos Detecta instancias rotas antes de que lo hagan los clientes
ActiveConnectionCount Conexiones abiertas Dimensionar y detectar agotamiento
RejectedConnectionCount Conexiones rechazadas por límite El ALB no ha escalado a tiempo ante un pico brusco

La distinción entre HTTPCode_Target_5XX_Count y HTTPCode_ELB_5XX_Count es la más útil del cuadro: el primero significa «la aplicación devolvió un error», el segundo «no había a quién preguntar». La creación de alarmas y paneles sobre estas métricas se estudia en 05-01; aquí basta con saber qué mirar.

Creación completa por CLI

Partimos de las variables de 03-01 y 03-02 ($VPC_ID, $PUB_A, $PUB_B, $SG_ALB, $SG_TIENDA).

# 1. El balanceador, en las DOS subredes públicas
ALB_ARN=$(aws elbv2 create-load-balancer \
  --profile mercadofresco-dev --region eu-west-1 \
  --name alb-mercadofresco-tienda \
  --type application \
  --scheme internet-facing \
  --ip-address-type ipv4 \
  --subnets "$PUB_A" "$PUB_B" \
  --security-groups "$SG_ALB" \
  --tags Key=Name,Value=alb-mercadofresco-tienda \
         Key=Proyecto,Value=mercadofresco Key=Entorno,Value=produccion \
         Key=Componente,Value=tienda Key=Propietario,Value=marta \
         Key=CentroCoste,Value=operaciones \
  --query 'LoadBalancers[0].LoadBalancerArn' --output text)

# 2. El grupo de destino, con la comprobación de estado bien ajustada
TG_TIENDA=$(aws elbv2 create-target-group \
  --profile mercadofresco-dev --region eu-west-1 \
  --name tg-mercadofresco-tienda \
  --protocol HTTPS --port 443 \
  --vpc-id "$VPC_ID" \
  --target-type instance \
  --health-check-protocol HTTPS \
  --health-check-path /salud \
  --health-check-interval-seconds 15 \
  --health-check-timeout-seconds 5 \
  --healthy-threshold-count 2 \
  --unhealthy-threshold-count 3 \
  --matcher HttpCode=200 \
  --tags Key=Proyecto,Value=mercadofresco Key=Entorno,Value=produccion \
         Key=Componente,Value=tienda Key=Propietario,Value=marta \
         Key=CentroCoste,Value=operaciones \
  --query 'TargetGroups[0].TargetGroupArn' --output text)

# 3. Atributos del grupo de destino
aws elbv2 modify-target-group-attributes --profile mercadofresco-dev --region eu-west-1 \
  --target-group-arn "$TG_TIENDA" \
  --attributes \
    Key=deregistration_delay.timeout_seconds,Value=60 \
    Key=load_balancing.algorithm.type,Value=least_outstanding_requests \
    Key=stickiness.enabled,Value=false

# 4. Escuchador HTTPS (requiere el certificado; ver 03-05 para la validación)
LISTENER_443=$(aws elbv2 create-listener --profile mercadofresco-dev --region eu-west-1 \
  --load-balancer-arn "$ALB_ARN" --protocol HTTPS --port 443 \
  --certificates CertificateArn="$CERT_ARN" \
  --ssl-policy ELBSecurityPolicy-TLS13-1-2-2021-06 \
  --default-actions "Type=forward,TargetGroupArn=$TG_TIENDA" \
  --query 'Listeners[0].ListenerArn' --output text)

# 5. Escuchador HTTP que solo redirige
aws elbv2 create-listener --profile mercadofresco-dev --region eu-west-1 \
  --load-balancer-arn "$ALB_ARN" --protocol HTTP --port 80 \
  --default-actions '[{"Type":"redirect","RedirectConfig":{
      "Protocol":"HTTPS","Port":"443","Host":"#{host}","Path":"/#{path}",
      "Query":"#{query}","StatusCode":"HTTP_301"}}]'

# 6. Conectar el ASG y hacer que confíe en el balanceador
aws autoscaling attach-load-balancer-target-groups \
  --profile mercadofresco-dev --region eu-west-1 \
  --auto-scaling-group-name asg-mercadofresco-tienda \
  --target-group-arns "$TG_TIENDA"

aws autoscaling update-auto-scaling-group \
  --profile mercadofresco-dev --region eu-west-1 \
  --auto-scaling-group-name asg-mercadofresco-tienda \
  --health-check-type ELB --health-check-grace-period 300

# 7. Esperar a que el ALB esté activo y obtener su nombre DNS
aws elbv2 wait load-balancer-available --profile mercadofresco-dev --region eu-west-1 \
  --load-balancer-arns "$ALB_ARN"

aws elbv2 describe-load-balancers --profile mercadofresco-dev --region eu-west-1 \
  --load-balancer-arns "$ALB_ARN" \
  --query 'LoadBalancers[0].DNSName' --output text

El último comando devuelve algo como alb-mercadofresco-tienda-1234567890.eu-west-1.elb.amazonaws.com. Ese nombre es la nueva puerta de entrada de MercadoFresco. Que mercadofresco.example apunte a él es exactamente el trabajo de la lección 03-05.

Comprobación del estado de los destinos, el comando que más se usa a diario:

aws elbv2 describe-target-health --profile mercadofresco-dev --region eu-west-1 \
  --target-group-arn "$TG_TIENDA" \
  --query 'TargetHealthDescriptions[].{
      Instancia:Target.Id, Puerto:Target.Port,
      Estado:TargetHealth.State, Motivo:TargetHealth.Reason,
      Detalle:TargetHealth.Description}' \
  --output table

Los motivos que más aparecen y qué significan de verdad:

Reason Significado Dónde mirar
Elb.RegistrationInProgress Recién registrada, aún sin comprobar Esperar
Elb.InitialHealthChecking Comprobando por primera vez Esperar
Target.Timeout No responde a tiempo Grupo de seguridad (03-02) o aplicación caída
Target.FailedHealthChecks Responde, pero no como se espera Código HTTP distinto del Matcher
Target.ResponseCodeMismatch Devuelve 302, 404, 500… La ruta /salud no existe o redirige
Target.NotInUse El grupo no está asociado a ningún escuchador Falta el paso 4
Target.DeregistrationInProgress Drenando conexiones Normal al reducir capacidad

Target.Timeout es casi siempre lo mismo: el grupo sg-mercadofresco-tienda no acepta el 443 desde sg-mercadofresco-alb. Si seguiste la lección 03-02, ya está resuelto.

Coste del ALB y limpieza

⚠️ Aviso de coste: el ALB cobra por hora aunque no reciba ni una petición

En eu-west-1 el precio tiene dos componentes:

  • Hora de balanceador: ≈ 0,027 USD/h → ≈ 20 USD al mes solo por existir.
  • LCU (Load Balancer Capacity Unit): ≈ 0,008 USD/LCU-hora.

Una LCU es el máximo de cuatro dimensiones medidas por hora: 25 conexiones nuevas por segundo, 3.000 conexiones activas por segundo, 1 GB/hora procesado, o 1.000 evaluaciones de regla por segundo. Se factura solo la dimensión más alta, no la suma.

Estimación para MercadoFresco: unas 2 LCU de media → 2 × 0,008 × 730 ≈ 12 USD/mes. Total, unos 32 USD al mes. Comparado con los 70 USD de los dos NAT Gateway de 03-01, es barato para lo que aporta, pero no está en la capa gratuita.

Para practicar: monta el ALB, verifica que reparte y bórralo el mismo día. Un ALB olvidado cuesta 20 USD al mes indefinidamente y hará saltar el presupuesto de 10 USD que configuramos en 01-02 hacia [email protected].

Limpieza, en orden:

# 1. Desconectar el ASG (si no, volvería a registrar instancias)
aws autoscaling detach-load-balancer-target-groups \
  --profile mercadofresco-dev --region eu-west-1 \
  --auto-scaling-group-name asg-mercadofresco-tienda \
  --target-group-arns "$TG_TIENDA"

# 2. Devolver el ASG a la comprobación básica
aws autoscaling update-auto-scaling-group --profile mercadofresco-dev --region eu-west-1 \
  --auto-scaling-group-name asg-mercadofresco-tienda --health-check-type EC2

# 3. Borrar el balanceador (esto elimina también sus escuchadores)
aws elbv2 delete-load-balancer --profile mercadofresco-dev --region eu-west-1 \
  --load-balancer-arn "$ALB_ARN"
aws elbv2 wait load-balancers-deleted --profile mercadofresco-dev --region eu-west-1 \
  --load-balancer-arns "$ALB_ARN"

# 4. Borrar el grupo de destino (no se puede antes: depende del escuchador)
aws elbv2 delete-target-group --profile mercadofresco-dev --region eu-west-1 \
  --target-group-arn "$TG_TIENDA"

# 5. Comprobar que no queda ninguno vivo en la región
aws elbv2 describe-load-balancers --profile mercadofresco-dev --region eu-west-1 \
  --query 'LoadBalancers[].[LoadBalancerName,State.Code]' --output table

El certificado de ACM no cuesta nada, así que puede dejarse.

El tráfico del viernes, de extremo a extremo

flowchart TB
    U["Clientes<br/>900 pedidos/hora (viernes 17-21 h)"]
    DNS["mercadofresco.example<br/>(Route 53, lección 03-05)"]

    subgraph VPC["vpc-mercadofresco"]
        subgraph PUBS["Subredes públicas"]
            NA["Nodo del ALB<br/>eu-west-1a"]
            NB["Nodo del ALB<br/>eu-west-1b"]
        end
        TG["tg-mercadofresco-tienda<br/>comprobación /salud cada 15 s<br/>least_outstanding_requests"]
        subgraph APPS["Subredes de aplicación (sin IP pública)"]
            I1["tienda-01 · 600 ped/h"]
            I2["tienda-02 · 600 ped/h"]
            I3["tienda-03 · pico"]
            I4["tienda-04 · pico"]
        end
        RDS[("mercadofresco-pedidos<br/>subredes de datos")]
    end

    U --> DNS --> NA
    DNS --> NB
    NA --> TG
    NB --> TG
    TG --> I1
    TG --> I2
    TG -.->|"añadidas por<br/>pico-viernes-tarde"| I3
    TG -.-> I4
    I1 --> RDS
    I2 --> RDS

Y las cuentas del viernes, ahora completas:

Momento Instancias sanas Capacidad Demanda Margen
Martes 11:00 2 1.200 ped/h ~100 ped/h 12×
Viernes 16:45 (acción pico-viernes-tarde) 4 2.400 ped/h ~200 ped/h Preparado
Viernes 19:00 (pico real) 4 2.400 ped/h 900 ped/h 2,6×
Viernes 19:00 con una instancia caída 3 1.800 ped/h 900 ped/h
Viernes 19:00 con la AZ 1a caída entera 2 1.200 ped/h 900 ped/h 1,3× — se aguanta
Viernes 22:00 (cpu-objetivo-60 reduce) 2 1.200 ped/h ~150 ped/h

La penúltima fila es la que justifica todo el trabajo de las tres lecciones: perder una zona de disponibilidad completa en pleno pico del viernes ya no tumba MercadoFresco. El problema 1 queda resuelto.

Errores Comunes y Consejos

Poner el balanceador en una sola subred. AWS lo exige en dos AZ como mínimo, pero si registras instancias solo en una, pierdes toda la redundancia sin ningún aviso.

Usar / como ruta de comprobación de estado. La portada consulta la base de datos, carga el catálogo y tarda cientos de milisegundos. Si la base de datos se ralentiza, todas las instancias fallan a la vez y el ALB devuelve 503 con la aplicación sana. Usa un /salud local y trivial.

Poner un margen de gracia demasiado corto en el ASG. Con --health-check-grace-period 60 y un arranque de dos minutos, el ASG mata cada instancia justo antes de que termine de arrancar, en bucle, gastando dinero sin servir nada.

Dejar el retraso de baja de registro en 300 segundos. Reducir capacidad tras el pico tarda cinco minutos de más. Ajústalo a la duración de tu petición más larga.

Activar sesiones pegajosas para «arreglar» un problema de sesión. Funciona hoy y rompe el escalado mañana. Es deuda técnica: documéntala y planifica sacar la sesión de la instancia.

Olvidar la política del bucket de registros. El comando de activación no da error, pero no aparece ningún fichero en mercadofresco-registros-web.

Confundir HTTPCode_ELB_5XX_Count con HTTPCode_Target_5XX_Count. El primero significa que no hay destinos sanos; el segundo, que la aplicación devuelve errores. Son incidencias distintas y se arreglan en sitios distintos.

Pedir el certificado de ACM en la región equivocada. Para un ALB, en la región del ALB. Para CloudFront, siempre en us-east-1. Lo veremos en 03-04.

Dejar un ALB de pruebas encendido. 20 USD al mes por un recurso que nadie usa. Revisa describe-load-balancers en todas las regiones donde hayas practicado.

Consejo de oro: antes de conectar el ASG, registra una instancia a mano en el grupo de destino y comprueba que pasa a healthy. Si no lo hace, el problema es el grupo de seguridad o el health check, y es mucho más fácil de diagnosticar con una sola instancia que con cuatro.

Ejercicios

Ejercicio 1: diagnosticar un ALB que devuelve 503

Marta despliega el ALB y al abrir su nombre DNS recibe 503 Service Unavailable. En describe-target-health las dos instancias aparecen como unhealthy con motivo Target.Timeout. Enumera al menos cinco causas posibles, ordenadas de más a menos probable, y el comando concreto que confirma o descarta cada una.

Ejercicio 2: diseñar el enrutamiento completo

MercadoFresco necesita, bajo un único ALB: la tienda en la raíz; la API en /api/* con un grupo de destino propio; el panel en admin.mercadofresco.example accesible solo desde la IP de la oficina 81.45.20.7; un 410 Gone para la ruta antigua /tienda-antigua/*; y redirección de todo el tráfico HTTP a HTTPS. Escribe las reglas con sus prioridades y justifica el orden.

Ejercicio 3: calcular el coste y contrastar la capacidad

Con los datos de MercadoFresco (2 instancias en horario normal, 4 los viernes de 17:00 a 21:00, 900 pedidos/hora en el pico, 600 pedidos/hora por instancia), calcula: el coste mensual del ALB suponiendo 3 LCU de media, cuántas instancias harían falta si el negocio creciera a 3.000 pedidos/hora, y si el ASG actual lo soportaría.

Soluciones

Solución 1

Causas, de más a menos probable:

1. El grupo de seguridad de las instancias no acepta tráfico del balanceador. Es la causa número uno de Target.Timeout.

aws ec2 describe-security-groups --profile mercadofresco-dev --region eu-west-1 \
  --group-ids "$SG_TIENDA" \
  --query 'SecurityGroups[0].IpPermissions[].{P:FromPort,Grupos:UserIdGroupPairs[].GroupId}'

Debe aparecer el puerto 443 con $SG_ALB en UserIdGroupPairs.

2. La aplicación no escucha en el puerto del grupo de destino. El grupo apunta al 443 pero la aplicación escucha en el 8080.

aws ssm start-session --profile mercadofresco-dev --region eu-west-1 --target "$ID_INSTANCIA"
# ya dentro:  ss -lntp | grep -E ':(443|8080)'

3. La ruta /salud no existe. Daría Target.ResponseCodeMismatch con un 404, pero si el servidor no responde en absoluto a esa ruta, se manifiesta como Target.Timeout.

# Desde otra instancia de la VPC
curl -k -i https://10.0.32.15/salud

4. Las instancias están en subredes sin ruta y el ALB no las alcanza. Comprobar que las subredes del ASG están en la misma VPC que el balanceador y que las AZ del ALB incluyen las de las instancias.

aws elbv2 describe-load-balancers --profile mercadofresco-dev --region eu-west-1 \
  --load-balancer-arns "$ALB_ARN" --query 'LoadBalancers[0].AvailabilityZones[].[ZoneName,SubnetId]'

5. Una NACL bloquea el tráfico de vuelta. Falta el rango de puertos efímeros en la salida de la subred de aplicación (lección 03-02). Se confirma en los Flow Logs con ACCEPT de entrada y REJECT de salida.

6. Menos probable pero real: el margen de gracia del ASG es corto y las instancias se están reemplazando antes de arrancar; se ve en describe-scaling-activities con reemplazos continuos.

Solución 2

Prioridad Condición Acción Por qué en ese orden
10 host-header = admin.mercadofresco.example AND source-ip = 81.45.20.7/32 forwardtg-mercadofresco-admin Debe evaluarse antes que la regla 20, que niega el resto
20 host-header = admin.mercadofresco.example fixed-response 403 Captura los accesos al panel desde cualquier otra IP
30 path-pattern = /tienda-antigua/* fixed-response 410 Antes que /api/* y que la acción por defecto
40 path-pattern = /api/* forwardtg-mercadofresco-api Tras las reglas específicas
(defecto) forwardtg-mercadofresco-tienda Todo lo demás

Justificación del orden: la clave está en el par 10/20. Las reglas se evalúan por prioridad ascendente y gana la primera que coincida; si la 20 tuviera prioridad menor, capturaría también al tráfico legítimo de la oficina y el panel sería inaccesible para todos. La condición de la regla 10 combina dos campos con AND, que es como funcionan las condiciones múltiples de un ALB.

aws elbv2 create-rule --profile mercadofresco-dev --region eu-west-1 \
  --listener-arn "$LISTENER_443" --priority 10 \
  --conditions '[
    {"Field":"host-header","HostHeaderConfig":{"Values":["admin.mercadofresco.example"]}},
    {"Field":"source-ip","SourceIpConfig":{"Values":["81.45.20.7/32"]}}]' \
  --actions "[{\"Type\":\"forward\",\"TargetGroupArn\":\"$TG_ADMIN\"}]"

aws elbv2 create-rule --profile mercadofresco-dev --region eu-west-1 \
  --listener-arn "$LISTENER_443" --priority 20 \
  --conditions '[{"Field":"host-header","HostHeaderConfig":{"Values":["admin.mercadofresco.example"]}}]' \
  --actions '[{"Type":"fixed-response","FixedResponseConfig":{
      "StatusCode":"403","ContentType":"text/plain","MessageBody":"Acceso restringido"}}]'

El escuchador del 80 se queda con la redirección 301 como acción por defecto, sin reglas: así todo el tráfico HTTP, incluido el del panel, acaba en HTTPS.

Matiz honesto: filtrar por source-ip en el ALB funciona, pero si mañana se pone CloudFront delante (lección 03-04), el ALB verá la IP de CloudFront y no la del cliente. Entonces habría que filtrar en WAF (04-05) o por la cabecera X-Forwarded-For.

Solución 3

Coste mensual del ALB:

  • Horas: 0,027 USD/h × 730 h = 19,71 USD
  • LCU: 3 LCU × 0,008 USD × 730 h = 17,52 USD
  • Total ≈ 37,23 USD/mes

Comparado con la infraestructura de red completa: ALB ≈ 37 USD + 2 NAT Gateway ≈ 70 USD = 107 USD al mes solo en red, sin contar instancias ni base de datos. Es el argumento para revisar en 11-03 si las dos NAT compensan.

Instancias necesarias para 3.000 pedidos/hora:

  • Capacidad estricta: 3.000 ÷ 600 = 5 instancias.
  • Pero hay que sobrevivir a la caída de una zona de disponibilidad completa. Con instancias repartidas en 2 AZ, perder una deja la mitad. Para que la mitad superviviente aguante 3.000 ped/h hacen falta 10 instancias, 5 por AZ.
  • Un compromiso razonable, aceptando degradación en el peor caso: 8 instancias (4 por AZ). Con una AZ caída quedan 4 × 600 = 2.400 ped/h, un 80 % de la demanda: la tienda va lenta pero no cae.

¿Lo soportaría el ASG actual? No. asg-mercadofresco-tienda tiene máximo 4, es decir, 2.400 pedidos/hora. Con 3.000 de demanda se quedaría corto en un 20 % incluso sin fallos. Los cambios necesarios:

aws autoscaling update-auto-scaling-group --profile mercadofresco-dev --region eu-west-1 \
  --auto-scaling-group-name asg-mercadofresco-tienda \
  --min-size 4 --desired-capacity 4 --max-size 10

Y antes de dar el cambio por bueno, hay que comprobar tres cosas más: que RDS aguanta 10 instancias abriendo conexiones (o hace falta un pool, o Aurora, que se ve en 06-03), que las subredes tienen IP libres (con /20 sobran) y que la cuota de instancias de la cuenta lo permite. Escalar la capa web es la parte fácil; el cuello de botella se traslada a la base de datos.

Conclusión

MercadoFresco tiene por fin una puerta de entrada única. Sabes por qué hace falta un balanceador más allá del reparto: comprobaciones de estado, alta disponibilidad entre zonas, terminación de TLS en un solo sitio y la posibilidad de que las instancias vivan en subredes privadas sin IP pública. Distingues los cuatro tipos —ALB para HTTP y HTTPS con enrutamiento por contenido, NLB para capa 4, latencia de microsegundos e IP fija, GWLB para aplicaciones virtuales de seguridad, y el CLB que solo se hereda— y sabes justificar por qué MercadoFresco necesita un ALB.

Conoces su anatomía —balanceador, escuchadores, reglas y grupos de destino— y el detalle de que la comprobación de estado vive en el grupo de destino, no en el balanceador. Y sobre todo has entendido la parte peligrosa: un health check que consulta la base de datos puede marcar todas las instancias como no sanas a la vez y devolver 503 con la aplicación perfectamente sana, o meter al ASG en un bucle de reemplazo. Por eso /salud es local y trivial, /salud/profunda es para la monitorización, y el margen de gracia del ASG es de 300 segundos.

Has conectado asg-mercadofresco-tienda al grupo tg-mercadofresco-tienda para que el registro y la baja sean automáticos, has cambiado la comprobación del ASG a ELB para que detecte aplicaciones muertas y no solo máquinas muertas, y has ajustado el drenaje de conexiones a 60 segundos, el tiempo del pedido más largo. Sabes enrutar por ruta y por host, combinar condiciones, usar respuestas fijas para cortar peticiones maliciosas en el balanceador y redirigir HTTP a HTTPS con un 301 que conserva la ruta. Has pedido un certificado gratuito a ACM con comodín, has elegido la política TLS 1.2/1.3 y entiendes qué es la terminación TLS y para qué sirve SNI —sabiendo que la validación por DNS queda pendiente de la próxima lección. Sabes por qué las sesiones pegajosas son un parche que rompe el escalado y dónde debe vivir la sesión de verdad. Has activado los registros de acceso hacia mercadofresco-registros-web y sabes qué significan RequestCount, TargetResponseTime, HealthyHostCount y la diferencia entre los 5XX del destino y los del balanceador.

Y las cuentas cierran: con cuatro instancias sanas repartidas en dos zonas, MercadoFresco aguanta los 900 pedidos por hora del viernes incluso perdiendo una zona de disponibilidad entera. El problema 1, las caídas de los viernes, queda resuelto.

Queda el dinero. En la lección 02-03 hicimos un cálculo que dolió: el 97 % del coste de S3 es transferencia de salida, porque cada foto del catálogo se descarga íntegra desde Irlanda cada vez que alguien la mira, y ahora además todo el tráfico dinámico pasa por un ALB que cobra por GB procesado. En la lección 03-04, «Amazon CloudFront», pondremos una red de distribución de contenido delante de todo: las fotos se servirán desde la edge location más cercana al cliente, el bucket mercadofresco-catalogo-fotos dejará de ser accesible directamente gracias a Origin Access Control, y veremos con números cuánto baja la factura. El ALB que acabas de montar seguirá ahí detrás, pero recibiendo solo lo que de verdad no se puede cachear.

Curso de AWS

Módulo 1: Introducción a AWS

Módulo 2: Servicios principales de AWS

Módulo 3: Redes y entrega de contenido

Módulo 4: Seguridad e identidad

Módulo 5: Monitorización y gestión

Módulo 6: Bases de datos

Módulo 7: Integración de aplicaciones

Módulo 8: Herramientas para desarrolladores

Módulo 9: Infraestructura como código y gobierno de cuentas

Módulo 10: Contenedores en AWS

Módulo 11: Mejores prácticas y gestión de costos

© Copyright 2026. Todos los derechos reservados