La lliçó anterior va contenidoritzar la botiga de MercadoFresco i la va posar a córrer en un clúster d'ECS. El resultat va ser bo però incomplet: sota el clúster continuen existint instàncies EC2 que cal dimensionar, l'AMI de les quals cal mantenir, que es paguen tant si són plenes com buides, i que triguen dos minuts a arrencar quan el clúster necessita capacitat nova. Vam amagar el problema darrere d'un proveïdor de capacitat; no el vam eliminar.

AWS Fargate l'elimina. És el motor de còmput sense servidor per a contenidors: es declara quanta CPU i quanta memòria necessita cada tasca, i AWS hi posa la resta —l'amfitrió, el kernel, els pedaços, l'aïllament— sense que existeixi cap instància que ningú pugui veure ni llistar. Aquesta lliçó migra el servei de la botiga a Fargate, ajusta el seu autoescalat al pic dels divendres, posa els treballadors de la cua a Fargate Spot i acaba amb la comparativa honesta entre Fargate, EC2 i Lambda.

Avís de cost. Fargate es factura per vCPU-hora i GB-hora consumits per la tasca, amb arrodoniment al segon i un mínim d'un minut. A eu-west-1 ronda els 0,047 USD per vCPU-hora i 0,0051 USD per GB-hora en x86, i aproximadament un 20 % menys en arm64/Graviton. Fargate Spot descompta al voltant del 70 % a canvi de poder ser interromput. No hi ha capa gratuïta per a Fargate: una tasca oblidada d'1 vCPU i 2 GB costa uns 41 USD al mes. Segueix la secció de neteja del final. Els preus són aproximats i orientatius; l'anàlisi de costos a fons és el mòdul 11. Dades i identificadors ficticis.

Contingut

  1. Què és Fargate i què deixa d'existir
  2. El mateix servei sobre EC2 i sobre Fargate
  3. Model de recursos: CPU, memòria i emmagatzematge efímer
  4. x86 i arm64: Graviton i l'estalvi real
  5. Diferències operatives: sense SSH, sense hostPort, sense DaemonSet
  6. ECS Exec: depurar sense servidor a tocar
  7. Registres amb FireLens i Fluent Bit
  8. L'arrencada de tasques i el pic dels divendres
  9. Migrar el servei de la botiga a Fargate
  10. Punts d'enllaç de VPC: deixar de dependre del NAT
  11. Autoescalat: seguiment, passos i programació
  12. Fargate Spot i els treballadors de la cua
  13. Tasques puntuals i programades amb EventBridge Scheduler
  14. Integració al pipeline i blue/green
  15. El servei en CDK amb un constructe L3
  16. Fargate enfront d'EC2 enfront de Lambda
  17. App Runner: un esglaó més de gestió
  18. Cost comparat i neteja
  19. Errors habituals i consells
  20. Exercicis
  21. Conclusió

Què és Fargate i què deixa d'existir

Fargate no és un servei que es contracti a part ni una consola diferent: és un tipus de llançament —i, amb més precisió, un proveïdor de capacitat— dins del mateix Amazon ECS de la lliçó anterior. Les definicions de tasca, els serveis, els grups de destinació, l'autoescalat i els rols són els mateixos objectes. El que canvia és on s'executa la tasca i qui és responsable de la màquina.

El que deixa d'existir Què significava abans Què implica ara
L'AMI Una imatge de sistema operatiu que cal mantenir i actualitzar Només existeix la teva imatge de contenidor
L'apedaçament de l'amfitrió Finestra mensual, reinicis esglaonats, CVE del kernel AWS apedaça l'amfitrió sense que te n'assabentis
L'escalat del clúster Un ASG, un proveïdor de capacitat, targetCapacity No hi ha clúster de màquines que escalar
L'empaquetatge de tasques Estratègies binpack i spread, límits d'ENI, buits que no quadren Cada tasca és la seva pròpia unitat
La capacitat ociosa Instàncies enceses a les 4 de la matinada d'un dimarts Es paga la tasca, no el buit
L'accés a l'amfitrió SSH, docker exec, volums de l'amfitrió ECS Exec; vegeu més avall
El que continua sent teu Per què importa
La imatge La seva mida, les seves dependències i les seves vulnerabilitats continuen sent responsabilitat teva
CPU i memòria de la tasca Ja no hi ha instància que absorbeixi un error de dimensionament: aquí es paga exacte
La xarxa Subxarxes, grups de seguretat, rutes i punts d'enllaç continuen sent decisions teves
Els permisos Rol d'execució i rol de tasca, exactament igual que a 10-01
La disponibilitat Repartir tasques entre AZ, dimensionar el mínim, definir l'autoescalat

La frase que resumeix el canvi: Fargate no elimina la feina d'operar una aplicació, elimina la feina d'operar un servidor. La Marta continua havent de decidir quantes tasques hi ha un divendres a les 19:00; el que ja no ha de decidir és de quina mida són les màquines que les allotgen.

Tècnicament, cada tasca de Fargate s'executa en el seu propi entorn aïllat per virtualització lleugera —la mateixa tecnologia que sustenta Lambda—, cosa que resol l'advertiment de 10-01 sobre el kernel compartit: dues tasques no comparteixen mai kernel, ni tan sols dues tasques teves.

El mateix servei sobre EC2 i sobre Fargate

graph TB
  subgraph EC2["ECS sobre EC2 (10-01)"]
    A1[ALB] --> S1[Servei ECS]
    S1 --> I1["Instancia m5.large<br/>AMI + agent ECS<br/>APEDACAR"]
    S1 --> I2["Instancia m5.large<br/>AMI + agent ECS<br/>APEDACAR"]
    I1 --> T1[Tasca]
    I1 --> T2[Tasca]
    I2 --> T3[Tasca]
    I2 --> H["Espai pagat<br/>i buit"]
    ASG["ASG + proveidor de capacitat<br/>arrencada: 2 minuts"] -.gestiona.-> I1
    ASG -.gestiona.-> I2
  end
  subgraph FG["ECS sobre Fargate (10-02)"]
    A2[ALB] --> S2[Servei ECS]
    S2 --> F1["Tasca 1 vCPU / 2 GB<br/>AZ a"]
    S2 --> F2["Tasca 1 vCPU / 2 GB<br/>AZ a"]
    S2 --> F3["Tasca 1 vCPU / 2 GB<br/>AZ b"]
    S2 --> F4["Tasca 1 vCPU / 2 GB<br/>AZ b"]
    AAS["Application Auto Scaling<br/>arrencada: 30-45 segons"] -.gestiona.-> S2
  end

Els dos diagrames tenen el mateix ALB, el mateix servei i les mateixes tasques. La diferència és a la capa intermèdia: al primer hi ha dues caixes que representen màquines —amb la seva AMI, el seu agent i el seu buit pagat—; al segon no n'hi ha cap.

Model de recursos: CPU, memòria i emmagatzematge efímer

A Fargate, cpu i memory a escala de tasca són obligatoris i només admeten combinacions concretes. No es pot demanar 1 vCPU amb 1 GB, ni 3 vCPU amb el que sigui.

vCPU (cpu) Memòria vàlida (memory) Increment Cas típic a MercadoFresco
256 (0,25) 512 MB, 1 GB, 2 GB fix Sidecar, tasca puntual petita
512 (0,5) 1 a 4 GB 1 GB Treballador de cola-mercadofresco-correo
1024 (1) 2 a 8 GB 1 GB La botiga i els treballadors de comandes
2048 (2) 4 a 16 GB 1 GB Càrrega nocturna cap a Redshift
4096 (4) 8 a 30 GB 1 GB Processos d'anàlisi puntuals
8192 (8) 16 a 60 GB 4 GB Poques vegades: convé repartir en més tasques
16384 (16) 32 a 120 GB 8 GB Gairebé mai

Dues conseqüències pràctiques:

  • La combinació es tria abans de conèixer la càrrega real, i gairebé sempre malament. El mètode correcte és el del mòdul 5: mirar CpuUtilized i MemoryUtilized de Container Insights durant dues setmanes, prendre el percentil 95 i afegir-hi un 30 % de marge. Sobredimensionar a Fargate costa diners des del primer segon, perquè no hi ha cap instància ja pagada on amagar l'excés.
  • La granularitat castiga les aplicacions amb poca CPU i molta memòria. Una tasca que necessita 6 GB obliga a demanar almenys 1 vCPU, encara que en faci servir el 5 %. Quan això passa molt, convé revisar si l'aplicació hauria de ser una Lambda o si hi ha una fuita de memòria.

