A mercadofresco-artefactos hi ha un ZIP verificat: ha passat 214 proves, té el seu commit a les metadades i
porta la versió al nom. I per portar-lo a producció, el Luis continua fent el de sempre: ssh a la
primera instància de l'ASG, scp del ZIP, descomprimir, systemctl restart, mirar el web, repetir a la
segona. Quaranta segons per instància servint errors, dues versions convivint mentre dura, i si
alguna cosa va malament, buscar el ZIP anterior i repetir el ritual amb la botiga caiguda.
AWS CodeDeploy converteix aquest ritual en una operació governada. Sap treure una instància del grup de destinació abans de tocar-la, executar els teus scripts en un ordre definit, comprovar que l'aplicació respon abans de tornar-li trànsit, avançar a poc a poc per la flota i —el que de debò importa— tornar enrere sola quan una alarma de CloudWatch salta durant el desplegament. És la lliçó que tanca el quart problema del curs: els desplegaments arriscats.
Avís de cost. CodeDeploy és gratuït per a EC2, Lambda i ECS; només cobra 0,02 USD per actualització d'instància en servidors locals. El que costa és el del voltant: en blue/green dupliques temporalment les instàncies de l'ASG —uns 0,09 USD per desplegament de 30 minuts amb dos
t3.medium— i les versions de Lambda no caduquen soles. Al final tens la neteja. Dades fictícies.
Contingut
- Què resol CodeDeploy i què no
- Les tres destinacions i les estratègies que admet cadascuna
- Conceptes: aplicació, grup de desplegament, revisió i configuració
- L'agent a les instàncies de l'ASG
- L'
appspec.ymlper a EC2 i els ganxos del cicle de vida - Els scripts reals de MercadoFresco
- Desplegament al lloc:
AllAtOnce,HalfAtATimeiOneAtATime - Blue/green amb l'ASG i els grups de destinació
- L'
appspecde Lambda i d'ECS - Canari i lineal: desplegar
mercadofresco-cobrar-pago - Reversió automàtica: la peça que resol el problema 4
- Comparació amb la reversió manual i amb Route 53 ponderat
- Migracions d'esquema: expansió i contracció
- Observabilitat del desplegament i diagnòstic d'una fallada
- Cost i neteja
- Errors habituals i consells
- Exercicis
- Conclusió
Què resol CodeDeploy i què no
CodeDeploy no construeix, no decideix quan s'ha de desplegar i no defineix infraestructura. Fa una cosa: agafa una revisió —un ZIP a S3 o una imatge— i la instal·la en un conjunt de destinacions seguint un pla, amb ganxos on poses els teus scripts i amb condicions d'aturada.
| Problema del desplegament manual | Què aporta CodeDeploy |
|---|---|
| La instància serveix errors mentre s'actualitza | La treu del grup de destinació abans de tocar-la |
| Dues versions convivint sense control | Controla quantes instàncies hi ha a cada versió |
| «S'ha reiniciat bé el servei?» | ValidateService ho comprova i falla si no |
| Tornar enrere és repetir el ritual a mà | Reversió automàtica en minuts |
| Ningú no sap què es va desplegar ni quan | Històric amb revisió, autor i resultat |
| El desplegament és igual en dev que en prod | Grups de desplegament amb configuració diferent |
I el que no aporta: no coordina l'ordre entre serveis diferents —per a això hi ha el pipeline de 08-04—, no migra la teva base de dades i no compensa una aplicació que no pot conviure amb ella mateixa en dues versions. Aquesta última limitació és el tema de la secció sobre migracions d'esquema.
Les tres destinacions i les estratègies que admet cadascuna
| Destinació | Al lloc | Blue/green | Canari | Lineal | Agent |
|---|---|---|---|---|---|
| EC2 / ASG | Sí | Sí | No | No | Sí |
| Servidors locals | Sí | No | No | No | Sí |
| AWS Lambda | No | Sí (per àlies) | Sí | Sí | No |
| Amazon ECS | No | Sí | Sí | Sí | No |
Tres observacions que eviten confusions freqüents. A EC2 no hi ha canari ni lineal: el
desplaçament percentual és cosa de Lambda i d'ECS, on el trànsit es reparteix per pes d'àlies o de grup
de destinació; a EC2 el més semblant és OneAtATime, que és granularitat d'instància, no de percentatge de
peticions. A Lambda i ECS no hi ha desplegament al lloc: sempre es crea la versió nova al costat de la
vella i es desplaça trànsit, que és més segur per construcció. I l'agent només cal a EC2 i als
servidors locals; a Lambda i ECS, CodeDeploy parla amb l'API del servei.
Conceptes: aplicació, grup de desplegament, revisió i configuració
Quatre objectes, i confondre'ls causa la meitat dels dubtes inicials:
| Objecte | Què és | A MercadoFresco |
|---|---|---|
| Aplicació | Contenidor lògic: nom i plataforma | app-mercadofresco-tienda, app-mercadofresco-cobrar-pago |
| Grup de desplegament | On i com: destinacions, estratègia, alarmes, reversió | dg-mercadofresco-tienda-desarrollo / -produccion |
| Revisió | Què es desplega: el ZIP amb el seu appspec.yml |
s3://mercadofresco-artefactos/tienda/1.5.0-a3f9c21/ |
| Configuració de desplegament | El ritme i quant ha de continuar sa | CodeDeployDefault.HalfAtATime, o una de pròpia |
L'important és el grup de desplegament: la mateixa aplicació i la mateixa revisió es comporten de manera
molt diferent segons el grup. En desenvolupament, AllAtOnce sense alarmes perquè sigui ràpid; en producció,
blue/green amb alarmes i reversió automàtica. Aquest és el mecanisme amb què se separen els entorns.
aws deploy create-application --application-name app-mercadofresco-tienda \
--compute-platform Server --profile mercadofresco-dev --region eu-west-1
aws deploy create-deployment-group \
--application-name app-mercadofresco-tienda \
--deployment-group-name dg-mercadofresco-tienda-produccion \
--service-role-arn arn:aws:iam::111122223333:role/rol-codedeploy-mercadofresco \
--auto-scaling-groups asg-mercadofresco-tienda \
--deployment-config-name CodeDeployDefault.HalfAtATime \
--load-balancer-info '{"targetGroupInfoList":[{"name":"tg-mercadofresco-tienda"}]}' \
--alarm-configuration '{"enabled": true, "ignorePollAlarmFailure": false,
"alarms": [{"name":"mercadofresco-alb-latencia-alta"},
{"name":"mercadofresco-pedidos-fallidos"}]}' \
--auto-rollback-configuration '{"enabled": true,
"events": ["DEPLOYMENT_FAILURE", "DEPLOYMENT_STOP_ON_ALARM"]}' \
--profile mercadofresco-dev --region eu-west-1Fixa't en ignorePollAlarmFailure: false: si CodeDeploy no aconsegueix consultar una alarma, el
desplegament falla en lloc de continuar a cegues. És el correcte —si el mecanisme de seguretat no respon,
no continuïs— però produeix fallades desconcertants quan al rol li falta cloudwatch:DescribeAlarms.
L'agent a les instàncies de l'ASG
L'agent és un procés que sondeja CodeDeploy, descarrega la revisió i executa els ganxos. Sense ell, la
instància es queda en Pending fins al timeout i el desplegament falla amb un missatge poc explicatiu.
Es pot instal·lar integrat dins de l'AMI, des del user data de lt-mercadofresco-tienda, o —el recomanable—
com a associació de Systems Manager amb actualització automàtica:
aws ssm create-association --name AWSCodeDeployAgentUpdate \
--targets Key=tag:Proyecto,Values=mercadofresco \
--schedule-expression "rate(14 days)" \
--profile mercadofresco-dev --region eu-west-1Aquesta última és la que fa servir MercadoFresco perquè resol el problema real: un agent desactualitzat deixa de funcionar sense avisar, i actualitzar-lo a mà en instàncies que l'ASG crea i destrueix és impossible.
Dos requisits que s'obliden. El rol de la instància ha de poder llegir l'artefacte:
{
"Version": "2012-10-17",
"Statement": [
{ "Effect": "Allow",
"Action": ["s3:GetObject", "s3:GetObjectVersion", "s3:ListBucket"],
"Resource": ["arn:aws:s3:::mercadofresco-artefactos",
"arn:aws:s3:::mercadofresco-artefactos/tienda/*"] },
{ "Effect": "Allow", "Action": ["kms:Decrypt"],
"Resource": "arn:aws:kms:eu-west-1:111122223333:key/*",
"Condition": {"StringEquals": {"kms:ViaService": "s3.eu-west-1.amazonaws.com"}} }
]
}El segon bloc cal perquè el bucket està xifrat amb alias/mercadofresco-datos: sense permís
de KMS, l'agent descarrega l'objecte i falla en desxifrar-lo, amb un error d'accés denegat que sembla
un problema d'S3. El segon requisit és sortida a internet o VPC endpoints: l'agent parla amb l'API
de CodeDeploy i amb S3, i una subxarxa privada sense NAT ni endpoints deixa el desplegament penjat. Per
diagnosticar, systemctl status codedeploy-agent i el registre a
/var/log/aws/codedeploy-agent/codedeploy-agent.log.
L'appspec.yml per a EC2
L'appspec.yml va a l'arrel del ZIP, no en un subdirectori, i diu a l'agent què cal copiar i què cal
executar:
version: 0.0
os: linux
files:
- source: /app
destination: /opt/mercadofresco/app
- source: /scripts
destination: /opt/mercadofresco/scripts
- source: /VERSION
destination: /opt/mercadofresco
# Sense aixo, un fitxer que ja existeixi al desti fa fallar el desplegament sencer
file_exists_behavior: OVERWRITE
permissions:
- object: /opt/mercadofresco/app
owner: mercadofresco
mode: 640
type: [file]
hooks:
ApplicationStop:
- { location: scripts/parar_servicio.sh, timeout: 60, runas: root }
BeforeInstall:
- { location: scripts/comprobar_espacio.sh, timeout: 30, runas: root }
AfterInstall:
- { location: scripts/instalar_dependencias.sh, timeout: 300, runas: mercadofresco }
- { location: scripts/cargar_configuracion.sh, timeout: 60, runas: mercadofresco }
ApplicationStart:
- { location: scripts/arrancar_servicio.sh, timeout: 120, runas: root }
ValidateService:
- { location: scripts/comprobar_salud.sh, timeout: 180, runas: mercadofresco }
- { location: scripts/calentar_cache.sh, timeout: 120, runas: mercadofresco }file_exists_behavior: OVERWRITE mereix un avís: sense ell, el valor per defecte és DISALLOW i el
desplegament falla si un fitxer ja existeix a la destinació. Com que la destinació gairebé sempre té la versió
anterior, és la primera fallada que troba tothom. RETAIN existeix per a fitxers que
l'aplicació genera i no s'han de sobreescriure.
Els ganxos del cicle de vida, un a un
| Ganxo | Quan | Revisió | Per a què serveix |
|---|---|---|---|
ApplicationStop |
Abans de res | L'ANTERIOR | Aturar el servei netament |
BeforeInstall |
Abans de copiar | La nova | Comprovacions prèvies, còpies |
AfterInstall |
Després de copiar | La nova | Dependències, permisos, configuració |
ApplicationStart |
Després d'instal·lar | La nova | Arrencar el servei |
ValidateService |
L'últim | La nova | Comprovar que funciona de debò |
BeforeAllowTraffic |
Només blue/green | La nova | Escalfar abans de rebre trànsit |
AfterAllowTraffic |
Només blue/green | La nova | Validar ja amb trànsit real |
Tres coses que cal entendre bé. ApplicationStop s'executa des de la revisió ANTERIOR, i és la
font d'un problema clàssic: si el desplegament anterior va deixar un parar_servicio.sh trencat, el desplegament
nou falla al primer ganxo encara que el codi nou sigui perfecte —i al primer desplegament d'una
instància no s'executa, perquè no hi ha revisió anterior—. Escriu-lo a prova de bales i fes que acabi
amb èxit encara que no trobi el servei. ValidateService és el ganxo que justifica tota la resta:
sense ell, «desplegat» vol dir «els fitxers estan copiats i systemctl no s'ha queixat», que no és el mateix
que «la botiga funciona». I els timeouts són per ganxo, amb un màxim d'una hora: un AfterInstall sense
memòria cau pot passar de 300 segons, i un ValidateService amb 10 segons falla sempre a la primera
instància, que és la més lenta a escalfar.
Els scripts reals de MercadoFresco
Aturar el servei sense fallar si no hi és:
#!/bin/bash
# scripts/parar_servicio.sh -> ApplicationStop
# ATENCIO: s'executa des de la revisio ANTERIOR. Ha de ser a prova de bales.
set -u # NO hi posem 'set -e': volem controlar les fallades nosaltres
systemctl list-unit-files | grep -q '^mercadofresco.service' || {
echo "El servei encara no existeix (primer desplegament)."; exit 0; }
systemctl stop mercadofresco
for i in $(seq 1 30); do
systemctl is-active --quiet mercadofresco || {
echo "Aturat netament en ${i}s"; exit 0; }
sleep 1
done
echo "No s'ha aturat en 30s. Forcant."
systemctl kill -s SIGKILL mercadofresco || true
exit 0 # MAI no fallem aqui: bloquejaria tots els desplegaments futursL'exit 0 final és deliberat: un ApplicationStop que falla deixa la instància en un estat del qual només
se surt recreant el grup de desplegament.
Comprovar la salut de debò:
#!/bin/bash
# scripts/comprobar_salud.sh -> ValidateService
set -euo pipefail
for i in $(seq 1 30); do
RESPOSTA=$(curl -sf -m 5 http://localhost:8080/salud 2>/dev/null || echo '{}')
if [ "$(echo "$RESPOSTA" | jq -r '.estado // "ko"')" = "ok" ]; then
# No n'hi ha prou amb un 200: comprovem les dependencies critiques una a una
for dep in aurora redis sqs; do
SALUT=$(echo "$RESPOSTA" | jq -r ".dependencias.${dep} // \"ko\"")
[ "$SALUT" = "ok" ] || { echo "Dependencia ${dep} en estat ${SALUT}"; exit 1; }
done
# I que la versio viva sigui la que acabem de desplegar
VERSIO_VIVA=$(echo "$RESPOSTA" | jq -r '.version')
[ "$VERSIO_VIVA" = "$(cat /opt/mercadofresco/VERSION)" ] || {
echo "Serveix ${VERSIO_VIVA}, no l'esperada"; exit 1; }
echo "Salut OK, versio ${VERSIO_VIVA}"; exit 0
fi
echo "Intent ${i}/30"; sleep 5
done
echo "No s'ha passat la comprovacio de salut en 150s"
exit 1Aquest script és el cor de la seguretat del desplegament, i fa tres comprovacions que un curl -f /salud simple no fa: que les dependències crítiques responguin —de res no serveix que el procés sigui viu
si no arriba a Aurora—, que la versió que respon sigui la que acabes d'instal·lar —detecta el cas en
què el servei no va arribar a reiniciar-se— i que tot passi dins d'un termini. El seu exit 1 és el que dispara
la reversió.
Escalfar la memòria cau abans de rebre trànsit:
#!/bin/bash
# scripts/calentar_cache.sh -> ValidateService (o BeforeAllowTraffic en blue/green)
set -euo pipefail
curl -sf -m 30 -X POST http://localhost:8080/interno/precargar-catalogo
for sku in FRUT-0012 VERD-0034 PESC-0007 CARN-0021; do
curl -sf -m 5 "http://localhost:8080/productos/${sku}" > /dev/null
done
echo "Memoria cau calenta"Sense aquest pas, la primera onada de trànsit troba la memòria cau buida, va a Aurora, i
TiempoConfirmacionPedido es dispara durant dos minuts. Al pic del divendres amb 900 comandes/hora, això
és exactament el que fa saltar mercadofresco-alb-latencia-alta i reverteix un desplegament que estava
bé.
Desplegament al lloc: AllAtOnce, HalfAtATime i OneAtATime
| Configuració | Alhora | Capacitat mínima | Durada (4 instàncies) | Quan |
|---|---|---|---|---|
AllAtOnce |
Totes | 0 | ~3 min | Desenvolupament. Mai en producció |
HalfAtATime |
50 % | 50 % | ~6 min | Producció amb marge de capacitat |
OneAtATime |
1 | N-1 | ~12 min | Màxima prudència; flotes petites |
AllAtOnce en producció és una caiguda, no un desplegament. Totes les instàncies fora alhora és el que
es vol evitar; i si falla, no queda cap instància amb la versió bona a la qual tornar.
Es pot definir una configuració pròpia amb aws deploy create-deployment-config i
--minimum-healthy-hosts type=FLEET_PERCENT,value=90. Però compte: amb aquest 90 % i una flota de 2
instàncies, el mínim sa és 2 (arrodoneix cap amunt) i cap desplegament no pot començar; amb flotes
petites fes servir HOST_COUNT en lloc de percentatges.
Blue/green amb l'ASG i els grups de destinació
En blue/green no es toca cap instància existent: se'n creen de noves, es comproven, se'ls passa el trànsit i només llavors es terminen les antigues.
flowchart TB
ALB[alb-mercadofresco-tienda] -->|100% abans| TGA[tg-mercadofresco-tienda]
ALB -.->|100% despres| TGV[tg-mercadofresco-tienda-verde]
TGA --> AZUL[Blau: v1.4.3<br/>i-aaa1, i-aaa2]
TGV --> VERDE[Verd: v1.5.0<br/>i-vvv1, i-vvv2]
VERDE --> H[BeforeAllowTraffic:<br/>escalfar memoria cau]
H --> S{Estat OK?}
S -->|No| F[Terminar el verd<br/>El blau continua servint]
S -->|Si| C[Canviar l'oient de l'ALB]
C --> W[Esperar 30 min<br/>vigilant les alarmes]
W -->|Alarma| R[REVERSIO:<br/>tornar al blau en 90 s]
W -->|Tot be| T[Terminar el blau]
aws deploy update-deployment-group \
--application-name app-mercadofresco-tienda \
--current-deployment-group-name dg-mercadofresco-tienda-produccion \
--deployment-style '{"deploymentType":"BLUE_GREEN",
"deploymentOption":"WITH_TRAFFIC_CONTROL"}' \
--blue-green-deployment-configuration '{
"terminateBlueInstancesOnDeploymentSuccess": {
"action": "TERMINATE", "terminationWaitTimeInMinutes": 30 },
"deploymentReadyOption": { "actionOnTimeout": "CONTINUE_DEPLOYMENT" },
"greenFleetProvisioningOption": { "action": "COPY_AUTO_SCALING_GROUP" }}' \
--profile mercadofresco-dev --region eu-west-1terminationWaitTimeInMinutes: 30 és la finestra en què l'entorn blau continua existint, apagat
però íntegre, després del canvi de trànsit: és el que fa que la reversió sigui de noranta segons, perquè
només cal tornar l'oient al grup de destinació blau —amb 0 estalvies cèntims i tornar enrere passa a ser un
desplegament complet de deu minuts—. actionOnTimeout: CONTINUE_DEPLOYMENT fa el canvi de trànsit
automàtic; l'alternativa STOP_DEPLOYMENT espera que algú premi «reencaminar trànsit», útil el
primer dia i insostenible com a pràctica. I COPY_AUTO_SCALING_GROUP crea un ASG nou copiant
lt-mercadofresco-tienda, davant de DISCOVER_EXISTING amb instàncies ja etiquetades.
| Aspecte | Al lloc | Blue/green |
|---|---|---|
| Cost durant el desplegament | Cap | Capacitat duplicada |
| Temps de reversió | Desplegament complet (~10 min) | ~90 segons |
| Risc per a la versió estable | Se sobreescriu | Intacta fins al final |
| Durada total | 6-12 min | 15-40 min |
| Estat local al disc | Es conserva | Es perd: instàncies noves |
MercadoFresco fa servir al lloc amb HalfAtATime en desenvolupament i blue/green en producció. Duplicar
dos t3.medium mitja hora són uns nou cèntims per desplegament; noranta segons de reversió valen
força més que això.
L'appspec de Lambda i d'ECS
Per a Lambda i ECS l'appspec és una altra cosa: no copia fitxers, declara quina versió ha de rebre el
trànsit. Admet YAML o JSON.
# appspec-lambda.yml
version: 0.0
Resources:
- mercadofresco-cobrar-pago:
Type: AWS::Lambda::Function
Properties:
Name: mercadofresco-cobrar-pago
Alias: produccion
CurrentVersion: "7" # la que serveix ara
TargetVersion: "8" # la nova
Hooks:
- BeforeAllowTraffic: mercadofresco-validar-antes-de-trafico
- AfterAllowTraffic: mercadofresco-validar-despues-de-traficoDiferència important: a Lambda els ganxos són funcions Lambda, no scripts, i tenen una obligació
que sempre s'oblida: comunicar el seu resultat amb PutLifecycleEventHookExecutionStatus, o CodeDeploy
espera fins al timeout i falla.
import boto3, json, os
cd = boto3.client("codedeploy")
lam = boto3.client("lambda")
def handler(event, context):
id_desplegament = event["DeploymentId"]
estat = "Failed"
try:
# Invoquem la versio NOVA directament, abans que rebi transit real
r = lam.invoke(
FunctionName=f"mercadofresco-cobrar-pago:{os.environ['VERSION_NUEVA']}",
Payload=json.dumps({"modo": "prueba_humo", "importe_eur": 1.00,
"clave_idempotencia": f"humo-{id_desplegament}"}))
cos = json.loads(r["Payload"].read())
if r["StatusCode"] == 200 and cos.get("estado") == "cobrado":
estat = "Succeeded"
except Exception as e:
print(f"Prova de fum fallida: {e}")
# SENSE aquesta crida, CodeDeploy espera fins al timeout i falla el desplegament
cd.put_lifecycle_event_hook_execution_status(
deploymentId=id_desplegament,
lifecycleEventHookExecutionId=event["LifecycleEventHookExecutionId"],
status=estat)
return {"status": estat}Fixa't en la clave_idempotencia derivada de l'identificador del desplegament: la prova de fum passa pel
mateix camí que un cobrament real, i sense una clau única cada desplegament reutilitzaria l'anterior. És la
idempotència de 07-05 aplicada al desplegament mateix. A ECS l'appspec referencia la definició de
tasca i el contenidor; el detall d'ECS és el mòdul 10.
Canari i lineal: desplegar mercadofresco-cobrar-pago
Aquí sí que hi ha desplaçament percentual de trànsit, la millor xarxa de seguretat que ofereix CodeDeploy.
| Configuració | Com desplaça | Durada | Quan |
|---|---|---|---|
AllAtOnce |
100 % de cop | Segons | Desenvolupament |
Canary10Percent5Minutes |
10 %, espera 5 min, la resta | ~5 min | Cobraments: poques peticions dolentes |
Canary10Percent30Minutes |
10 %, espera 30 min, la resta | ~30 min | Canvis de risc alt |
Linear10PercentEvery1Minute |
+10 % cada minut | ~10 min | Degradació gradual |
Canari o lineal, amb criteri. El canari manté un percentatge petit una estona i després salta al
100 %: si la fallada és evident, només el 10 % la pateix i poc temps. El lineal puja a poc a poc i detecta
millor les degradacions que depenen de la càrrega —una fuita de memòria, un pool que s'esgota— però exposa el
50 % abans de la meitat del desplegament. Per a mercadofresco-cobrar-pago, la Marta tria
Canary10Percent5Minutes: una fallada en el cobrament és evident en segons, no gradual, i amb 900
comandes/hora al pic, cinc minuts al 10 % són unes 7 comandes exposades.
El mecanisme es recolza en versions i àlies, que vam veure a 02-05: mercadofresco-cobrar-pago:produccion
apunta a la versió 7, i CodeDeploy li afegeix un pes cap a la 8 pujant-lo segons la configuració. Tot el
que invoca la funció fa servir l'àlies i no s'assabenta de res.
Es llança amb aws deploy create-deployment i
--deployment-config-name CodeDeployDefault.LambdaCanary10Percent5Minutes, passant l'appspec a
--revision. L'alarma que ho vigila va sobre els errors de l'àlies, no de la funció sencera:
aws cloudwatch put-metric-alarm \
--alarm-name mercadofresco-cobrar-pago-errores-canario \
--namespace AWS/Lambda --metric-name Errors --statistic Sum \
--dimensions Name=FunctionName,Value=mercadofresco-cobrar-pago \
Name=Resource,Value=mercadofresco-cobrar-pago:produccion \
--period 60 --evaluation-periods 1 --threshold 3 \
--comparison-operator GreaterThanThreshold --treat-missing-data notBreaching \
--alarm-actions arn:aws:sns:eu-west-1:111122223333:alertas-mercadofresco \
--profile mercadofresco-dev --region eu-west-1El període de 60 segons i un sol període d'avaluació són deliberats: amb una finestra de 5 minuts per al canari, una alarma de 3 períodes de 5 minuts saltaria quan el desplegament ja és al 100 %. L'alarma ha de ser més ràpida que el desplegament que vigila.
Reversió automàtica: la peça que resol el problema 4
Aquesta és la secció per la qual existeix la lliçó. CodeDeploy reverteix sola en tres situacions, declarades
a autoRollbackConfiguration: DEPLOYMENT_FAILURE quan un ganxo retorna diferent de 0 o expira,
DEPLOYMENT_STOP_ON_ALARM quan una alarma d'alarmConfiguration passa a ALARM durant el desplegament,
i DEPLOYMENT_STOP_ON_REQUEST quan algú l'atura a mà.
L'important és entendre què vol dir «revertir» en cada modalitat, perquè no és el mateix. Al lloc, CodeDeploy llança un desplegament nou amb la revisió anterior: complet, amb els seus ganxos i els seus minuts. En blue/green dins de la finestra d'espera, torna l'oient de l'ALB al grup de destinació blau: noranta segons, i les instàncies blaves ni se n'han assabentat. A Lambda o ECS, torna el pes de l'àlies a la versió anterior: segons.
| Alarma | Què detecta | Per què és aquí |
|---|---|---|
mercadofresco-alb-latencia-alta |
p95 > 1.500 ms, 2 períodes de 60 s | Una versió lenta és una versió trencada |
mercadofresco-pedidos-fallidos |
DLQ > 5 missatges en 5 min | El consumidor nou no processa bé |
mercadofresco-tienda-degradada |
Composta (05-01) | Visió de conjunt |
Triar les alarmes és la decisió de disseny d'aquesta secció, i han de complir tres condicions.
Detectar el que provoca un desplegament dolent: una alarma de cost no hi pinta res; una de latència o
de 5xx, sí. Ser més ràpides que el desplegament, perquè una de 3 períodes de 5 minuts no protegeix un
desplegament de 10. I no saltar per causes alienes: si mercadofresco-alb-latencia-alta salta cada divendres
a les 19:00 pel pic normal, revertirà desplegaments correctes i l'equip acabarà desactivant la
reversió. Mira-les un mes abans de connectar-les.
L'estat inicial de l'alarma importa. Si en començar ja és en ALARM, CodeDeploy no arrenca: és
correcte —no despleguis sobre un sistema que ja va malament— però desconcerta la primera vegada.
Comparació amb la reversió manual i amb Route 53 ponderat
| Mecanisme | Temps de reversió | Automàtic | Granularitat |
|---|---|---|---|
| Manual per SSH (el d'avui) | 10-30 min, amb nervis | No | Instància |
| CodeDeploy al lloc | ~10 min | Sí | Instància |
| CodeDeploy blue/green | ~90 s | Sí | Entorn complet |
| CodeDeploy canari (Lambda) | Segons | Sí | % d'invocacions |
| Route 53 ponderat (03-05) | 60 s + TTL | No de sèrie | % de resolucions DNS |
Val la pena comparar amb Route 53 ponderat, que a 03-05 també repartia trànsit i podria semblar alternatiu. No ho és, per dues raons. El TTL del DNS: encara que posis el pes a 0 a l'instant, els resolutors i els navegadors continuen fent servir la resposta desada durant el TTL, així que «revertir» triga minuts i mai no és complet. I que el repartiment és de resolucions, no de peticions: un client que resol una vegada i manté la connexió es queda on ha caigut. Route 53 ponderat és excel·lent per moure trànsit entre regions; CodeDeploy és el mecanisme correcte per desplegar una versió, perquè opera sobre el balancejador i és immediat i complet.
Migracions d'esquema: expansió i contracció
Aquí hi ha l'advertiment més important de la lliçó, i no és un detall tècnic sinó una regla de procés: el desplegament del codi i el canvi de l'esquema no han d'anar al mateix pas.
El raonament és senzill. Durant qualsevol desplegament gradual conviuen dues versions del codi contra
una sola base de dades: si l'AfterInstall de la nova executa ALTER TABLE pedidos DROP COLUMN direccion_antigua, la vella —que continua servint la meitat del trànsit— comença a fallar. I si el
desplegament reverteix, la reversió no desfà l'ALTER TABLE: et quedes amb el codi vell i l'esquema
nou, el pitjor dels estats possibles. La resposta és expansió i contracció, en tres desplegaments:
| Fase | Què es fa | Compatible amb | Quan |
|---|---|---|---|
| 1. Expandir | Afegir el nou sense treure res: columna NULLABLE |
Totes dues versions | Abans del codi |
| 2. Migrar | Codi que escriu als dos i llegeix del nou amb reserva | Totes dues versions | Desplegament normal |
| 3. Contraure | Treure el vell | Només la nova | Dies o setmanes després |
Aplicat a la franja horària que el Luis afegirà:
-- FASE 1 (expandir): ABANS de desplegar el codi. Sense NOT NULL, sense DEFAULT i sense
-- index: no reescriu la taula ni bloqueja. La 1.4.3 no coneix la columna i la ignora.
ALTER TABLE pedidos ADD COLUMN franja_entrega VARCHAR(10) NULL;
-- FASE 3 (contraure): setmanes despres, quan CAP instancia no serveix ja la 1.4.3
ALTER TABLE pedidos ALTER COLUMN franja_entrega SET NOT NULL;
CREATE INDEX CONCURRENTLY idx_pedidos_franja ON pedidos(franja_entrega);Quatre regles pràctiques que se'n deriven. No executis mai migracions en un ganxo de CodeDeploy:
el ganxo corre a cada instància, així que amb quatre instàncies tens quatre ALTER TABLE
simultanis, i si falla a mitges el desplegament reverteix però l'esquema no. La migració és un pas propi
del pipeline, abans del desplegament de l'aplicació; això és 08-04. Tota migració d'expansió ha de ser
reversible o innòcua: una columna NULLABLE sobra però no molesta si el codi reverteix. I
CREATE INDEX CONCURRENTLY per no bloquejar la taula, fora del desplegament. El recorregut complet, amb
el consumidor de la cua i el contracte de l'esdeveniment, és la lliçó 08-05.
Observabilitat del desplegament i diagnòstic d'una fallada
CodeDeploy publica a EventBridge cada canvi d'estat, així que tot el de 07-03 s'hi aplica, amb un
patró sobre source: ["aws.codedeploy"], detail-type: ["CodeDeploy Deployment State-change Notification"] i detail.state: ["FAILURE", "STOP"].
Amb destinació a alertas-mercadofresco i una transformació d'entrada que deixi un missatge llegible: quina
aplicació, quina versió, quin estat i l'enllaç a la consola. Un desplegament que reverteix sol a les 19:15
d'un divendres és una bona notícia, però només si algú se n'assabenta. El diagnòstic d'una fallada:
# Quin desplegament ha fallat i per que; despres, quina instancia i quin ganxo concret
aws deploy get-deployment --deployment-id d-A1B2C3D4E \
--query 'deploymentInfo.[status,errorInformation.code,errorInformation.message]' --output table
aws deploy get-deployment-target --deployment-id d-A1B2C3D4E --target-id i-0abc123def456 \
--query 'deploymentTarget.instanceTarget.lifecycleEvents[?status==`Failed`]'| Codi d'error | Què significa | On cal mirar |
|---|---|---|
HEALTH_CONSTRAINTS |
Menys instàncies sanes de les exigides | Percentatge amb flota petita? |
SCRIPT_FAILED |
Un ganxo ha retornat diferent de 0 | El registre de l'agent en aquella instància |
SCRIPT_TIMED_OUT |
Un ganxo ha superat el seu timeout |
Puja el timeout o accelera l'script |
NO_INSTANCES |
Cap instància no encaixa | Etiquetes o nom de l'ASG |
AGENT_ISSUE_* |
L'agent no respon | És viu? Hi ha sortida de xarxa? |
ALARM_ACTIVE |
Una alarma era en ALARM en començar |
Arregla el sistema abans de desplegar |
Cost i neteja
| Concepte | Cost |
|---|---|
| CodeDeploy a EC2, Lambda i ECS | 0 USD (0,02 USD/instància en servidors locals) |
| Capacitat duplicada en blue/green | ~0,09 USD per desplegament (2 × t3.medium, 30 min) |
| Emmagatzematge de versions de Lambda | Quota de 75 GB per regió |
| Total de MercadoFresco | ~2 USD/mes amb 20 desplegaments |
# Les versions antigues de Lambda NO s'esborren soles i consumeixen quota
aws lambda list-versions-by-function --function-name mercadofresco-cobrar-pago \
--query 'Versions[?Version!=`$LATEST`].[Version,LastModified]' --output table
aws lambda delete-function --function-name mercadofresco-cobrar-pago:3
# ASG orfes d'un blue/green fallit: instancies corrent i facturant
aws autoscaling describe-auto-scaling-groups \
--query "AutoScalingGroups[?starts_with(AutoScalingGroupName,'CodeDeploy_')].[AutoScalingGroupName,DesiredCapacity]"Els ASG orfes són el cost ocult d'aquesta lliçó. Un blue/green interromput a mitges pot deixar un
ASG amb prefix CodeDeploy_ i les seves instàncies vives, servint a ningú i facturant. Revisa'ls després de cada
desplegament fallit.
Errors Habituals i Consells
Un ApplicationStop que pot fallar. S'executa des de la revisió anterior i bloqueja tots els
desplegaments futurs d'aquella instància. Acaba sempre amb exit 0.
Oblidar file_exists_behavior: OVERWRITE. El valor per defecte DISALLOW fa fallar el desplegament
tan bon punt un fitxer ja existeix a la destinació, que és sempre a partir del segon.
Un ValidateService que només comprova que el procés és viu. Un que no arriba a Aurora passa la
comprovació i rep trànsit: valida dependències i versió.
Executar migracions de base de dades en un ganxo. Corre a cada instància, no és transaccional respecte al desplegament, i la reversió no ho desfà. És l'error més car del mòdul.
AllAtOnce en producció, que no és un desplegament sinó una caiguda programada; i percentatges de flota
sana amb flotes petites, perquè FLEET_PERCENT=90 amb 2 instàncies exigeix 2 de sanes i cap desplegament
no pot començar. Fes servir HOST_COUNT.
terminationWaitTimeInMinutes: 0 en blue/green. Estalvies cèntims i perds la reversió de 90
segons, que és la raó per la qual vas triar blue/green.
Alarmes més lentes que el desplegament, que salten quan ja està tot desplegat; o alarmes amb falsos positius connectades a la reversió, que revertiran desplegaments bons fins que l'equip desactivi la reversió sencera. Mira-les un mes abans de connectar-les.
Oblidar PutLifecycleEventHookExecutionStatus en un ganxo de Lambda, que fa esperar fins al timeout amb
un missatge que no esmenta la crida que falta; o manca de permisos de KMS al rol de la instància,
que impedeix desxifrar el ZIP amb un error que sembla d'S3.
Consell: prova la reversió a propòsit. Desplega una versió amb ValidateService que retorni 1 i
cronometra: una reversió que ningú no ha assajat és una hipòtesi. Tingues un /salud que digui la veritat,
amb l'estat de cada dependència i la versió que serveix, perquè és la peça sobre la qual es recolza tota la
resta. I desplega primer en desenvolupament: els ganxos trencats es descobreixen igual de bé allà.
Exercicis
Exercici 1: el desplegament que es va quedar encallat
El Luis desplega la 1.5.0 a dg-mercadofresco-tienda-produccion (al lloc, HalfAtATime, 4 instàncies).
La primera meitat va bé; la segona falla amb SCRIPT_FAILED a ApplicationStop. La reversió es llança i
també falla a ApplicationStop. Resultat: 2 instàncies amb 1.5.0, 2 amb 1.4.3 i cap desplegament
possible. Investigant, veu que el parar_servicio.sh de la 1.4.3 fa set -e i systemctl stop mercadofresco && rm /var/run/mercadofresco.pid, i que aquest fitxer PID ja no existeix des de la 1.4.2.
Respon: (a) per què la reversió falla al mateix lloc; (b) per què les dues primeres instàncies sí que van funcionar; (c) com desbloqueges la situació ara mateix, amb les ordres; (d) com evites que torni a passar; (e) què hauria canviat si el grup fos blue/green.
Exercici 2: triar estratègia per a tres components
Per a cada component indica destinació, configuració de desplegament, alarmes connectades a la reversió i
justificació. (a) La botiga web a asg-mercadofresco-tienda (2-4 instàncies), amb pic els divendres
de 17:00 a 21:00 i 900 comandes/hora, on un error 500 és una venda perduda. (b) La Lambda
mercadofresco-cobrar-pago, unes 900 invocacions/hora al pic, ja idempotent (07-05), on una fallada
pot cobrar dues vegades o no cobrar. (c) Els treballadors d'asg-mercadofresco-trabajadores, que
consumeixen cola-mercadofresco-pedidos, no reben trànsit de l'ALB i si s'aturen 5 minuts la cua creix i
es buida després.
Exercici 3: la migració que va trencar la reversió
El dimarts a les 11:00, el Luis desplega la 1.6.0 en blue/green. La 1.6.0 reanomena la columna direccion a
direccion_entrega, i l'AfterInstall executa
ALTER TABLE pedidos RENAME COLUMN direccion TO direccion_entrega;. El verd arrenca bé, passa
ValidateService i rep el 100 % del trànsit. Al cap de 8 minuts, mercadofresco-pedidos-fallidos salta: el
consumidor de la cua, que encara és 1.5.2, falla a cada missatge. CodeDeploy reverteix al blau en 90 segons.
I llavors la botiga sencera deixa de funcionar.
Respon: (a) per què la reversió va empitjorar les coses; (b) quantes vegades es va executar l'ALTER TABLE
i què va passar a la segona; (c) el pla de recuperació immediata; (d) com s'hauria d'haver fet el
canvi, amb les fases i què es desplega a cadascuna; (e) quin control automàtic hauria impedit que
això arribés a producció.
Solucions
Solució 1
(a) Perquè ApplicationStop s'executa sempre des de la revisió anterior instal·lada a la
instància, i a les instàncies 3 i 4 la revisió anterior és la 1.4.3, l'script de la qual està trencat. La
reversió és un desplegament nou de la 1.4.3, i el seu primer ganxo torna a ser l'ApplicationStop del
que hi ha instal·lat —que continua sent la 1.4.3 trencada—. S'executa el mateix script defectuós i falla igual.
El bucle és exactament el motiu pel qual aquest ganxo ha de ser a prova de bales.
(b) Per casualitat, i val la pena entendre-la: a les instàncies 1 i 2 el fitxer PID existia
—eren més antigues i n'arrossegaven un de la 1.4.1—, així que rm va retornar 0 i l'script va acabar bé. A les
3 i 4, recreades per l'ASG amb la 1.4.3 neta, no hi havia fitxer, rm va retornar 1 i set -e va avortar. Un
desplegament que funciona a mitja flota i falla a l'altra meitat gairebé sempre assenyala estat divergent entre
instàncies, i això ja és un problema en si: les instàncies d'un ASG haurien de ser indistingibles.
(c) Desbloquejar. El camí ràpid, si la botiga serveix malament, és arreglar l'script a mà a
les instàncies afectades per Session Manager, editant el
deployment-root/<id>/deployment-archive/scripts/parar_servicio.sh, i tornar a llançar. El net és saltar-se
el ganxo una sola vegada: a la consola es pot llançar un desplegament marcant l'opció d'ometre
ApplicationStop, BeforeBlockTraffic i AfterBlockTraffic, pensada exactament per a aquest cas.
L'alternativa equivalent per CLI és esborrar i recrear el grup de desplegament, perquè això elimina la
referència a l'última revisió coneguda i ApplicationStop deixa d'executar-se:
aws deploy delete-deployment-group --application-name app-mercadofresco-tienda \
--deployment-group-name dg-mercadofresco-tienda-produccion \
--profile mercadofresco-dev --region eu-west-1
# ...recrear-lo, i desplegar la 1.4.3 de nou amb create-deployment.(d) Tres mesures. A l'script, treure set -e, posar exit 0 incondicional al final i fer servir
rm -f, que no falla si el fitxer no existeix. Al procés, una prova dels ganxos a CodeBuild:
un contenidor que executi cada script contra un sistema net i comprovi que retornen 0 en els casos
«el servei no existeix», «el servei està aturat» i «el servei està corrent». I desplegar sempre primer en
desenvolupament, on aquesta fallada hauria aparegut sense conseqüències.
(e) Amb blue/green no hauria passat res: les instàncies verdes són noves i no tenen revisió
anterior, així que ApplicationStop ni s'executa. Si el desplegament fallés per un altre motiu, el blau
—intacte, amb la 1.4.3 funcionant— continuaria servint el 100 % i la reversió seria tornar l'oient
de l'ALB. És un argument a favor de blue/green que no apareix a les taules: elimina d'arrel tota una classe de
fallades, les heretades del desplegament anterior.
Solució 2
(a) La botiga web. EC2 amb l'ASG, blue/green, terminationWaitTimeInMinutes: 30 i
actionOnTimeout: CONTINUE_DEPLOYMENT. Alarmes: mercadofresco-alb-latencia-alta i
mercadofresco-tienda-degradada. Justificació: amb 2-4 instàncies, un desplegament al lloc deixa la
meitat de la capacitat fora justament quan més falta fa; blue/green manté el 100 % durant tot el
procés, i la reversió de 90 segons és el que permet desplegar sense por. Regla operativa afegida:
cap desplegament de la botiga entre les 16:00 i les 22:00 del divendres, no per desconfiar del mecanisme
sinó perquè equivocar-se al pic surt desproporcionadament car. Ganxos: BeforeAllowTraffic escalfa
la memòria cau —clau, o la primera onada dispara la latència i reverteix un desplegament bo— i
AfterAllowTraffic fa una prova de fum amb trànsit real.
(b) La Lambda de cobraments. Canary10Percent5Minutes, amb
mercadofresco-cobrar-pago-errores-canario (període 60 s, 1 avaluació, llindar 3) i una sobre Duration
p99. Justificació: una fallada de cobrament és evident en segons, no gradual, així que el canari detecta
abans i exposa menys que el lineal. Amb 900 invocacions/hora, 5 minuts al 10 % són unes 7 comandes
exposades, i la idempotència de 07-05 evita que un reintent després de la reversió dupliqui el cobrament. Més un
BeforeAllowTraffic que invoca la versió nova amb un pagament de prova d'1,00 €. El detall que no s'ha
d'oblidar: l'alarma ha de portar la dimensió Resource de l'àlies, o mesuraria els errors de totes les
versions juntes i es contaminaria amb les invocacions de la vella.
(c) Els treballadors. Al lloc amb AllAtOnce, sense alarmes de latència, amb
mercadofresco-pedidos-fallidos connectada a la reversió. Justificació: aquí el raonament canvia
del tot, i aquest és l'interès de l'apartat. No reben trànsit de l'ALB, així que no hi ha peticions que
puguin fallar: si s'aturen cinc minuts, la cua creix i es buida després, que és exactament
l'amortiment que buscàvem a 07-01. Blue/green seria complexitat i cost sense benefici. El que sí que cal
garantir és un ApplicationStop net, que deixi acabar el missatge en curs i no l'esborri a
mitges, o quedaran missatges en vol reapareixent en expirar la visibilitat. I vigilar
ApproximateAgeOfOldestMessage després del desplegament: si no baixa en deu minuts, el consumidor nou no
processa encara que el procés sigui viu.
Solució 3
(a) Perquè la reversió va tornar el codi a la 1.5.2 però no va desfer l'esquema. La 1.5.2
consulta direccion, que ja no existeix. Abans de la reversió almenys la botiga funcionava amb la 1.6.0 i
només fallava el consumidor; després falla tot, perquè el 100 % del trànsit el serveix un codi
incompatible amb l'esquema. És el parany que la lliçó adverteix: la reversió reverteix artefactes, no
bases de dades, i un canvi d'esquema destructiu converteix la teva xarxa de seguretat en un
accelerador de l'incident.
(b) Es va executar una vegada per instància verda, és a dir 2 vegades. La primera va tenir èxit; la segona
va fallar amb ERROR: column "direccion" does not exist, perquè el canvi de nom ja estava fet. Que el
desplegament no s'aturés aquí depèn de si l'script s'empassava l'error. Aquest comportament és la
demostració de per què les migracions no van en ganxos: no són idempotents i s'executen tantes
vegades com instàncies hi hagi.
(c) Recuperació immediata, amb la botiga caiguda, així que ràpid i sense elegàncies. Convergir cap
endavant, no cap enrere: l'esquema ja és a l'estat nou i tornar a canviar-li el nom és una altra migració
amb risc, així que redesplegar la 1.6.0, que sí que és compatible, i recuperar la botiga. Després,
desplegar la versió compatible del consumidor, que continua a 1.5.2 i continua fallant; mentrestant els
missatges s'acumulen a cola-mercadofresco-pedidos i acabaran a la DLQ, però no es perden. Amb la
botiga servint, aplicar el runbook de la DLQ de 07-05 —contenir, classificar, reprocessar—. I un post-mortem
sense buscar culpables, amb la regla de procés escrita.
(d) Com s'hauria d'haver fet, en tres desplegaments separats per dies. Desplegament 1 (expandir),
dilluns: només esquema, sense codi nou —ALTER TABLE pedidos ADD COLUMN direccion_entrega VARCHAR(255) NULL; més un UPDATE que copiï els valors—; la 1.5.2 continua funcionant perquè no coneix la columna nova
i no li molesta. Desplegament 2 (migrar), dimarts: el codi 1.6.0 escriu a les dues columnes i llegeix
de direccion_entrega amb reserva a direccion, cosa que el fa compatible en tots dos sentits —conviu
amb la 1.5.2 durant el desplegament gradual i funciona si cal revertir—; aquí el consumidor de la cua es
desplega abans que la botiga, perquè sàpiga llegir el camp nou abans que comenci a arribar, que és
l'ordre productor/consumidor que tanca 08-05. Desplegament 3 (contraure), la setmana següent, quan
cap instància no serveix ja la 1.5.2: ALTER TABLE pedidos DROP COLUMN direccion;. I cada fase d'esquema
com a pas propi del pipeline, executat una sola vegada des d'una tasca dedicada, mai des d'un ganxo.
(e) Tres controls, de més barat a més car. Una anàlisi de les migracions a CodeBuild que faci fallar
la construcció si detecta DROP COLUMN, RENAME COLUMN, ALTER COLUMN ... NOT NULL o DROP TABLE sense
una etiqueta explícita de «contracció aprovada»: són trenta línies d'script i haurien parat això en
sec. Una prova de compatibilitat cap enrere que arrenqui la versió anterior del codi contra
l'esquema nou i executi la suite de fum —simula directament la reversió, i és sorprenentment rara
a la pràctica—. I revisió obligatòria de tot canvi a migraciones/ mitjançant una regla de
propietaris de codi, perquè cap canvi d'esquema no entri amb una aprovació distreta.
Conclusió
El ritual del Luis s'ha acabat. Ja no hi ha ssh, ni scp, ni quaranta segons d'errors per instància,
ni dues versions convivint sense control. Hi ha una aplicació app-mercadofresco-tienda, dos grups de
desplegament que fan que la mateixa revisió es comporti de manera diferent en desenvolupament i en producció, un
artefacte identificat a mercadofresco-artefactos i un pla que CodeDeploy executa igual totes les
vegades. I sobretot, una cosa que no existia: una tornada enrere que no depèn que algú estigui mirant.
Coneixes les tres destinacions i què admet cadascuna —a EC2 no hi ha canari ni lineal; a Lambda i ECS no hi ha
desplegament al lloc— i saps que l'agent només cal a EC2, instal·lat com a associació de Systems
Manager perquè s'actualitzi sol. Domines l'appspec.yml amb els seus files, permissions i hooks,
inclòs file_exists_behavior: OVERWRITE, la primera fallada que troba tothom. I coneixes els
ganxos un a un, amb les dues veritats que més incidents eviten: que ApplicationStop s'executa des de
la revisió anterior —i per això ha d'acabar sempre amb exit 0— i que ValidateService és el ganxo
que justifica tota la resta, comprovant dependències i versió en lloc de conformar-se amb un procés
viu.
Saps triar el ritme: AllAtOnce només en desenvolupament, HalfAtATime amb marge de capacitat, OneAtATime
quan la prudència importa més que el rellotge, i per què un FLEET_PERCENT alt amb dues instàncies impedeix
arrencar qualsevol desplegament. Tens el blue/green amb el seu terminationWaitTimeInMinutes de 30 minuts
—literalment el preu de la reversió de 90 segons— i el seu avantatge amagat: en ser instàncies noves,
elimina d'arrel les fallades heretades del desplegament anterior. I el canari de mercadofresco-cobrar-pago
amb Canary10Percent5Minutes, la seva alarma sobre la dimensió Resource de l'àlies i períodes més curts que
el desplegament mateix, perquè una alarma més lenta que allò que vigila no protegeix res.
La peça central és la reversió automàtica, i ara saps què vol dir en cada cas: un desplegament complet al lloc, noranta segons en blue/green dins de la finestra, segons a Lambda. Saps que triar les alarmes és una decisió de disseny amb tres condicions —que detectin el que provoca un desplegament dolent, que siguin més ràpides que el desplegament i que no tinguin falsos positius, perquè una alarma sorollosa acaba amb l'equip desactivant la reversió sencera—. I per què Route 53 ponderat no serveix per a això: el TTL del DNS fa que revertir sigui lent i incomplet.
I t'endús l'advertiment més important del mòdul, que no és tècnic sinó de procés: el desplegament de
l'aplicació i el canvi d'esquema no van al mateix pas. Perquè conviuen dues versions contra una
sola base de dades, perquè un ganxo s'executa una vegada per instància, i sobretot perquè la reversió
reverteix artefactes, no bases de dades —un RENAME COLUMN mal col·locat converteix la teva xarxa de seguretat en
un accelerador de l'incident—. La resposta és expansió i contracció en tres desplegaments separats.
I aquí hi ha el que falta. Cada peça funciona, però ningú no les ha encadenat. El Luis encara ha
de recordar-se de llançar la construcció en fusionar, copiar la ruta de l'artefacte, escriure
aws deploy create-deployment amb el bucket i la clau correctes, esperar, mirar si ha anat bé i repetir-ho
per a l'entorn següent. El pas d'esquema s'executa a mà. Ningú no comprova que el que es desplega en
producció sigui exactament el que es va validar en preproducció, ni hi ha un moment en què la Marta aprovi
formalment que un canvi surti. Eines excel·lents i zero orquestració: continuem depenent que
una persona recordi la seqüència un divendres a la tarda.
A 08-04, «AWS CodePipeline», s'encadena tot. Veurem la diferència entre lliurament continu i
desplegament continu i per què MercadoFresco tria el primer, amb aprovació manual abans de producció;
l'estructura de pipelines, etapes, accions i artefactes que flueixen entre elles; els tipus V1 i V2, els
disparadors per branca, etiqueta o ruta de fitxer, i les variables de pipeline; l'aprovació manual
amb la informació exacta que la Marta necessita per decidir en trenta segons; les etapes de desenvolupament,
preproducció i producció; les portes de qualitat amb una acció Lambda que consulta les mètriques de
MercadoFresco/Tienda i atura el pipeline si alguna cosa es degrada; els reintents, els permisos per acció i
l'accés entre comptes; i les notificacions cap a alertas-mercadofresco i Slack.
Curs d'AWS
Mòdul 1: Introducció a AWS
- Què és AWS?
- Configuració del teu compte d'AWS
- Infraestructura global d'AWS
- Consola d'administració d'AWS
- AWS CLI i SDK
Mòdul 2: Serveis principals d'AWS
Mòdul 3: Xarxes i lliurament de contingut
- Amazon VPC
- Grups de seguretat i llistes de control d'accés
- Elastic Load Balancing
- Amazon CloudFront
- Route 53
Mòdul 4: Seguretat i identitat
- AWS Identity and Access Management (IAM)
- AWS Key Management Service (KMS)
- Secrets Manager i Parameter Store
- AWS Shield
- AWS WAF
Mòdul 5: Monitoratge i gestió
- Amazon CloudWatch
- AWS X-Ray i traçabilitat distribuïda
- AWS CloudTrail
- AWS Config
- AWS Trusted Advisor
Mòdul 6: Bases de dades
- Com triar la base de dades adequada
- Amazon DynamoDB
- Amazon Aurora
- Amazon Redshift
- Amazon ElastiCache
Mòdul 7: Integració d'aplicacions
- Amazon SQS
- Amazon SNS
- Amazon EventBridge
- AWS Step Functions
- Patrons d'integració: idempotència, reintents i cues de missatges fallits