L'emmagatzematge efímer són 20 GB per omissió, ampliables fins a 200 GB amb ephemeralStorage. Es cobra només el que excedeixi els 20 GB gratuïts. És un disc temporal que desapareix en acabar la tasca: serveix per descomprimir un fitxer o per a una memòria cau local, mai per a estat. Quan cal persistència compartida, es munta EFS (02-02), que Fargate admet de manera nativa.

{
  "family": "mercadofresco-carga-analitica",
  "requiresCompatibilities": ["FARGATE"],
  "networkMode": "awsvpc",
  "cpu": "2048", "memory": "8192",
  "ephemeralStorage": { "sizeInGiB": 60 },
  "runtimePlatform": { "cpuArchitecture": "ARM64", "operatingSystemFamily": "LINUX" }
}

x86 i arm64: Graviton i l'estalvi real

Fargate executa tasques en dues arquitectures: X86_64 i ARM64, aquesta última sobre processadors AWS Graviton. El canvi es fa amb un camp de la definició de tasca, però exigeix que la imatge estigui construïda per a aquesta arquitectura.

Aspecte x86_64 arm64 (Graviton)
Preu per vCPU-hora ~0,047 USD ~0,037 USD (-20 %)
Rendiment Referència Igual o millor en càrregues web, Python, Java, Node
Imatge L'habitual Cal construir-la per a linux/arm64
Compatibilitat Total Falla amb binaris natius només x86 o rodes de Python sense versió arm
Disponible a Fargate Spot

La construcció multiarquitectura es resol a CodeBuild amb docker buildx:

docker buildx create --use --name multiarc
docker buildx build --platform linux/amd64,linux/arm64 \
  --tag "${URI}:${ETIQUETA}" --push .
# Publica un index de manifests: ECR guarda les dues imatges sota la mateixa etiqueta
# i cada tasca descarrega la que correspon a la seva arquitectura.

Per a MercadoFresco l'estalvi és real i mesurable: la botiga són 2 tasques base més fins a 2 al pic, d'1 vCPU i 2 GB. Passar a Graviton baixa el cost mensual del servei d'uns 85 USD a uns 68 USD, un 20 % sense tocar una línia de codi de negoci. El requisit és provar-ho: el Luis construeix la imatge per a les dues arquitectures, desplega arm64 a preproducció durant una setmana, compara latència i errors al tauler mercadofresco-produccion, i només llavors canvia producció.

El risc concret és el de les dependències: una roda de Python que només publica binaris x86 obliga a compilar en la construcció —cosa que l'etapa constructor del Dockerfile de 10-01 ja permet— o a bloquejar el canvi. És preferible descobrir-ho a CodeBuild que en un desplegament.

Diferències operatives: sense SSH, sense hostPort, sense DaemonSet

Fargate imposa restriccions que no són arbitràries: es deriven del fet que l'amfitrió no existeix per a tu.

Restricció Per què Què es fa en el seu lloc
Sense SSH ni docker exec No hi ha màquina a la qual connectar-se ECS Exec (a continuació)
Sense hostPort diferent del containerPort No hi ha ports de l'amfitrió que mapar awsvpc dona una IP per tasca; no hi ha conflicte
Només mode de xarxa awsvpc Cada tasca és la seva pròpia ENI Grups de seguretat per tasca, grup de destinació de tipus ip
Sense DaemonSet ni tasques de tipus DAEMON No hi ha nodes on posar-ne un per node Sidecars: FireLens, X-Ray, OTel dins de cada tasca
Sense volums de l'amfitrió ni privileged L'amfitrió no és teu Volums efímers, EFS, i linuxParameters limitats
Sense GPU ni famílies d'instància especials No tries la màquina EC2 continua existint per a aquests casos
Sense awsvpcTrunking per gestionar No hi ha instància amb límit d'ENI Desapareix un dels paranys cars de 10-01

La restricció que més incomoda al principi és la primera, i la segona que més, la del DaemonSet: molta gent executava un contenidor de recollida de registres per instància. A Fargate aquest patró se substitueix per un sidecar dins de cada tasca, cosa que costa una mica de CPU i memòria per tasca però elimina la coordinació entre nodes.

ECS Exec: depurar sense servidor a tocar

ECS Exec obre una sessió d'ordres dins d'un contenidor en execució fent servir AWS Systems Manager, sense ports oberts, sense claus SSH i sense bastió. Requereix tres coses:

  1. El servei o la tasca amb --enable-execute-command.
  2. El rol de la tasca —no el d'execució— amb permisos de canal d'SSM.
  3. L'agent d'SSM, que Fargate ja inclou a partir de la versió de plataforma 1.4.
{"Version": "2012-10-17", "Statement": [{
  "Effect": "Allow", "Resource": "*",
  "Action": ["ssmmessages:CreateControlChannel", "ssmmessages:CreateDataChannel",
             "ssmmessages:OpenControlChannel", "ssmmessages:OpenDataChannel"]
}]}
aws ecs execute-command --cluster ecs-mercadofresco \
  --task 9f2c1b7a4e0d4a6f8b3c5d7e1a2b3c4d \
  --container tienda --interactive --command "/bin/sh"

Tres advertiments que cal interioritzar abans de fer-lo servir a producció:

  • Tot queda auditat a CloudTrail (05-03) amb l'esdeveniment ExecuteCommand: qui, quan, en quina tasca i amb quina ordre. A més es pot exigir que la sessió es registri a CloudWatch Logs o a S3 amb executeCommandConfiguration al clúster, xifrant amb alias/mercadofresco-datos. A MercadoFresco, fer servir ECS Exec a producció dispara una notificació a alertas-mercadofresco: no està prohibit, està vigilat.
  • Els canvis fets dins d'un contenidor no sobreviuen. Editar un fitxer de configuració a la tasca funciona fins que la tasca es reposa, i llavors desapareix silenciosament. ECS Exec serveix per diagnosticar, no per arreglar.
  • Amb readonlyRootFilesystem: true el sistema de fitxers és de només lectura, que és exactament el que es vol: si necessites escriure per depurar, la resposta sol ser que falta un registre.

A la pràctica, el 90 % del que la gent anava a buscar per SSH ja és a CloudWatch Logs Insights o a X-Ray. ECS Exec és per al 10 % restant: comprovar una resolució DNS, verificar que una variable d'entorn va arribar com s'esperava o confirmar que el procés escolta al port correcte.

Registres amb FireLens i Fluent Bit

El controlador awslogs de 10-01 continua funcionant i és el correcte per omissió. Quan cal més —encaminar cap a diversos destins, filtrar abans d'enviar, reescriure el format o enviar còpia a un sistema extern—, la resposta a Fargate és FireLens: un sidecar de Fluent Bit que ECS configura automàticament.

[
  {
    "name": "registro",
    "image": "public.ecr.aws/aws-observability/aws-for-fluent-bit:stable",
    "essential": true,
    "firelensConfiguration": { "type": "fluentbit", "options": { "enable-ecs-log-metadata": "true" } },
    "cpu": 64, "memoryReservation": 128
  },
  {
    "name": "tienda",
    "image": "555566667777.dkr.ecr.eu-west-1.amazonaws.com/mercadofresco/tienda@sha256:9c1e...f4a2",
    "essential": true,
    "logConfiguration": {
      "logDriver": "awsfirelens",
      "options": { "Name": "cloudwatch_logs", "region": "eu-west-1",
                   "log_group_name": "/ecs/mercadofresco-tienda", "log_stream_prefix": "tienda-",
                   "auto_create_group": "false" }
    }
  }
]

El cost de FireLens és un contenidor més per tasca, uns 64 CPU i 128 MB, que en un servei de quatre tasques són diners de debò. La regla de MercadoFresco: awslogs per omissió, FireLens només quan hi hagi un requisit que awslogs no cobreixi, com filtrar els registres d'accés amb dades personals abans que surtin de la tasca.

L'arrencada de tasques i el pic dels divendres

Aquest és el punt pel qual existeix la lliçó. Una tasca de Fargate travessa aquestes fases:

  1. Aprovisionament (PROVISIONING): es crea l'ENI a la subxarxa i se li associa el grup de seguretat. De 3 a 10 segons.
  2. Descàrrega de la imatge (PENDING): s'autentica a ECR i es descarreguen les capes que faltin. De 5 a 25 segons segons la mida de la imatge i si hi ha punt d'enllaç de VPC.
  3. Arrencada del contenidor: s'executa l'ENTRYPOINT. D'1 a 5 segons.
  4. Comprovacions d'estat: l'ALB registra la destinació i espera els encerts consecutius. De 15 a 40 segons segons la configuració del grup de destinació.
Fase ASG amb AMI (abans) Fargate (ara)
Arrencada de la màquina 60-75 s (BIOS, kernel, cloud-init) 0 s: no hi ha màquina
Preparació de xarxa Inclosa 3-10 s (ENI)
Obtenció de l'artefacte Inclosa a l'AMI 5-25 s (imatge des d'ECR)
Arrencada de l'aplicació 20-30 s 1-5 s
Registre i comprovacions 20-40 s 15-40 s
Total fins a rebre trànsit ≈ 120 s ≈ 35-45 s

El que significa per al divendres a les 19:00 amb 900 comandes/hora és concret: quan l'alarma d'ALBRequestCountPerTarget supera el llindar, la capacitat nova comença a atendre peticions als 40 segons en lloc dels dos minuts. Amb la pujada de trànsit mesurada a MercadoFresco —de 300 a 900 comandes/hora en uns vuit minuts—, aquests 80 segons de diferència són la frontera entre una latència que puja una mica i una latència que dispara mercadofresco-alb-latencia-alta.

I hi ha una conseqüència menys òbvia i més valuosa: amb arrencades de 40 segons, es pot permetre un mínim més baix. Abans calien 2 instàncies sempre enceses per absorbir el que l'ASG trigava a reaccionar. Amb Fargate, el mínim pot continuar sent 2 tasques per disponibilitat —mai menys, per sobreviure a la pèrdua d'una AZ—, però el marge extra que es mantenia «per si de cas» deixa de ser necessari.

La palanca que redueix la fase 2 és la mida de la imatge i la ruta fins a ECR. La imatge de 220 MB de la botiga triga uns 8 segons des d'un punt d'enllaç de VPC i uns 20 a través del NAT. És un altre argument per al Dockerfile acurat de 10-01 i per a la secció següent.

Migrar el servei de la botiga a Fargate

El canvi, sorprenentment, és petit: la definició de tasca de 10-01 ja declarava requiresCompatibilities: ["EC2", "FARGATE"] i mode awsvpc, precisament per a això.

Pas 1: fixar CPU i memòria amb dades, no amb intuïció. Container Insights fa dues setmanes que mesura. La consulta que la Marta executa:

aws cloudwatch get-metric-statistics --namespace ECS/ContainerInsights \
  --metric-name CpuUtilized --statistics Maximum p95 --period 300 \
  --dimensions Name=ServiceName,Value=svc-mercadofresco-tienda Name=ClusterName,Value=ecs-mercadofresco \
  --start-time 2026-07-15T00:00:00Z --end-time 2026-07-29T00:00:00Z

El percentil 95 de CPU és de 0,62 vCPU i el de memòria d'1,4 GB, amb un màxim absolut de 0,81 vCPU al pic del divendres. La combinació vàlida més ajustada per sobre d'això amb marge és 1 vCPU i 2 GB. Baixar a 0,5 vCPU / 2 GB seria temptador —estalvia un 25 %— però deixa la tasca del divendres al 160 % de la seva CPU: la latència es degradaria exactament quan importa.

Pas 2: crear el servei amb el proveïdor de capacitat de Fargate.

aws ecs create-service --cluster ecs-mercadofresco --region eu-west-1 \
  --service-name svc-mercadofresco-tienda-fg --task-definition mercadofresco-tienda:24 \
  --desired-count 4 \
  --capacity-provider-strategy capacityProvider=FARGATE,weight=1,base=2 \
  --platform-version LATEST \
  --network-configuration 'awsvpcConfiguration={subnets=[snet-mercadofresco-app-a,snet-mercadofresco-app-b],
      securityGroups=[sg-mercadofresco-tienda],assignPublicIp=DISABLED}' \
  --load-balancers 'targetGroupArn=...targetgroup/tg-mercadofresco-tienda/abc123,containerName=tienda,containerPort=8080' \
  --health-check-grace-period-seconds 45 \
  --deployment-configuration '{"minimumHealthyPercent": 100, "maximumPercent": 200,
      "deploymentCircuitBreaker": {"enable": true, "rollback": true}}' \
  --enable-execute-command --propagate-tags SERVICE

Tres detalls de l'ordre:

  • assignPublicIp=DISABLED amb subxarxes privades. Les tasques van a snet-mercadofresco-app-a i -b, sense IP pública. Això és el correcte i el que obliga a la secció següent: sense IP pública, la tasca necessita una ruta cap a ECR, S3, CloudWatch Logs i Secrets Manager, i aquesta ruta és un NAT car o uns punts d'enllaç barats.
  • No hi ha --placement-strategy. Les estratègies de col·locació són d'EC2. Fargate reparteix les tasques entre les subxarxes declarades, de manera que la disponibilitat s'obté declarant subxarxes de les dues AZ, no amb una estratègia.
  • --platform-version LATEST. La versió de plataforma és l'equivalent a l'AMI de l'amfitrió, i la gestiona AWS. Fixar-la a una versió concreta només té sentit si una novetat trenca alguna cosa, i llavors és una mesura temporal, no permanent.

Pas 3: convivència i tall. Igual que a 10-01, l'ALB reparteix per pesos entre el servei d'EC2 i el de Fargate: 90/10, després 50/50, després 0/100 al llarg de dues setmanes, vigilant TargetResponseTime i HTTPCode_Target_5XX. El dia que el pes arriba a 100, l'ASG del clúster d'EC2 s'esborra i amb ell l'AMI, la plantilla de llançament i el cicle d'apedaçament.

Punts d'enllaç de VPC: deixar de dependre del NAT

Una tasca de Fargate en subxarxa privada parla amb diversos serveis d'AWS només per arrencar. Si aquesta comunicació surt pel NAT, es paga dues vegades: l'hora del NAT i cada gigabyte processat.

Punt d'enllaç Tipus Per a què Què falla sense ell
com.amazonaws.eu-west-1.ecr.api Interfície Autenticació i metadades d'ECR CannotPullContainerError
com.amazonaws.eu-west-1.ecr.dkr Interfície Protocol de descàrrega d'imatges CannotPullContainerError
com.amazonaws.eu-west-1.s3 Passarel·la Les capes d'imatge viuen a S3 La descàrrega es penja i expira
com.amazonaws.eu-west-1.logs Interfície CloudWatch Logs La tasca arrenca i no es veu ni un registre
com.amazonaws.eu-west-1.secretsmanager Interfície Resoldre els secrets ResourceInitializationError
com.amazonaws.eu-west-1.ssm Interfície Parameter Store Igual que l'anterior
com.amazonaws.eu-west-1.ssmmessages Interfície ECS Exec ECS Exec no connecta
com.amazonaws.eu-west-1.kms Interfície Desxifrar secrets i imatge Falla el desxifratge

El d'S3 és el que més s'oblida i el més important: és de tipus passarel·la, és gratuït i sense ell la descàrrega d'imatges no funciona encara que els dos d'ECR estiguin posats. MercadoFresco ja tenia vpce-mercadofresco-s3 des del mòdul 3, així que aquest està resolt.

for SERVEI in ecr.api ecr.dkr logs secretsmanager ssm ssmmessages kms; do
  aws ec2 create-vpc-endpoint --vpc-id vpc-mercadofresco \
    --vpc-endpoint-type Interface \
    --service-name "com.amazonaws.eu-west-1.${SERVEI}" \
    --subnet-ids snet-mercadofresco-app-a snet-mercadofresco-app-b \
    --security-group-ids sg-mercadofresco-endpoints \
    --private-dns-enabled \
    --tag-specifications 'ResourceType=vpc-endpoint,Tags=[{Key=Proyecto,Value=mercadofresco},
        {Key=Entorno,Value=produccion},{Key=Componente,Value=endpoints},
        {Key=Propietario,Value=plataforma},{Key=CentroCoste,Value=tecnologia}]'
done

El càlcul de l'estalvi per a MercadoFresco, amb 4,8 desplegaments per setmana, reposicions de tasques i escalat diari:

Concepte Amb NAT Amb punts d'enllaç d'interfície
Descàrrega d'imatges ~55 GB/mes × 0,045 USD = 2,50 USD Trànsit pel punt d'enllaç: ~0,55 USD
Registres i crides a l'API ~30 GB/mes × 0,045 = 1,35 USD ~0,30 USD
Cost fix 2 NAT × 0,045 USD/h ≈ 66 USD/mes 7 punts d'enllaç × 2 AZ × 0,011 USD/h ≈ 112 USD/mes
Total ≈ 70 USD/mes ≈ 113 USD/mes

I aquí convé ser honest en lloc de repetir l'eslògan: amb set punts d'enllaç en dues AZ, els punts d'enllaç surten més cars que el NAT en una arquitectura de la mida de MercadoFresco. L'argument a favor no és només el preu, en són altres tres: el trànsit no surt de la xarxa d'AWS, cosa que és un requisit de seguretat defensable davant d'una auditoria; l'arrencada de tasques és més ràpida i més previsible; i el NAT deixa de ser un punt únic de fallada per a l'arrencada. La decisió de la Marta és intermèdia i raonada: punts d'enllaç per a ECR, S3 i Logs —els del camí crític d'arrencada, que són quatre i costen uns 64 USD— i mantenir el NAT per a la resta, sabent que al mòdul 11 es revisarà si compensa.

Autoescalat: seguiment, passos i programació

Els tres tipus de política es combinen, i cadascun resol un problema diferent.

Tipus Com decideix Fortalesa Debilitat
Seguiment de destinació Manté una mètrica en un valor Simple, s'autoregula Reacciona després del canvi
Escalat per passos Llindars amb salts diferents Resposta agressiva davant de salts grans Cal calibrar els esglaons a mà
Escalat programat Rellotge Actua abans que arribi la càrrega Cec davant de l'inesperat

La configuració completa de MercadoFresco fa servir els tres. El seguiment de destinació sobre ALBRequestCountPerTarget de 10-01 es manté com a base. A sobre, l'escalat programat del divendres, que és la peça que faltava:

DESTI="--service-namespace ecs --scalable-dimension ecs:service:DesiredCount \
  --resource-id service/ecs-mercadofresco/svc-mercadofresco-tienda-fg"

# 16:45, quinze minuts abans del pic: pujar el minim a 6 tasques.
aws application-autoscaling put-scheduled-action $DESTI \
  --scheduled-action-name pico-viernes-inicio \
  --schedule "cron(45 16 ? * FRI *)" --timezone "Europe/Madrid" \
  --scalable-target-action MinCapacity=6,MaxCapacity=20

# 21:30, mitja hora despres del pic: tornar el minim a 2.
aws application-autoscaling put-scheduled-action $DESTI \
  --scheduled-action-name pico-viernes-fin \
  --schedule "cron(30 21 ? * FRI *)" --timezone "Europe/Madrid" \
  --scalable-target-action MinCapacity=2,MaxCapacity=20

Tres decisions de disseny en aquestes vuit línies:

  • Es programa el mínim, no el nombre desitjat. Fixar DesiredCount desactivaria de fet el seguiment de destinació durant la finestra. Pujant el mínim, la capacitat està garantida i el seguiment continua podent créixer per sobre si el divendres és millor del previst.
  • --timezone "Europe/Madrid". Sense això, el cron és UTC i a l'estiu el pic s'avança una hora respecte de l'acció programada. És un error que només apareix en canviar l'hora, a l'octubre, quan ningú no recorda haver tocat res.
  • Quinze minuts abans i mitja hora després. Abans, perquè les tasques estiguin sanes quan arribi el trànsit; després, amb generositat, perquè baixar massa aviat és el que provoca l'oscil·lació que es veu com a pics de latència a les 21:05.

El cost d'aquesta finestra és fàcil de calcular i de defensar: 4 tasques extra × 5 hores × 4,3 divendres × 0,057 USD/h ≈ 4,9 USD al mes. És probablement els millors diners que gasta MercadoFresco.

Fargate Spot i els treballadors de la cua

Fargate Spot executa tasques sobre capacitat sobrant d'AWS amb un descompte proper al 70 %, a canvi que AWS la pugui reclamar. Quan ho fa:

  1. Emet un esdeveniment de canvi d'estat a EventBridge i envia SIGTERM al contenidor.
  2. Espera el stopTimeout de la definició de tasca, amb un màxim de dos minuts.
  3. Envia SIGKILL i la tasca desapareix.

Dos minuts d'avís són molt o poc segons la càrrega:

Càrrega de MercadoFresco Fargate Spot? Raó
Botiga (svc-mercadofresco-tienda-fg) No És trànsit d'usuari: una interrupció durant el pic del divendres és exactament el que estem evitant
Treballadors de cola-mercadofresco-pedidos Sí, parcialment El missatge torna a la cua en expirar la visibilitat i un altre treballador el processa; amb idempotència (07-05) no hi ha duplicats
Treballadors de -correo, -almacen, -analitica Sí, gairebé tot Tolerància màxima: res no és síncron ni urgent
Càrrega nocturna a Redshift Es reintenta; si triga deu minuts més, no ho nota ningú
Tasques puntuals de migració de dades No Una interrupció a mitges pot deixar estat inconsistent

La manera correcta d'aplicar-ho no és «tot Spot» sinó un repartiment per proveïdors de capacitat, que garanteix un terra sota demanda:

aws ecs update-service --cluster ecs-mercadofresco \
  --service svc-mercadofresco-trabajadores \
  --capacity-provider-strategy \
      capacityProvider=FARGATE,weight=1,base=1 \
      capacityProvider=FARGATE_SPOT,weight=4,base=0 \
  --force-new-deployment

base=1 al proveïdor sota demanda significa que la primera tasca sempre és estable; el weight reparteix totes les altres en proporció 1 a 4. Amb 10 tasques: 1 base + 9 repartides com a 1,8 sota demanda i 7,2 Spot, és a dir, aproximadament 3 sota demanda i 7 Spot.

Escenari de treballadors Composició Cost mensual aproximat
Tot sota demanda 10 × (0,5 vCPU / 1 GB) ≈ 190 USD
Repartiment 1:4 amb base 1 3 sota demanda + 7 Spot ≈ 97 USD
Tot Spot (no recomanat) 10 Spot ≈ 57 USD

L'estalvi del repartiment 1:4 és de gairebé el 50 % i manté un terra que sobreviu a una retirada massiva de capacitat Spot. El requisit tècnic que ho fa segur és el de l'exercici de 10-01: gestor de SIGTERM que acaba el missatge en curs i no en demana un altre, amb stopTimeout: 120 i temps de visibilitat de la cua folgat.

Tasques puntuals i programades amb EventBridge Scheduler

No tot és un servei. La càrrega nocturna que alimenta wg-mercadofresco-analitica (06-04) s'executa un cop al dia i acaba. A EC2 això era una instància encesa o un cron en una màquina que algú havia de cuidar; a Fargate és una tasca puntual programada.

aws scheduler create-schedule --name mercadofresco-carga-analitica-nocturna \
  --schedule-expression "cron(0 3 * * ? *)" --schedule-expression-timezone "Europe/Madrid" \
  --flexible-time-window '{"Mode": "FLEXIBLE", "MaximumWindowInMinutes": 30}' \
  --target '{
    "Arn": "arn:aws:ecs:eu-west-1:111122223333:cluster/ecs-mercadofresco",
    "RoleArn": "arn:aws:iam::111122223333:role/rol-scheduler-mercadofresco",
    "EcsParameters": {
      "TaskDefinitionArn": "arn:aws:ecs:eu-west-1:111122223333:task-definition/mercadofresco-carga-analitica:7",
      "LaunchType": "FARGATE", "TaskCount": 1,
      "CapacityProviderStrategy": [{"capacityProvider": "FARGATE_SPOT", "weight": 1}],
      "NetworkConfiguration": {"awsvpcConfiguration": {
        "Subnets": ["snet-mercadofresco-app-a", "snet-mercadofresco-app-b"],
        "SecurityGroups": ["sg-mercadofresco-tienda"], "AssignPublicIp": "DISABLED"}}
    },
    "RetryPolicy": {"MaximumRetryAttempts": 2, "MaximumEventAgeInSeconds": 3600},
    "DeadLetterConfig": {"Arn": "arn:aws:sqs:eu-west-1:111122223333:mercadofresco-pedidos-fallidos"}
  }'

El que és rellevant d'aquesta configuració: la finestra flexible de 30 minuts deixa que AWS triï el moment dins de la finestra, cosa que redueix la contenció i encaixa perfectament amb Spot; la política de reintents converteix una fallada transitòria en un reintent automàtic; i la DLQ garanteix que una fallada persistent deixa rastre en lloc de desaparèixer. És el mateix patró que 07-05 aplicat a una tasca programada.

Per a una execució puntual —una migració, una reparació de dades— n'hi ha prou amb aws ecs run-task amb la mateixa configuració de xarxa i --launch-type FARGATE. Si la feina té diversos passos amb dependències entre ells, l'eina correcta és Step Functions (07-04), que pot llançar tasques d'ECS i esperar que acabin.

Integració al pipeline i blue/green

El pipeline-mercadofresco-tienda del mòdul 8 canvia poc: on abans hi havia un desplegament de CodeDeploy sobre un ASG, ara hi ha un desplegament sobre un servei d'ECS.

graph LR
  G["GitHub<br/>mercadofresco-tienda<br/>conn-mercadofresco-github"] --> B["CodeBuild<br/>build-mercadofresco-tienda<br/>docker build + push"]
  B --> E["ECR 555566667777<br/>mercadofresco/tienda:v1.7.0-c4d8e12"]
  E --> R["Replicacio<br/>a 111122223333"]
  R --> P["CodePipeline<br/>desplegament"]
  P --> Q["Lambda<br/>mercadofresco-puerta-calidad<br/>escaneig + proves"]
  Q --> D["CodeDeploy blue/green<br/>app-mercadofresco-tienda"]
  D --> V["tg-mercadofresco-verde<br/>port de proves 8443"]
  V --> S["build-mercadofresco-humo"]
  S --> T["tg-mercadofresco-tienda<br/>transit real"]

El blue/green de CodeDeploy sobre ECS funciona diferent que sobre EC2, i la diferència és una millora: CodeDeploy crea un conjunt de tasques nou complet amb la revisió nova, el registra a tg-mercadofresco-verde, permet executar les proves de fum contra el port de proves de l'ALB sense trànsit real, i només llavors desplaça l'oient de producció cap al grup verd. El conjunt blau es manté durant el temps d'espera de terminació, de manera que una reversió és un canvi d'oient: segons.

# appspec.yaml per a CodeDeploy sobre ECS
version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: <TASK_DEFINITION>          # ho substitueix el pipeline
        LoadBalancerInfo:
          ContainerName: "tienda"
          ContainerPort: 8080
        PlatformVersion: "LATEST"
Hooks:
  - AfterAllowTestTraffic: "arn:aws:lambda:eu-west-1:111122223333:function:mercadofresco-puerta-calidad"

Amb la configuració de desplegament canària ECSCanary10Percent5Minutes, el 10 % del trànsit va al conjunt verd durant 5 minuts; si mercadofresco-alb-latencia-alta o mercadofresco-pedidos-fallidos salten en aquest interval, CodeDeploy reverteix sol. És la millora sobre el circuit breaker de 10-01: aquell detecta tasques que no arrenquen; aquest detecta tasques que arrenquen i responen malament.

Les mètriques DORA de MercadoFresco milloren on era d'esperar: la restauració passa de 4 minuts a menys d'1, perquè revertir ja no significa desplegar res, només moure un oient.

El servei en CDK amb un constructe L3

Tot l'anterior són unes vint línies al projecte infra-cdk/ de 09-02, gràcies a un constructe de nivell 3 que crea l'ALB, el grup de destinació, el servei, la definició de tasca, els rols i el grup de registres.

import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecsp from 'aws-cdk-lib/aws-ecs-patterns';

const servei = new ecsp.ApplicationLoadBalancedFargateService(this, 'Tienda', {
  cluster,
  serviceName: `svc-mercadofresco-tienda-${config.nombre}`,
  cpu: 1024,
  memoryLimitMiB: 2048,
  desiredCount: config.nombre === 'produccion' ? 4 : 2,
  runtimePlatform: { cpuArchitecture: ecs.CpuArchitecture.ARM64 },
  taskImageOptions: {
    image: ecs.ContainerImage.fromEcrRepository(repositori, etiqueta),   // per digest en produccio
    containerPort: 8080,
    environment: { ENTORNO: config.nombre, COLA_PEDIDOS: cola.queueName },
    secrets: {
      BD_CONTRASENA: ecs.Secret.fromSecretsManager(secretRds, 'password'),
      ENDPOINT_CACHE: ecs.Secret.fromSsmParameter(parametreCache),
    },
    logDriver: ecs.LogDrivers.awsLogs({ streamPrefix: 'tienda', logRetention: 30 }),
  },
  taskSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
  publicLoadBalancer: true,
  circuitBreaker: { rollback: true },
  enableExecuteCommand: config.nombre !== 'produccion',
});

servei.targetGroup.configureHealthCheck({
  path: '/salud', healthyThresholdCount: 2, interval: cdk.Duration.seconds(15),
});

// Permisos minims amb els metodes grant*: inclouen els de KMS que gairebe ningu recorda.
cola.grantSendMessages(servei.taskDefinition.taskRole);
taulaCistelles.grantReadWriteData(servei.taskDefinition.taskRole);

const escalat = servei.service.autoScaleTaskCount({ minCapacity: 2, maxCapacity: 20 });
escalat.scaleOnRequestCount('PerPeticions', {
  requestsPerTarget: 120,
  targetGroup: servei.targetGroup,
  scaleOutCooldown: cdk.Duration.seconds(30),
  scaleInCooldown: cdk.Duration.minutes(5),
});
escalat.scaleOnSchedule('PicDivendres', {
  schedule: appscaling.Schedule.cron({ weekDay: 'FRI', hour: '16', minute: '45' }),
  minCapacity: 6,
});

L'advertiment de 09-02 continua vigent: cdk synth i llegir la plantilla la primera vegada. Aquest constructe pren decisions per tu —crea un ALB públic, obre el seu grup de seguretat al 0.0.0.0/0 al port 80, crea un grup de registres amb retenció per omissió— i cal verificar que coincideixen amb el que vols. A producció, MercadoFresco hi afegeix el certificat i el redirectHTTP: true per no servir mai per HTTP.

Fixa't també en enableExecuteCommand: config.nombre !== 'produccion': ECS Exec activat a desenvolupament i preproducció, i desactivat a producció tret d'activació explícita durant un incident. És una decisió de govern expressada en una línia d'infraestructura.

Fargate enfront d'EC2 enfront de Lambda

Tots tres executen codi sense que tu compris maquinari, i l'elecció es fa per criteris objectius.

Criteri EC2 Fargate Lambda
Unitat La instància La tasca (contenidor) La invocació
Model de cost Per instància-hora, plena o buida Per vCPU-hora i GB-hora de la tasca Per invocació i GB-segon, amb capa gratuïta
Cost amb càrrega constant 24/7 El més baix amb bon empaquetatge i Savings Plans Intermedi El més alt
Cost amb càrrega intermitent El més alt (paga l'oci) Intermedi El més baix (no paga l'oci)
Arrencada en fred 2 min (instància nova) 35-45 s 100 ms - 2 s
Durada màxima Il·limitada Il·limitada 15 minuts
Memòria màxima Fins a TB 120 GB 10 GB
Estat local Disc persistent Efímer (o EFS) Efímer (o EFS)
Control de l'entorn Total: kernel, GPU, famílies Imatge i recursos Runtime gestionat o imatge
Feina operativa Alta: AMI, pedaços, escalat Baixa: només la imatge Mínima
Portabilitat AMI, lligada a AWS Imatge OCI: corre a qualsevol lloc Lligada al model de Lambda
Quan triar-lo GPU, llicències per nucli, càrregues enormes i constants, requisits de kernel Serveis de llarga durada contenidoritzats: l'opció per omissió Esdeveniments, pics irregulars, integracions curtes

La decisió raonada de MercadoFresco, component a component:

Component Elecció Per què
Botiga Fargate sota demanda Procés de llarga durada, trànsit continu, arrencada de 40 s suficient, sense oci per pagar
Treballadors de comandes Fargate, 1 sota demanda + 4 Spot Tolerant a interrupció amb idempotència; -50 % de cost
Treballadors de correu i magatzem Fargate Spot Res urgent ni síncron
mercadofresco-generar-miniaturas Lambda Es dispara per esdeveniment d'S3, dura segons, amb llargs períodes sense feina
-cobrar-pago, -reservar-stock, -asignar-reparto Lambda Passos curts de la màquina mercadofresco-procesar-pedido; contenidoritzar-los seria un retrocés
Càrrega nocturna a Redshift Tasca puntual a Fargate Spot Dura 25 minuts: passa dels 15 de Lambda
Res EC2 Cap component no necessita ja kernel, GPU ni llicència per nucli

El criteri que resol la majoria dels dubtes: si el procés viu esperant peticions, és Fargate; si el procés es desperta davant d'un esdeveniment i mor, és Lambda; si necessites el control de la màquina, és EC2. I el criteri econòmic, que s'afina al mòdul 11: per sota d'una utilització sostinguda alta, Fargate guanya a EC2 perquè no paga l'oci; per sobre, EC2 amb Savings Plans (11-05) recupera l'avantatge.

App Runner: un esglaó més de gestió

AWS App Runner va un pas més enllà: se li dona una imatge de contenidor o un repositori de codi, i crea el servei, el balancejador, el certificat, el domini i l'autoescalat, inclòs escalar a zero. No hi ha VPC que dissenyar, ni grup de destinació, ni definició de tasca.

El que és rellevant és on deixa d'encaixar, i per això MercadoFresco no el fa servir: dona molt menys control de xarxa —l'accés a la VPC exigeix un connector i continua havent-hi limitacions—, no admet sidecars ni tasques multicontenidor, el model de desplegament no ofereix el blue/green canari de CodeDeploy, i el seu cost per unitat és superior al de Fargate. És una opció excel·lent per a un servei HTTP senzill o un prototip, i un mal encaix per a una botiga amb Aurora en subxarxa privada, cues, memòria cau i un pipeline amb porta de qualitat. Se'n parla perquè és la pregunta que sempre apareix: la resposta és que l'escala de gestió no és una classificació, és un intercanvi entre comoditat i control.

Cost comparat i neteja

El càlcul complet del servei de la botiga, amb preus aproximats d'eu-west-1:

Fargate x86, tasca d'1 vCPU i 2 GB: 1 × 0,04656 + 2 × 0,00511 = 0,05678 USD/hora.

Escenari Càlcul Mensual
2 tasques base 24/7 2 × 0,05678 × 730 82,9 USD
+ finestra del divendres (4 extra × 5 h × 4,3) 4 × 5 × 4,3 × 0,05678 4,9 USD
Total Fargate x86 ≈ 88 USD
Total Fargate arm64 (-20 %) ≈ 70 USD
ASG anterior: 2 × m5.large sota demanda 2 × 0,107 × 730 156 USD
+ EBS 2 × 30 GB gp3 2,4 USD
Total EC2 anterior ≈ 158 USD

MercadoFresco passa d'uns 158 USD a uns 70 USD al mes a la botiga, amb arm64, i elimina de passada la feina de mantenir AMI i pedaços. Amb els treballadors a Spot, l'estalvi total del mòdul ronda els 150 USD mensuals.

Amb dos matisos honestos, perquè la comparació no és completa sense ells. El primer: les instàncies EC2 es podrien comprar amb Savings Plans i baixar un 30-40 %, cosa que estreny molt la diferència —i Fargate també admet Compute Savings Plans, tema d'11-05—. El segon: si el clúster d'EC2 estigués molt ben empaquetat, amb la botiga i els treballadors compartint instàncies al 85 % d'ocupació, EC2 seria competitiu. El problema és que aquest empaquetatge cal aconseguir-lo i mantenir-lo, i aquesta és exactament la classe de feina que Fargate elimina.

Neteja, en ordre estricte:

# 1. Accions programades i politiques d'escalat: si no, reposen tasques
aws application-autoscaling delete-scheduled-action $DESTI --scheduled-action-name pico-viernes-inicio
aws application-autoscaling deregister-scalable-target $DESTI
# 2. El servei a zero i esborrat
aws ecs update-service --cluster ecs-mercadofresco --service svc-mercadofresco-tienda-fg --desired-count 0
aws ecs delete-service --cluster ecs-mercadofresco --service svc-mercadofresco-tienda-fg --force
# 3. Programacions d'EventBridge Scheduler
aws scheduler delete-schedule --name mercadofresco-carga-analitica-nocturna
# 4. ELS PUNTS D'ENLLAC D'INTERFICIE: costen per hora encara que no hi passi transit
aws ec2 describe-vpc-endpoints --filters Name=vpc-id,Values=vpc-mercadofresco \
  --query 'VpcEndpoints[?VpcEndpointType==`Interface`].VpcEndpointId' --output text \
  | xargs -r aws ec2 delete-vpc-endpoints --vpc-endpoint-ids
# 5. El cluster i el grup de registres
aws ecs delete-cluster --cluster ecs-mercadofresco
aws logs delete-log-group --log-group-name /ecs/mercadofresco-tienda

El pas 4 és el residu car d'aquesta lliçó: set punts d'enllaç d'interfície en dues AZ costen uns 112 USD al mes encara que no hi passi ni un sol byte. Un punt d'enllaç oblidat és la fuita silenciosa més habitual després de les adreces IP elàstiques sense associar.

Errors Habituals i Consells

Error: demanar una combinació de CPU i memòria invàlida. RegisterTaskDefinition falla amb un missatge poc clar. Consell: tingues la taula a mà; amb el CDK, memoryLimitMiB i cpu es validen en la síntesi, que és abans.

Error: dimensionar per intuïció. Sobredimensionar a Fargate es paga des del primer segon. Consell: percentil 95 de Container Insights durant dues setmanes, més un 30 %, i revisar-ho al cap d'un mes.

Error: subxarxes privades sense punts d'enllaç ni NAT. La tasca es queda a PROVISIONING i mor amb CannotPullContainerError. Consell: abans de migrar, comprova la ruta a ECR api, ECR dkr, S3, Logs i Secrets Manager; el d'S3 és de passarel·la, és gratis i és el que més s'oblida.

Error: creure que sense NAT sempre és més barat. Set punts d'enllaç d'interfície en dues AZ superen el NAT en una arquitectura mitjana. Consell: posa punts d'enllaç només per al camí crític d'arrencada i decideix la resta amb dades del mòdul 11.

Error: programar DesiredCount en lloc del mínim. Desactiva de fet el seguiment de destinació durant la finestra. Consell: programa MinCapacity i deixa que la política reactiva continuï treballant per sobre.

Error: oblidar --timezone a l'escalat programat. El pic es desplaça una hora en canviar l'hora. Consell: Europe/Madrid explícit en tota acció programada, i revisar l'última setmana d'octubre.

Error: posar la botiga a Fargate Spot per estalviar. Una interrupció amb dos minuts d'avís durant el pic del divendres és just el que el curs porta deu mòduls evitant. Consell: Spot només on la interrupció es reintenta sola, i sempre amb base sota demanda.

Error: no gestionar SIGTERM als treballadors. Amb Spot, cada interrupció es converteix en un missatge reprocessat o perdut. Consell: gestor que acaba el missatge en curs i no en demana un altre, stopTimeout: 120 i temps de visibilitat folgat.

Error: fer servir ECS Exec per arreglar alguna cosa. El canvi desapareix en la reposició següent i deixa un sistema que ningú no pot reproduir. Consell: ECS Exec per diagnosticar; l'arranjament va pel pipeline. I a producció, amb notificació a alertas-mercadofresco.

Error: canviar a arm64 sense provar-ho. Una roda de Python sense binari arm trenca l'arrencada. Consell: docker buildx amb les dues plataformes, una setmana a preproducció i comparació de latència abans de tocar producció.

Consell: fixa --platform-version LATEST i no l'ancoris. Ancorar una versió de plataforma és renunciar a les millores i als pedaços, que és just el que has vingut a comprar.

Consell: mantén minimumHealthyPercent: 100 a producció. Amb Fargate ja no hi ha un buit d'instància que limiti el maximumPercent, així que 100/200 no costa capacitat reservada, només uns minuts de doble facturació per desplegament.

Consell: posa una alarma sobre RunningTaskCount enfront de DesiredTaskCount. És el senyal més primerenc d'un problema d'arrencada, de quota de Fargate o d'esgotament d'IP a la subxarxa.

Exercicis

Exercici 1: dimensionar i decidir el repartiment de capacitat

Els treballadors de cola-mercadofresco-pedidos processen cada missatge en 12 segons de mitjana, amb un pic de 900 missatges/hora els divendres de 17:00 a 21:00 i uns 150 missatges/hora la resta del temps. Container Insights indica que cada treballador fa servir el percentil 95 de 0,31 vCPU i 780 MB. L'acord de servei intern és que cap comanda no esperi més de 3 minuts a la cua. Dissenya: (a) la combinació de CPU i memòria de la tasca, justificada; (b) quantes tasques calen al pic i fora del pic, amb el càlcul; (c) la política d'autoescalat completa, indicant quina mètrica fas servir i per què no la CPU; (d) el repartiment entre FARGATE i FARGATE_SPOT amb la seva base i els seus weight, i què passa si AWS retira tota la capacitat Spot durant el pic; i (e) el cost mensual aproximat del teu disseny.

Exercici 2: la migració que es va quedar a PROVISIONING

El Luis migra el servei de la botiga a Fargate en preproducció. Les tasques es queden diversos minuts a PROVISIONING i acaben amb ResourceInitializationError: unable to pull secrets or registry auth. Comprova el següent i tot sembla correcte: el rol d'execució té els permisos d'ECR i de Secrets Manager, la definició de tasca és la mateixa que funcionava a EC2, i les subxarxes són snet-mercadofresco-app-a i -b. Diagnostica (a) les tres causes de xarxa possibles, en ordre de probabilitat, amb la comprovació concreta de cadascuna; (b) per què el mateix rol i la mateixa definició sí que funcionaven al tipus de llançament EC2; (c) quin punt d'enllaç de VPC concret arreglaria el cas més probable i per què el seu tipus importa; i (d) quines dues comprovacions afegiries al pipeline perquè aquesta fallada no torni a arribar a un desplegament.

Exercici 3: la proposta de passar-ho tot a Lambda

La Sara torna d'una conferència amb una proposta: eliminar Fargate i passar tota la botiga a Lambda darrere d'API Gateway, «perquè només es paga per petició i escala a zero». Aporta la dada que la botiga rep unes 300 comandes/hora fora de pic i que a les 4 de la matinada no hi ha trànsit. Respon amb criteri tècnic i econòmic: (a) tres raons tècniques concretes per les quals la botiga de MercadoFresco no encaixa bé a Lambda; (b) el càlcul aproximat que compara el cost de totes dues opcions amb el trànsit real; (c) quina part de la seva proposta sí que té raó i on ja s'està aplicant a l'arquitectura actual; (d) què mesuraries abans de descartar-la del tot; i (e) com l'hi explicaries en una frase que no soni a «no».

Solucions

Solució 1

(a) La combinació. El percentil 95 és 0,31 vCPU i 780 MB. Afegint-hi un 30 % de marge: 0,40 vCPU i 1,01 GB. La combinació vàlida immediatament superior és 512 (0,5 vCPU) amb 1 GB de memòria. Pujar a 1 vCPU duplicaria el cost per a un 20 % de CPU sense fer servir, i baixar a 0,25 vCPU no és possible perquè no hi arriba. Cost per tasca: 0,5 × 0,04656 + 1 × 0,00511 = 0,0279 USD/hora.

(b) Quantes tasques. Un treballador processa 3600 / 12 = 300 missatges/hora. Fora de pic, 150 missatges/hora exigeixen 1 tasca, però el mínim ha de ser 2 per disponibilitat: una sola tasca significa zero capacitat mentre es reposa. Al pic, 900 missatges/hora exigeixen 900 / 300 = 3 tasques per anar al dia, i aquest és exactament el punt on la cua no creix però tampoc no es recupera d'un retard. Per complir els 3 minuts amb marge i absorbir la variabilitat es fan servir 5 tasques al pic, que donen 1500 missatges/hora de capacitat i permeten drenar un retard acumulat.

(c) La política d'autoescalat. La CPU no serveix: un treballador que consumeix missatges està sempre igual d'ocupat, tingui la cua 10 o 10.000 missatges, així que la CPU no reflecteix el retard. La mètrica correcta és el retard per tasca, que es calcula amb una mètrica matemàtica de CloudWatch: ApproximateNumberOfMessagesVisible / RunningTaskCount. Amb un objectiu de 3 minuts i 300 missatges/hora per tasca, la destinació és 300 / 60 × 3 = 15 missatges per tasca.

{"TargetValue": 15.0, "ScaleOutCooldown": 60, "ScaleInCooldown": 300,
 "CustomizedMetricSpecification": {"Metrics": [
   {"Id": "visibles", "MetricStat": {"Metric": {"Namespace": "AWS/SQS",
      "MetricName": "ApproximateNumberOfMessagesVisible",
      "Dimensions": [{"Name": "QueueName", "Value": "cola-mercadofresco-pedidos"}]},
      "Stat": "Average"}, "ReturnData": false},
   {"Id": "tareas", "MetricStat": {"Metric": {"Namespace": "ECS/ContainerInsights",
      "MetricName": "RunningTaskCount",
      "Dimensions": [{"Name": "ServiceName", "Value": "svc-mercadofresco-trabajadores"},
                     {"Name": "ClusterName", "Value": "ecs-mercadofresco"}]},
      "Stat": "Average"}, "ReturnData": false},
   {"Id": "retraso", "Expression": "visibles / MAX([tareas, 1])", "ReturnData": true}]}}

S'hi afegeix una acció programada per als divendres que puja MinCapacity a 5 a les 16:45 i la torna a 2 a les 21:30, amb --timezone "Europe/Madrid": pujar per rellotge evita els primers minuts de retard que la política reactiva no pot evitar per definició.

(d) El repartiment de capacitat. capacityProvider=FARGATE,weight=1,base=2 més capacityProvider=FARGATE_SPOT,weight=3,base=0. Les dues tasques del terra són estables, i de les tres extra del pic aproximadament 0,75 van sota demanda i 2,25 a Spot. Si AWS retira tota la capacitat Spot durant el pic, queden les 2 tasques sota demanda amb capacitat per a 600 missatges/hora enfront de 900 entrants: la cua creix uns 300 missatges/hora i l'acord de 3 minuts s'incompleix en uns vint minuts. La mitigació té dues parts: la política d'autoescalat detecta el retard i demana tasques noves, que el proveïdor sota demanda sí que pot servir —el repartiment per weight s'aplica a les tasques noves, i amb Spot no disponible ECS llança sota demanda—; i una alarma sobre ApproximateAgeOfOldestMessage avisa alertas-mercadofresco si el missatge més antic supera els 3 minuts. El que no cal fer és posar base=0: el terra estable és el que converteix una retirada de Spot en una degradació en comptes d'una caiguda.

(e) Cost mensual. Fora de pic: 2 tasques × 0,0279 × (730 − 17) ≈ 39,8 USD. Al pic (4 h × 4,3 divendres = 17,2 h): 2 sota demanda × 0,0279 × 17,2 ≈ 0,96 USD, més 3 tasques extra majoritàriament Spot ≈ 3 × 0,0084 × 17,2 ≈ 0,43 USD. Total ≈ 41 USD al mes, enfront dels 156 USD de l'ASG dedicat de treballadors que hi havia abans.

Solució 2

(a) Les tres causes de xarxa, per probabilitat.

  1. Falten els punts d'enllaç d'interfície d'ECR i Secrets Manager, i no hi ha NAT a la subxarxa de preproducció. És la causa més probable perquè l'error esmenta registry auth i secrets, que són exactament les dues primeres crides sortints d'una tasca. Comprovació: aws ec2 describe-route-tables sobre les subxarxes -app-a i -b buscant la ruta 0.0.0.0/0, i aws ec2 describe-vpc-endpoints filtrant per la VPC.
  2. El grup de seguretat dels punts d'enllaç no permet l'entrada des del de les tasques. Els punts d'enllaç d'interfície són ENI amb grup de seguretat propi: si sg-mercadofresco-endpoints no accepta el port 443 des de sg-mercadofresco-tienda, existeixen però no es poden fer servir. Comprovació: regles d'entrada de sg-mercadofresco-endpoints.
  3. El DNS privat del punt d'enllaç està desactivat. Sense --private-dns-enabled, el nom secretsmanager.eu-west-1.amazonaws.com continua resolent a la IP pública i el trànsit intenta sortir per on no hi ha sortida. Comprovació: el camp PrivateDnsEnabled del punt d'enllaç.

(b) Per què sí que funcionava a EC2. Perquè al tipus de llançament EC2, qui descarrega la imatge i resol els secrets és l'agent d'ECS de la instància, que fa servir la ruta de xarxa de la instància i el seu grup de seguretat. Si aquestes instàncies eren en una subxarxa amb NAT o tenien un grup de seguretat més permissiu, tot funcionava. En passar a Fargate, la connectivitat passa a dependre de l'ENI de la tasca, amb les subxarxes i el grup de seguretat declarats a networkConfiguration. És el mateix canvi de frontera del qual parlava awsvpc a 10-01, ara visible: la xarxa ja no és de la màquina, és de la tasca.

(c) El punt d'enllaç concret i per què importa el seu tipus. Per al cas més probable en calen tres: ecr.api, ecr.dkr i secretsmanager, tots tres d'interfície (ENI privada amb grup de seguretat, es paga per hora i per GB). Però el que sol faltar i no dona la cara és s3, que és de passarel·la: no és una ENI sinó una entrada a la taula de rutes, és gratuït, i sense ell les capes de la imatge —que s'emmagatzemen a S3— no es descarreguen encara que els dos punts d'enllaç d'ECR siguin perfectes. Confondre els dos tipus porta a posar un punt d'enllaç d'interfície per a S3, que funciona però costa diners innecessàriament en aquest cas.

(d) Dues comprovacions al pipeline. La primera, una prova de desplegament a preproducció amb la mateixa configuració de xarxa que producció: la fallada apareix on ha d'aparèixer. La segona, una regla d'AWS Config (05-04) o una prova del CDK (09-02) que verifiqui que tota subxarxa feta servir per un servei d'ECS té, o bé ruta cap a un NAT, o bé els cinc punts d'enllaç del camí crític. És una invariant d'arquitectura i per tant es prova com a codi, no es recorda. Com a reforç, la comprovació que el circuit breaker està activat amb rollback: true hauria convertit aquest incident en una reversió automàtica en lloc de en tasques girant en va.

Solució 3

(a) Tres raons tècniques.

  1. La connexió a Aurora. Cada Lambda concurrent obre la seva pròpia connexió, i amb 300 comandes/hora en pics de concurrència això esgota el pool d'aurora-mercadofresco-pedidos ràpidament. Es resol amb RDS Proxy, que afegeix cost i una peça més; a Fargate, cada tasca manté un pool estable i el problema no existeix.
  2. L'arrencada en fred amb estat calent. La botiga manté en memòria la memòria cau del catàleg que precarrega des de mercadofresco-catalogo en arrencar. A Fargate aquest cost es paga un cop per tasca i dura hores; a Lambda es pagaria a cada arrencada en fred, i la primera petició de cada entorn d'execució seria lenta just quan arriba un pic.
  3. La reescriptura. La botiga és una aplicació WSGI amb Gunicorn; portar-la a Lambda exigeix un adaptador o partir-la en funcions, més un canvi del model de sessions, dels fitxers estàtics i de l'observabilitat. És un projecte de setmanes el benefici del qual és dubtós, just després d'acabar la migració a contenidors.

(b) El càlcul. Amb 300 comandes/hora de mitjana i unes 8 peticions HTTP per comanda, en surten unes 2.400 peticions/hora, és a dir, 1,75 milions al mes. Suposant 250 ms de mitjana i 2 GB de memòria: 1,75 M × 0,25 s × 2 GB = 875.000 GB-s. A 0,0000167 USD per GB-s són uns 14,6 USD, més 0,35 USD d'invocacions, més API Gateway: 1,75 M × 3,5 USD/milió ≈ 6,1 USD. Total ≈ 21 USD, enfront dels 70 USD de Fargate arm64. La Sara té raó en el número brut. Però hi falten tres partides que canvien la conclusió: RDS Proxy (uns 30 USD/mes), el cost de la reescriptura (setmanes de feina, que a cost d'equip supera de llarg l'estalvi anual de 588 USD) i el risc de latència per arrencades en fred durant el pic del divendres, que és precisament el problema que aquest mòdul acaba de resoldre.

(c) En què té raó i on ja s'aplica. Té raó en el principi: no pagar per capacitat ociosa. I aquest principi ja està aplicat on encaixa: mercadofresco-generar-miniaturas es dispara per esdeveniment d'S3 i no es paga entre pujades de foto; -cobrar-pago, -reservar-stock i -asignar-reparto són passos curts de la màquina d'estats; i els treballadors de la cua escalen fins al mínim fora del pic. L'arquitectura ja és híbrida per disseny: Lambda on la feina és esporàdica i curta, Fargate on el procés viu esperant peticions.

(d) Què mesuraria abans de descartar-la. Tres coses concretes: la distribució real de la latència de la botiga per percentils a X-Ray, per saber quant pesaria una arrencada en fred al p99; el nombre de connexions simultànies a Aurora al pic del divendres, per dimensionar si RDS Proxy seria suficient; i el cost real de Fargate durant un mes complet amb arm64 i l'escalat programat ja aplicat, perquè la comparació s'està fent contra un número que encara no s'ha mesurat. Sense aquestes tres dades, totes dues postures són opinions.

(e) La frase. «Tens raó en el principi i per això ja ho estem aplicant: tot el que es dispara per un esdeveniment i mor en segons ja és a Lambda. La botiga és el contrari —un procés que viu esperant peticions i manté memòria cau i connexions—, i per a això Fargate costa cinquanta dòlars més al mes i ens estalvia una reescriptura, un RDS Proxy i les arrencades en fred del divendres a les set.»

Conclusió

Les instàncies han desaparegut. La botiga de MercadoFresco s'executa ara sobre Fargate, i ja no existeix cap màquina que la Marta pugui llistar, dimensionar, apedaçar o deixar-se encesa.

Tens clar què desapareix —l'AMI, l'apedaçament de l'amfitrió, l'escalat del clúster, l'empaquetatge de tasques, la capacitat ociosa i fins i tot el límit d'ENI per instància— i què continua sent teu: la imatge, la CPU i la memòria, la xarxa i els permisos. Amb la frase que ordena la resta: Fargate no elimina la feina d'operar una aplicació, elimina la feina d'operar un servidor. I amb el model de recursos real: les combinacions vàlides de CPU i memòria, els 20 GB d'emmagatzematge efímer ampliables a 200, i la decisió de dimensionar amb el percentil 95 de Container Insights més un 30 %, perquè aquí sobredimensionar es paga des del primer segon. Més arm64 amb Graviton, que baixa el servei de 88 a 70 USD mensuals amb docker buildx i una setmana de prova a preproducció.

Tens les diferències operatives i què fer amb cadascuna: ECS Exec en lloc d'SSH, auditat a CloudTrail i amb la regla que serveix per diagnosticar i no per arreglar; FireLens amb Fluent Bit com a sidecar on abans hi havia un DaemonSet, amb awslogs com a opció per omissió perquè el sidecar costa CPU a cada tasca; i awsvpc com a únic mode de xarxa, que ja no és una restricció sinó la manera normal de treballar. I tens el número que justifica el mòdul sencer: de 120 segons a 35-45 fins que una tasca nova rep trànsit, amb el desglossament per fases i el que significa el divendres a les 19:00 quan el trànsit passa de 300 a 900 comandes/hora en vuit minuts.

Tens la migració completa: definició de tasca sense canvis perquè ja declarava FARGATE, subxarxes privades snet-mercadofresco-app-a i -b sense IP pública, grup de seguretat per tasca, i els punts d'enllaç de VPC del camí crític —amb l'anàlisi honesta que set punts d'enllaç en dues AZ surten més cars que el NAT, i la decisió raonada de posar només els quatre que importen—. L'autoescalat en tres capes: seguiment de destinació com a base, i sobretot l'escalat programat del divendres, que puja el mínim a 6 a les 16:45 amb Europe/Madrid explícit i costa 4,9 USD al mes. Fargate Spot amb el repartiment base=1, weight 1:4 per als treballadors i el criteri que decideix on entra: només on la interrupció amb dos minuts d'avís es reintenta sola. Les tasques programades amb EventBridge Scheduler per a la càrrega nocturna a Redshift, amb finestra flexible, reintents i DLQ. I el pipeline amb blue/green canari de CodeDeploy sobre tg-mercadofresco-tienda i -verde, que baixa la restauració de 4 minuts a menys d'1 perquè revertir és moure un oient; tot això en vint línies de CDK amb ApplicationLoadBalancedFargateService.

I tens la comparativa honesta Fargate enfront d'EC2 enfront de Lambda, amb el criteri que resol la majoria dels dubtes —si el procés viu esperant peticions, és Fargate; si es desperta davant d'un esdeveniment i mor, és Lambda; si necessites el control de la màquina, és EC2— i la decisió component a component de MercadoFresco, en la qual EC2 ja no apareix en cap fila.

Queda una pregunta que algú de l'equip farà aquesta mateixa setmana, i que mereix una resposta seriosa en lloc d'un arronsament d'espatlles: tothom parla de Kubernetes. És l'estàndard de facto de l'orquestració de contenidors, té un ecosistema enorme, funciona igual a qualsevol núvol i hi ha moltíssima gent que en sap. Ens estem equivocant quedant-nos a ECS?

A 10-03, «Amazon EKS», es respon amb dades i no amb preferències. Veuràs què és Kubernetes i què resol que ECS no, el seu vocabulari mínim però real, què gestiona EKS i què continua sent teu, les quatre opcions de còmput inclòs Auto Mode, els manifests complets del desplegament de la botiga amb sondes, Ingress i l'AWS Load Balancer Controller, IRSA i Pod Identity com a equivalents del rol de tasca, Karpenter per als nodes, i l'argument central que gairebé ningú no posa per escrit: el cost ocult de les actualitzacions de versió. Amb la comparativa ECS enfront d'EKS i la decisió raonada de MercadoFresco, juntament amb els criteris objectius que la canviarien.

Curs d'AWS

Mòdul 1: Introducció a AWS

Mòdul 2: Serveis principals d'AWS

Mòdul 3: Xarxes i lliurament de contingut

Mòdul 4: Seguretat i identitat

Mòdul 5: Monitoratge i gestió

Mòdul 6: Bases de dades

Mòdul 7: Integració d'aplicacions

Mòdul 8: Eines per a desenvolupadors

Mòdul 9: Infraestructura com a codi i govern de comptes

Mòdul 10: Contenidors a AWS

Mòdul 11: Millors pràctiques i gestió de costos

© Copyright 2026. Tots els drets reservats