El codi de MercadoFresco ja viu en un repositori amb regles, branques curtes i pull requests que algú
revisa. Però revisar una PR és una persona llegint un diff, i hi ha preguntes que ningú no pot respondre
llegint: passen les 214 proves? arrenca el projecte en una màquina neta, o només al portàtil del Luis
on hi ha un psycopg2 instal·lat a mà el 2024? té alguna de les 87 dependències una vulnerabilitat
publicada aquesta setmana? s'ha colat una clau en un fitxer de configuració?
AWS CodeBuild respon tot això automàticament. És un servei de construcció gestionat i sense
servidors: arrenca un contenidor net, clona el teu codi, executa el que li diguis en un buildspec.yml,
desa els resultats i s'apaga, cobrant per minut d'execució i no per tenir-lo. Aquí és on
«funciona al meu portàtil» deixa de ser un argument, perquè a partir d'ara l'únic que compta és si
funciona en un contenidor buit que ningú no ha tocat.
Avís de cost. CodeBuild cobra per minut segons la mida de còmput: a
eu-west-1, unBUILD_GENERAL1_SMALLuns 0,005 USD/min i unMEDIUMuns 0,010, amb 100 minuts gratis al mes del tipus petit. Amb 20 construccions diàries de 4 minuts en MEDIUM, MercadoFresco pagarà uns 24 USD al mes. El car no és això: és una construcció de 22 minuts que ningú no optimitza, o construir dins de la VPC sense ser conscient del cost del NAT, que veurem al final. Dades fictícies.
Contingut
- Què és la integració contínua i quin problema resol
- Anatomia d'un projecte de CodeBuild
- El rol de servei i els seus permisos
- El
buildspec.ymlde MercadoFresco, comentat - Les fases, una a una
- Variables d'entorn i secrets sense fuites als registres
- Proves unitàries i informes de proves i cobertura
- Què fer quan una prova falla
- Proves d'integració: simulació o clon d'Aurora
- Anàlisi estàtica, dependències i secrets filtrats
- Qualitat com a porta, no com a informe
- Artefactes, memòria cau i construccions en paral·lel
- CodeBuild dins de la VPC, amb el seu avís de cost
- Depurar una construcció que falla
- Mètriques, alarmes i cost real
- Errors habituals i consells
- Exercicis
- Conclusió
Què és la integració contínua i quin problema resol
Integració contínua significa que cada canvi s'integra a la branca compartida i es verifica automàticament, diverses vegades al dia. L'important és la segona meitat: es verifica automàticament. Sense verificació, «integració contínua» és només empènyer codi sovint.
| Símptoma | Causa real | Què l'elimina |
|---|---|---|
| «Al meu portàtil funciona» | El portàtil té estat acumulat | Contenidor net a cada construcció |
| «Se'm va oblidar executar les proves» | Executar-les és voluntari | Execució automàtica a cada push |
| «Aquesta prova fa mesos que falla» | Ningú no mira el resultat | La construcció en vermell bloqueja la PR |
| «Funcionava abans del teu canvi» | Ningú no sap quan es va trencar | Historial de construccions per commit |
| «No sé quina versió hi ha desplegada» | Es desplega una carpeta, no un artefacte | Artefacte versionat i immutable |
Fixa't en el patró: en tots els casos l'arranjament és treure a les persones la responsabilitat de recordar-se'n. Un procés que depèn de la disciplina individual falla el dia que hi ha pressa, que és exactament el dia que més falta fa. El flux que muntarem:
flowchart LR
A[Push o PR] --> B[Contenidor net]
B --> C[install] --> D[pre_build<br/>secrets, lint, escanejos]
D --> E[build<br/>proves + empaquetatge] --> F[post_build]
F --> G{Tot verd?}
G -->|Si| H[Artefacte a<br/>mercadofresco-artefactos] --> J[Desplegament: 08-03]
G -->|No| I[Vermell: alertas-mercadofresco] --> K[La PR no es fusiona]
Anatomia d'un projecte de CodeBuild
Un projecte és la definició de com construir alguna cosa. Les seves set peces:
| Peça | Què defineix | Decisió de MercadoFresco |
|---|---|---|
| Origen | D'on surt el codi | GitHub via conn-mercadofresco-github |
| Entorn | Imatge, mida de còmput, privilegis | amazonlinux2-x86_64-standard:5.0, MEDIUM |
| Rol de servei | Què pot fer la construcció a AWS | rol-codebuild-mercadofresco-tienda |
| Buildspec | Les ordres que cal executar | buildspec.yml a l'arrel del repositori |
| Artefactes | Què es desa i on | ZIP a mercadofresco-artefactos |
| Memòria cau | Què es reutilitza entre construccions | Local (custom + docker layer) |
| Registres | On va la sortida | /aws/codebuild/build-mercadofresco-tienda |
Sobre la imatge de l'entorn. Les gestionades d'AWS porten Python, Node, Java, Go, la CLI i Docker preinstal·lats, i s'actualitzen soles. Una imatge pròpia a ECR té sentit quan instal·lar dependències del sistema triga més de dos o tres minuts a cada construcció: mous aquest temps a una construcció d'imatge ocasional. MercadoFresco comença amb la gestionada.
Sobre la mida de còmput. És la decisió amb més impacte en cost i durada, i la intuïció enganya:
| Mida | vCPU / RAM | USD/min | Durada a MercadoFresco | Cost per construcció |
|---|---|---|---|---|
SMALL |
2 / 3 GB | 0,005 | 9 min 40 s | 0,048 USD |
MEDIUM |
4 / 7 GB | 0,010 | 4 min 10 s | 0,042 USD |
LARGE |
8 / 15 GB | 0,020 | 3 min 30 s | 0,070 USD |
MEDIUM és més barat que SMALL aquí, perquè el doble de preu per minut es compensa amb més del doble
de velocitat: les proves corren amb pytest -n auto i aprofiten els 4 vCPU. De MEDIUM a LARGE, en
canvi, el temps baixa poc i el cost puja, perquè la feina ja no és paral·lelitzable. Cal mesurar, no
suposar: la mida òptima depèn de si la teva construcció sap fer servir els nuclis que li dónes.
Sobre privilegedMode. Només cal per construir imatges de Docker, perquè el dimoni necessita
privilegis. Activa'l únicament quan el necessitis: un contenidor privilegiat que executa codi d'un
repositori té més superfície d'atac.
aws codebuild create-project \
--name build-mercadofresco-tienda \
--source '{"type": "GITHUB",
"location": "https://github.com/mercadofresco/mercadofresco-tienda.git",
"buildspec": "buildspec.yml", "gitCloneDepth": 1, "reportBuildStatus": true}' \
--environment '{"type": "LINUX_CONTAINER",
"image": "aws/codebuild/amazonlinux2-x86_64-standard:5.0",
"computeType": "BUILD_GENERAL1_MEDIUM", "privilegedMode": false,
"environmentVariables": [
{"name": "BUCKET_ARTEFACTOS", "value": "mercadofresco-artefactos", "type": "PLAINTEXT"}]}' \
--artifacts '{"type": "S3", "location": "mercadofresco-artefactos",
"packaging": "ZIP", "namespaceType": "BUILD_ID"}' \
--cache '{"type": "LOCAL", "modes": ["LOCAL_CUSTOM_CACHE", "LOCAL_DOCKER_LAYER_CACHE"]}' \
--service-role arn:aws:iam::111122223333:role/rol-codebuild-mercadofresco-tienda \
--timeout-in-minutes 20 --queued-timeout-in-minutes 30 \
--tags Key=Proyecto,Value=mercadofresco Key=Entorno,Value=produccion \
Key=Componente,Value=cicd Key=Propietario,Value=luis Key=CentroCoste,Value=plataforma \
--profile mercadofresco-dev --region eu-west-1Dos paràmetres mereixen atenció. gitCloneDepth: 1 clona només l'últim commit: els 1.847 commits del
Luis afegeixen 40 segons a cada construcció sense aportar res —tret que necessitis la història per a
git describe, cas en què hi has de posar 0—. I timeout-in-minutes 20 és un fre d'emergència: una
construcció penjada consumiria el temps d'espera per defecte de 60 minuts, i això són minuts facturats.
El rol de servei i els seus permisos
La construcció actua a AWS amb el rol de servei, i aquí el privilegi mínim de 04-01 importa molt:
aquest rol el fa servir codi que canvia a cada commit. Amb PowerUserAccess, qualsevol que pugui fusionar
una PR podria fer qualsevol cosa al compte.
{
"Version": "2012-10-17",
"Statement": [
{ "Sid": "Registros", "Effect": "Allow",
"Action": ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
"Resource": "arn:aws:logs:eu-west-1:111122223333:log-group:/aws/codebuild/build-mercadofresco-*:*" },
{ "Sid": "ArtefactosSoloEnSuPrefijo", "Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:GetObjectVersion"],
"Resource": "arn:aws:s3:::mercadofresco-artefactos/tienda/*" },
{ "Sid": "ConfiguracionNoSensible", "Effect": "Allow",
"Action": ["ssm:GetParameters", "ssm:GetParameter"],
"Resource": "arn:aws:ssm:eu-west-1:111122223333:parameter/mercadofresco/construccion/*" },
{ "Sid": "SoloElSecretoDePruebas", "Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:eu-west-1:111122223333:secret:mercadofresco/pruebas/*" },
{ "Sid": "InformesDePruebas", "Effect": "Allow",
"Action": ["codebuild:CreateReportGroup", "codebuild:CreateReport",
"codebuild:UpdateReport", "codebuild:BatchPutTestCases",
"codebuild:BatchPutCodeCoverages"],
"Resource": "arn:aws:codebuild:eu-west-1:111122223333:report-group/build-mercadofresco-*" }
]
}L'important és als Resource, no a les accions. El rol no pot llegir
mercadofresco/produccion/rds/mfadmin: només secrets sota mercadofresco/pruebas/. És la diferència entre
una construcció compromesa que espatlla un entorn de proves i una que té la contrasenya de
producció. Un projecte de construcció no necessita mai credencials de producció, i si creus que
les necessita, és que estàs desplegant des de la construcció en lloc de des de CodeDeploy (08-03).
El buildspec.yml de MercadoFresco, comentat
Aquest fitxer viu a l'arrel de mercadofresco-tienda, versionat juntament amb el codi, i és el cor de la
lliçó:
version: 0.2
# Variables. Les de 'variables' son publiques i apareixen als registres.
# Les de 'parameter-store' i 'secrets-manager' es resolen en temps d'execucio
# i CodeBuild les emmascara a la sortida.
env:
variables:
BUCKET_ARTEFACTOS: "mercadofresco-artefactos"
COBERTURA_MINIMA: "75"
parameter-store:
URL_API_PRUEBAS: "/mercadofresco/construccion/url_api_pruebas"
HOST_AURORA_PRUEBAS: "/mercadofresco/construccion/host_aurora_pruebas"
secrets-manager:
CLAVE_PASARELA_PRUEBAS: "mercadofresco/pruebas/pasarela:clave_api"
exported-variables:
- VERSION_APP
- COMMIT_CORTO
phases:
install:
runtime-versions:
python: 3.12
commands:
- pip install --upgrade pip
- pip install -r requirements.txt -r requirements-dev.txt
- pip install --quiet bandit pip-audit ruff
pre_build:
commands:
- export COMMIT_CORTO=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c1-7)
- export VERSION_APP=$(cat VERSION)-${COMMIT_CORTO}
- echo "Construint versio ${VERSION_APP}"
# Portes ordenades de mes rapida a mes lenta
- ruff check app/ tests/ && ruff format --check app/ tests/
- git secrets --scan || (echo "SECRET DETECTAT AL CODI"; exit 1)
- pip-audit --strict --desc
- bandit -r app/ -ll -f json -o informe-bandit.json
build:
commands:
# Proves unitaries alhora, amb informe JUnit i cobertura.
- |
pytest tests/unitarias -n auto \
--junitxml=informes/junit-unitarias.xml \
--cov=app --cov-report=xml:informes/cobertura.xml \
--cov-fail-under=${COBERTURA_MINIMA}
# Proves d'integracio contra serveis simulats (moto).
- pytest tests/integracion --junitxml=informes/junit-integracion.xml
# Empaquetatge: nomes el que cal en produccio.
- mkdir -p paquete
- pip install -r requirements.txt --target paquete/ --quiet
- cp -r app/ scripts/ appspec.yml paquete/
- echo "${VERSION_APP}" > paquete/VERSION
- cd paquete && zip -rq ../mercadofresco-tienda-${VERSION_APP}.zip . && cd ..
post_build:
# finally s'executa ENCARA QUE les ordres anteriors fallin.
commands:
- |
if [ "${CODEBUILD_BUILD_SUCCEEDING}" = "1" ]; then
aws s3 cp mercadofresco-tienda-${VERSION_APP}.zip \
s3://${BUCKET_ARTEFACTOS}/tienda/${VERSION_APP}/ \
--metadata commit=${CODEBUILD_RESOLVED_SOURCE_VERSION},version=${VERSION_APP}
echo "Artefacte publicat: ${VERSION_APP}"
else
echo "Construccio fallida: no es publica artefacte"
fi
finally:
- echo "Duracio total: $((SECONDS / 60))m $((SECONDS % 60))s"
# Els informes es registren a CodeBuild i es veuen a la consola amb el seu historic.
reports:
pruebas-unitarias:
files: ["informes/junit-unitarias.xml"]
file-format: JUNITXML
cobertura:
files: ["informes/cobertura.xml"]
file-format: COBERTURAXML
artifacts:
files: [mercadofresco-tienda-*.zip]
discard-paths: yes
cache:
paths: ["/root/.cache/pip/**/*", ".ruff_cache/**/*"]Les fases, una a una
| Fase | Per a què serveix | Si falla | Durada |
|---|---|---|---|
install |
Temps d'execució i eines | Avorta; només s'executa finally |
20-90 s |
pre_build |
Credencials, variables, comprovacions ràpides | Avorta abans de gastar en proves | 30-60 s |
build |
Compilar, provar, empaquetar | Avorta, però post_build sí que s'executa |
2-4 min |
post_build |
Publicar, notificar, netejar | Marca la construcció com a fallida | 10-30 s |
Dos comportaments confonen tothom la primera vegada. post_build s'executa encara que build
falli, i és deliberat: vols publicar els informes de les proves precisament quan han fallat. Per
això el post_build de dalt comprova CODEBUILD_BUILD_SUCCEEDING; sense aquesta comprovació publicaries a
S3 l'artefacte d'una construcció les proves de la qual van fallar, l'error més perillós d'aquesta lliçó. I
l'ordre dins de pre_build no és casual: ruff triga 2 segons, l'escaneig de secrets 5,
bandit 15 i pip-audit 20, així que un error de format falla en 2 segons en lloc de en 40. Ordena
sempre les teves portes per cost creixent.
Variables d'entorn i secrets sense fuites als registres
Els registres van a CloudWatch Logs i els llegeix qualsevol amb permís sobre aquest grup. Qualsevol valor que
hi imprimeixis és visible, i un set -x o un echo de depuració poden imprimir un secret sense que ningú
se n'adoni.
| Tipus | On es desa | Emmascarat? | Per a què |
|---|---|---|---|
PLAINTEXT |
Definició del projecte | No | Configuració pública |
PARAMETER_STORE |
Parameter Store | Sí (si és SecureString) |
Configuració per entorn |
SECRETS_MANAGER |
Secrets Manager | Sí | Contrasenyes, claus d'API |
La sintaxi del bloc secrets-manager —NOM_VARIABLE: nom-secret:clau-json:etiqueta— és la que
més s'equivoca. Els dos punts separen el nom del secret de la clau concreta dins del JSON: sense
:clave_api, la variable rebria el JSON sencer —{"clave_api": "...", "url": "..."}— i el teu codi
fallaria amb un error confús. I si el secret té rotació de 04-03, AWSCURRENT garanteix que fas servir la
versió vigent.
Com emmascara CodeBuild. Substitueix per *** els valors resolts des de Parameter Store i Secrets
Manager. Però és una coincidència de cadenes, no màgia, i s'escapa en tres casos: si transformes el
valor (echo $CLAVE | base64), el que s'imprimeix ja no coincideix i surt en clar; si el secret acaba en un
fitxer que després imprimeixes amb cat; i si una eina l'inclou en un missatge d'error, com una
cadena de connexió completa a l'excepció d'un driver.
Tres regles pràctiques: mai set -x en un buildspec que manegi secrets; redirigeix a /dev/null
allò que pugui portar credencials quan no necessitis la sortida; i no posis secrets en variables
PLAINTEXT, ni «temporalment per provar», perquè queden a la definició del projecte i a CloudTrail.
Proves unitàries i informes de proves i cobertura
Les proves de MercadoFresco viuen a tests/ i proven el que importa. Un exemple real —la idempotència
del consumidor que vam construir a 07-05, que és exactament el tipus de propietat que ningú no verifica a mà:
# tests/unitarias/test_idempotencia.py
import pytest
from app.pedidos import processar_missatge_comanda
def test_mateix_missatge_dues_vegades_cobra_una_sola_vegada(taula_idempotencia, passarela_falsa):
"""L'escenari del modul 7: SQS lliura dues vegades la mateixa comanda."""
missatge = {"id_pedido": "PED-2026-00841", "importe_eur": 48.20,
"clave_idempotencia": "PED-2026-00841:cobro"}
primera = processar_missatge_comanda(missatge)
segona = processar_missatge_comanda(missatge) # el duplicat
assert primera["estado"] == "cobrado"
assert segona["desde_cache"] is True
assert passarela_falsa.nombre_de_cobraments == 1 # L'ASSERCIO que importa
assert passarela_falsa.total_cobrat == pytest.approx(48.20)
def test_franja_invalida_es_rebutja_sense_tocar_aurora(aurora_falsa):
with pytest.raises(ValueError, match="franja_entrega"):
processar_missatge_comanda({"id_pedido": "X", "franja_entrega": "noche"})
assert aurora_falsa.escriptures == 0 # rebuig ABANS d'escriureFixa't en què s'afirma. No es comprova «que la funció retorni alguna cosa»: es comprova que la passarel·la es va cridar exactament una vegada i que una dada invàlida no va arribar a escriure's a Aurora. Una prova que no pot fallar quan el comportament es trenca no és una prova, és decoració.
El bloc reports converteix l'XML de JUnit en alguna cosa que CodeBuild entén: a la consola veuràs per
construcció quantes proves van passar, quines van fallar amb la seva traça i la tendència històrica. Sense ell
hauries de buscar la fallada en 2.000 línies de registre.
Sobre --cov-fail-under=75. La cobertura mesura quines línies van executar les proves, no si ho van fer
bé: es pot tenir un 95 % sense una sola asserció útil. Tot i així serveix per detectar codi que ningú
no executa, i un llindar que falla la construcció impedeix que baixi sense que ningú se n'adoni. El criteri
de la Marta és assenyat: el llindar comença en el valor actual i només pot pujar, mai no es baixa per
«desbloquejar» una PR. Baixar-lo una vegada és baixar-lo per sempre.
Què fer quan una prova falla
És la secció més curta i important del mòdul, perquè d'ella depèn que tota la resta serveixi.
| Situació | Reacció correcta | Reacció que arruïna el sistema |
|---|---|---|
| Falla per una prova mal escrita | Arreglar la prova a la mateixa PR | Marcar-la @pytest.mark.skip |
| Falla de manera intermitent | Investigar avui: sol ser una cursa real | Reintentar fins que passi |
| Falla per un servei extern caigut | Simular-lo; la unitària no surt a la xarxa | Desactivar la prova |
| Falla i hi ha pressa per desplegar | Revertir el commit i desplegar l'anterior | Saltar-se la construcció |
Les proves intermitents són el perill més gran, més que les que fallen sempre. Una que falla sempre s'arregla; una que falla una de cada quinze vegades ensenya l'equip a prémer «reintentar», i a partir d'aquí una fallada real també es reintenta fins que passa. Solen assenyalar alguna cosa certa: dependència de l'ordre d'execució, una espera fixa en lloc d'una condició, o una condició de cursa que també existeix en producció. Tracta-la com una fallada de prioritat alta o esborra-la, però no la deixis parpellejant. I la regla que ho sosté tot: una construcció en vermell bloqueja la fusió; sense ella, l'equip aprèn en dues setmanes que el vermell és opcional. Aquesta porta es tanca del tot a 08-04.
Proves d'integració: simulació o clon d'Aurora
Les proves unitàries no toquen la xarxa. Les d'integració sí, i hi ha dues estratègies amb equilibris molt diferents:
| Estratègia | Fidelitat | Velocitat | Cost | Quan |
|---|---|---|---|---|
| Serveis simulats (moto, LocalStack) | Mitjana | Segons | 0 | La majoria de casos |
| Contenidor real (Postgres en Docker) | Alta per a SQL | 30-60 s | 0 | Consultes i esquema |
Clon aurora-mf-pruebas-luis |
Total | Minuts | ENI + NAT | Migracions i rendiment |
Amb moto, les crides a AWS s'intercepten en memòria:
# tests/integracion/test_flujo_pedido.py
import boto3, json
from moto import mock_aws
from app.pedidos import confirmar_comanda
@mock_aws
def test_comanda_confirmada_encua_i_publica_esdeveniment():
sqs = boto3.client("sqs", region_name="eu-west-1")
sns = boto3.client("sns", region_name="eu-west-1")
url_cua = sqs.create_queue(QueueName="cola-mercadofresco-pedidos")["QueueUrl"]
tema = sns.create_topic(Name="mercadofresco-pedido-confirmado")["TopicArn"]
resultat = confirmar_comanda(
{"id_cliente": "CLI-4471", "lineas": [{"sku": "FRUT-0012", "uds": 3}],
"franja_entrega": "tarde"}, url_cua=url_cua, tema_arn=tema)
missatges = sqs.receive_message(QueueUrl=url_cua, MaxNumberOfMessages=10)
cos = json.loads(missatges["Messages"][0]["Body"])
assert cos["id_pedido"] == resultat["id_pedido"]
assert cos["franja_entrega"] == "tarde"
assert cos["version_evento"] == "2" # veure 08-05Això verifica el flux complet —confirmar, encuar, publicar— en menys d'un segon i sense cost, i per al 90 % dels casos és suficient. El clon d'Aurora es reserva per al que la simulació no et pot dir: si una migració triga 4 segons o 40 minuts sobre 340 GB reals, si un índex nou es fa servir de debò, si una consulta es degrada amb el volum de producció. Això exigeix VPC, i la VPC té un cost.
Anàlisi estàtica, dependències i secrets filtrats
| Eina | Què busca | Bloquejant | Cost |
|---|---|---|---|
ruff |
Errors d'estil, imports sense fer servir, bugs evidents | Sí | 0 |
git-secrets |
Patrons de credencials al codi | Sí, sempre | 0 |
pip-audit |
CVE coneguts en dependències | Sí, amb matisos | 0 |
bandit |
Patrons de codi insegur | Informe | 0 |
| Amazon Inspector | Vulnerabilitats en imatges d'ECR i Lambda | Configurable | Per recurs |
git-secrets és la xarxa que faltava a 08-01. El .gitignore protegeix del descuit; això protegeix
també del git add -f:
- git secrets --register-aws # patrons d'AWS: AKIA, claus secretes
- git secrets --add 'sk_live_[0-9a-zA-Z]{24}' # claus de passarela de pagament
- git secrets --add 'postgres://[^:]+:[^@]+@' # cadenes de connexio amb contrasenya
- git secrets --add --allowed 'AKIAIOSFODNN7EXAMPLE' # el de la documentacio, permesQue sigui bloquejant no es discuteix: un fals positiu costa afegir una excepció --allowed; un fals
negatiu costa rotar credencials en producció.
pip-audit amb matisos. Falla si alguna dependència té un CVE conegut, cosa que és correcta però
té una manera de fallar que cal anticipar: es publica un CVE en una biblioteca popular un dimarts a la
tarda i totes les teves construccions es posen en vermell, inclosa la d'una correcció urgent que no té
res a veure. Evita la sortida fàcil de --ignore-vuln, que es converteix en una llista que només creix; el
correcte és fallar i avisar per alertas-mercadofresco amb l'identificador de la construcció, de
manera que existeixi un procediment i no una excepció permanent.
Amazon CodeGuru Reviewer mereix una menció: analitza el codi amb models entrenats sobre el mateix codi d'Amazon i detecta el que un linter no veu —fuites de recursos, condicions de cursa, ús incorrecte de les API d'AWS—. És de pagament i les seves recomanacions són suggeriments, no portes: per a tres persones és un luxe prescindible; per a cinquanta pot compensar.
Qualitat com a porta, no com a informe
Aquí hi ha el criteri que separa un pipeline útil d'un teatre de qualitat. Una comprovació és o una porta —falla la construcció i bloqueja la fusió— o un informe que ningú no llegirà. No hi ha punt intermedi: un informe que no bloqueja res s'ignora al tercer dia.
| Comprovació | Porta? | Per què |
|---|---|---|
| Proves unitàries | Sí | Una prova en vermell és un comportament trencat |
| Cobertura < 75 % | Sí | Impedeix que baixi sense que ningú se n'adoni |
| Secrets detectats | Sí | El cost del fals negatiu és rotar en producció |
ruff |
Sí | Ràpid i objectiu; discutir estil a les PR és temps perdut |
| CVE en dependències | Sí, amb avís | Amb procediment per al dimarts a la tarda |
bandit |
No, informe | Molts falsos positius; es revisa setmanalment |
| Complexitat ciclomàtica | No, informe | Llindar arbitrari; genera discussions estèrils |
La regla per decidir: si no estàs disposat a aturar un desplegament per això, no és una porta. I si no
ho és, sigues honest sobre el fet que gairebé ningú no ho llegirà: posa-li un moment explícit de revisió
—«els dilluns es mira l'informe de bandit»— o treu-ho del buildspec.
Artefactes: el paquet de l'aplicació i les imatges
El resultat de la construcció és un artefacte immutable i versionat, i aquest és el canvi conceptual
més important davant de l'scp del Luis: ja no es desplega «el que hi ha a la carpeta», es desplega
mercadofresco-tienda-1.5.0-a3f9c21.zip, un fitxer que existeix, té identificador, es pot descarregar
sis mesos després i és exactament el que es va provar.
El bucket mercadofresco-artefactos es crea amb tres propietats no negociables: versionat, que
CodePipeline exigeix i que protegeix d'una sobreescriptura accidental; xifratge amb
alias/mercadofresco-datos i BucketKeyEnabled per reduir les crides a KMS, que es facturen a part; i
una regla de cicle de vida que faci caducar els artefactes.
aws s3api put-bucket-versioning --bucket mercadofresco-artefactos \
--versioning-configuration Status=Enabled --profile mercadofresco-dev
aws s3api put-bucket-lifecycle-configuration --bucket mercadofresco-artefactos \
--lifecycle-configuration '{"Rules":[{
"ID":"caducar-artefactos-antiguos","Status":"Enabled",
"Filter":{"Prefix":"tienda/"},
"Expiration":{"Days":90},
"NoncurrentVersionExpiration":{"NoncurrentDays":30}}]}' \
--profile mercadofresco-devSense cicle de vida, vint artefactes diaris de 45 MB són 27 GB a l'any de ZIP que ningú no desplegarà mai; amb 90 dies en tens de sobres per tornar enrere i el cost es queda en cèntims.
Imatges de contenidor. Si en lloc d'un ZIP construeixes una imatge, necessites privilegedMode: true,
un docker login contra ECR a pre_build amb aws ecr get-login-password, un docker build etiquetant
amb ${VERSION_APP} i un docker push a post_build. Sobre això, només el just: ECR, les capes,
l'escaneig d'imatges i el desplegament en contenidors són el mòdul 10. Aquí n'hi ha prou de saber que
CodeBuild construeix imatges igual de bé que ZIP i que LOCAL_DOCKER_LAYER_CACHE reutilitza les capes.
Memòria cau de dependències i el seu efecte real
Instal·lar 87 paquets des de PyPI triga 45-70 segons a cada construcció: per 20 construccions diàries, 20 minuts al dia descarregant el mateix.
| Tipus de memòria cau | On viu | Estalvi mesurat | Limitació |
|---|---|---|---|
Local (LOCAL_CUSTOM_CACHE) |
Amfitrió de la construcció | 40-55 s | Només si cau al mateix amfitrió |
| S3 | Bucket que indiquis | 25-40 s | Es paga pujar i baixar |
| Capes de Docker | Amfitrió de la construcció | 1-3 min | Només amb privilegedMode |
Els números reals: sense memòria cau, 4 min 10 s; amb encert, 3 min 20 s; amb fallada, 4 min 12 s. L'estalvi és real però modest, i convé dir-ho perquè hi ha expectatives exagerades: la memòria cau local depèn que la construcció caigui en un amfitrió que la tingui, i amb 20 diàries l'encert ronda el 60 %.
Dos advertiments. Una memòria cau enverinada és pitjor que no tenir-ne: si deses site-packages en lloc
de la memòria cau de pip, arrossegues versions antigues i depurar-ho porta hores —desa sempre ~/.cache/pip—. I
si sospites de la memòria cau, invalida-la: aws codebuild invalidate-project-cache és la primera ordre a
provar quan una construcció falla de manera inexplicable.
Construccions en lots
Quan la bateria de proves creix, el bloc batch del buildspec defineix un graf de construccions: diverses
—pruebas_unitarias, pruebas_integracion, escaneos— corren alhora, i una etapa empaquetado
amb depend-on espera les tres; fast-fail: true cancel·la les altres així que una falla. Una
construcció seqüencial de 12 minuts pot baixar a 6, però el cost total en minuts no baixa —pagues
els mateixos, només que en paral·lel—; el que compres és temps d'espera del desenvolupador, que sol valer
molt més que 0,04 USD. Comença senzill: no paral·lelitzis una construcció de 4 minuts.
CodeBuild dins de la VPC, amb el seu avís de cost
Per defecte CodeBuild corre fora de la teva VPC, amb sortida a internet i sense accés a les teves subxarxes
privades: no pot parlar amb aurora-mf-pruebas-luis, que és a snet-mercadofresco-datos-a.
aws codebuild update-project --name build-mercadofresco-tienda \
--vpc-config '{"vpcId": "vpc-mercadofresco",
"subnets": ["snet-mercadofresco-app-a", "snet-mercadofresco-app-b"],
"securityGroupIds": ["sg-mercadofresco-construccion"]}' \
--profile mercadofresco-dev --region eu-west-1Tres coses que cal fer bé. Subxarxes privades, sempre: en una de pública sense IP pública la
construcció no tindrà sortida a internet i pip install es penjarà fins al temps d'espera, i és la fallada més comuna
i desconcertant. Sortida per NAT per arribar a PyPI, o VPC endpoints per a les API d'AWS. I un grup
de seguretat sg-mercadofresco-construccion amb una regla d'entrada a sg-mercadofresco-basedatos que
permeti el 5432 des d'ell: no obris mai la base de dades per CIDR.
Avís de cost important. Ficar CodeBuild a la VPC té dos costos que sorprenen a la factura. Les ENI: cada construcció crea i destrueix una interfície de xarxa, cosa que afegeix 30-60 segons d'arrencada a cada execució —amb 20 diàries, 20 minuts al dia facturats per no fer res—. I el NAT gateway: 0,048 USD/hora més 0,048 USD per GB; descarregar 300 MB de dependències 20 vegades al dia són uns 9 GB al mes només en trànsit. La recomanació pràctica és tenir dos projectes:
build-mercadofresco-tiendafora de la VPC per al 90 % de les construccions amb serveis simulats, ibuild-mercadofresco-integraciondins, només a les PR cap amaino de manera nocturna. I VPC endpoints de tipus Gateway per a S3 i DynamoDB, gratuïts, que eviten que aquest trànsit passi pel NAT.
Depurar una construcció que falla
1. Els registres de CloudWatch, a /aws/codebuild/build-mercadofresco-tienda. Per anar al gra sense
llegir 2.000 línies, aws codebuild batch-get-builds --ids <id> amb
--query 'builds[0].phases[?phaseStatus==FAILED].[phaseType,contexts[0].message]' et dóna la fase que
va fallar i el seu missatge.
2. Reproducció local amb la imatge oficial. La manera més ràpida d'iterar, i no costa res:
./codebuild_build.sh -i public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:5.0 \
-a /tmp/salida -s ~/proyectos/tienda -b buildspec.ymlL'script és al repositori aws/aws-codebuild-docker-images i executa el mateix buildspec en la
mateixa imatge, a la teva màquina: si falla igual, tens un bucle de depuració de segons en lloc de minuts.
Compte: els secrets no es resolen en local tret que li passis credencials, així que exporta valors de
prova.
3. La sessió de depuració interactiva. Quan la fallada només passa a CodeBuild —i passa—, posa
codebuild-breakpoint com a ordre just abans de la que falla: la construcció s'atura allà i espera.
Llança-la amb --debug-session-enabled i connecta amb Session Manager des de la consola. Et trobes dins
del contenidor, al punt exacte, amb el codi clonat i les variables resoltes; codebuild-resume
continua. Requereix permisos d'SSM al rol de servei, i la construcció continua facturant mentre
esperes: no deixis una sessió oberta a l'hora de dinar.
4. Les variables que CodeBuild et dóna, que solen resoldre el dubte abans que res:
CODEBUILD_RESOLVED_SOURCE_VERSION (el SHA exacte construït), CODEBUILD_WEBHOOK_TRIGGER (què ho va
disparar: branch/main, pr/42, tag/v1.5.0), CODEBUILD_BUILD_SUCCEEDING (imprescindible a
post_build), CODEBUILD_BUILD_ID i CODEBUILD_SRC_DIR.
Mètriques, alarmes i cost real
CodeBuild publica mètriques a AWS/CodeBuild. Les tres que importen són FailedBuilds (alarma: ≥ 3 en
1 hora, o 1 de sola si és main), Duration (p90 > 8 min) i SucceededBuilds per a la taxa d'èxit.
aws cloudwatch put-metric-alarm --alarm-name mercadofresco-construcciones-fallidas \
--namespace AWS/CodeBuild --metric-name FailedBuilds --statistic Sum \
--dimensions Name=ProjectName,Value=build-mercadofresco-tienda \
--period 3600 --evaluation-periods 1 --threshold 3 \
--comparison-operator GreaterThanOrEqualToThreshold --treat-missing-data notBreaching \
--alarm-actions arn:aws:sns:eu-west-1:111122223333:alertas-mercadofresco \
--profile mercadofresco-dev --region eu-west-1--treat-missing-data notBreaching és important: sense construccions no hi ha dades, i no voldràs una alarma
sonant cada nit. És la mateixa lliçó de 05-01.
Cost real de MercadoFresco al mes:
| Concepte | Càlcul | Cost |
|---|---|---|
| Construccions de PR i branques | 20/dia × 4,2 min × 22 dies × 0,010 | 18,48 USD |
| Integració nocturna (a la VPC) + trànsit NAT | 1/dia × 9 min × 30 × 0,010 + 9 GB | 3,13 USD |
| Artefactes a S3 amb caducitat de 90 dies | ~4 GB | 0,09 USD |
| Registres de CloudWatch | ~2 GB ingerits | 1,15 USD |
| Total | ≈ 22,85 USD/mes |
Vint-i-tres dòlars al mes per eliminar «funciona al meu portàtil» del vocabulari de l'equip. Compara-ho amb un desplegament trencat un divendres a les 19:00 amb 900 comandes/hora en joc.
Neteja: delete-project, delete-report-group --delete-reports i delete-log-group. Els grups de
registre no s'esborren en esborrar el projecte i continuen facturant emmagatzematge; posa'ls retenció amb
aws logs put-retention-policy --retention-in-days 30 des del primer dia.
Errors Habituals i Consells
Publicar l'artefacte sense comprovar CODEBUILD_BUILD_SUCCEEDING. post_build s'executa encara que
build falli, així que puges a S3 el paquet d'una construcció les proves de la qual van fallar. És l'error
més perillós de la lliçó.
Posar secrets en variables PLAINTEXT, que queden a la definició del projecte i a CloudTrail; o
oblidar :clau a la referència a Secrets Manager, amb què la variable rep el JSON sencer i
l'aplicació falla amb un error que no apunta a la causa. I fer servir set -x amb secrets: l'emmascarament
és coincidència de cadenes i així que transformes el valor surt en clar.
CodeBuild en una subxarxa pública. Sense IP pública no hi ha sortida a internet i pip install es penja
fins al temps d'espera. Subxarxes privades amb NAT, sempre. I no fiquis totes les construccions a la VPC
«per si de cas»: pagues 30-60 s d'ENI a cadascuna més el trànsit del NAT.
Baixar el llindar de cobertura per desbloquejar una PR. Es baixa una vegada i ja no torna a pujar. I reintentar una prova intermitent fins que passi ensenya l'equip que el vermell no significa res, així que el dia que sigui real també es reintentarà.
Desar site-packages a la memòria cau en lloc de ~/.cache/pip. Arrossegues versions antigues i depurar-ho porta hores.
I no posar retenció als grups de registre: facturen per sempre, fins i tot després d'esborrar el projecte.
Consell: ordena les portes de més ràpida a més lenta. Una fallada de format ha de fallar en 2 segons, no després de 4 minuts de proves.
Consell: fes que el buildspec sigui executable en local amb codebuild_build.sh i la imatge oficial; si només
funciona dins de CodeBuild, cada iteració de depuració costa minuts. Exporta la versió amb
exported-variables perquè CodePipeline (08-04) la faci servir a les etapes següents, i posa un
timeout-in-minutes ajustat: és el fre que evita pagar 60 minuts per una construcció penjada.
Exercicis
Exercici 1: l'artefacte que no hauria d'existir
El divendres a les 18:40, el Luis veu a mercadofresco-artefactos el fitxer
tienda/1.5.2-c7a91f3/mercadofresco-tienda-1.5.2-c7a91f3.zip, publicat a les 18:32. Però a CodeBuild la
construcció c7a91f3 apareix en vermell: van fallar 3 proves de tests/unitarias/test_pagos.py.
Respon: (a) com és possible que existeixi l'artefacte si la construcció va fallar; (b) què ho ha permès i com es corregeix; (c) per què és perillós més enllà d'aquest cas, tenint en compte el que farà CodePipeline a 08-04; (d) quina comprovació posaries perquè un artefacte així no es pugui desplegar; (e) quina alarma hauria avisat la Marta a les 18:35.
Exercici 2: la construcció de 22 minuts
La construcció triga 22 minuts: install 4 min (140 paquets i psycopg2 compilat des de les fonts),
pre_build 3 min (pip-audit, bandit, ruff i git-secrets en sèrie), build 14 min (620 proves
unitàries en sèrie, 40 d'integració contra el clon d'Aurora i l'empaquetatge), post_build 1 min. El
projecte és a la VPC, en SMALL, sense memòria cau. El Luis ha començat a saltar-se la construcció local.
Proposa un pla que baixi el temps per sota dels 6 minuts. Per a cada mesura indica l'estalvi estimat, l'efecte en el cost i què es perd. Digues explícitament quina aplicaries primer i per què.
Exercici 3: el secret que va sortir als registres
La Sara, revisant els registres d'una construcció, troba aquesta línia a
/aws/codebuild/build-mercadofresco-tienda:
El secret està declarat correctament a env.secrets-manager i CodeBuild l'emmascara a la sortida
directa. A pre_build hi ha aquestes dues línies:
- export CADENA_CONEXION="postgresql://mfadmin:${PASS_AURORA}@${HOST_AURORA_PRUEBAS}:5432/mf"
- echo "Connectant a ${CADENA_CONEXION}"Respon: (a) per què no ha funcionat l'emmascarament; (b) què fas els primers 30 minuts,
en ordre; (c) com corregeixes el buildspec; (d) els registres fa 6 mesos que tenen retenció
indefinida i aquesta línia apareix en 340 construccions: com ho abordes; (e) quin control automàtic
afegiries per detectar-ho la propera vegada.
Solucions
Solució 1
(a) Perquè post_build s'executa encara que build falli. És deliberat —permet publicar informes
de proves fallides— però significa que les ordres de publicació que hi posis s'executen igualment:
les proves van fallar a build, la fase va avortar, i post_build va pujar el ZIP tan tranquil.
(b) Falta la guarda de CODEBUILD_BUILD_SUCCEEDING: el buildspec culpable té un aws s3 cp sense
condició a post_build. La correcció és la que sí que apareix al buildspec de la lliçó:
post_build:
commands:
- |
if [ "${CODEBUILD_BUILD_SUCCEEDING}" != "1" ]; then
echo "Construccio fallida: no es publica artefacte"; exit 1
fi
- aws s3 cp mercadofresco-tienda-*.zip s3://${BUCKET_ARTEFACTOS}/tienda/${VERSION_APP}/(c) Perquè trenca la garantia de la qual depèn tota la resta: que un artefacte publicat és un artefacte que va passar les proves. A 08-04 el pipeline prendrà l'artefacte d'una etapa i el passarà a la següent; si a més algú desplega per nom de fitxer des de S3, es desplegaria codi amb tres proves de pagaments trencades. I seria silenciós: el ZIP existeix, té bon aspecte i el seu nom no diu res de la seva procedència. La confiança en el sistema es perd sencera amb un sol cas així.
(d) Dues capes barates. Metadades a l'objecte —--metadata estado=exitosa,commit=...— i una
comprovació al desplegament que rebutgi el que no les tingui. I, més robust, separar
responsabilitats: que la construcció no publiqui res i sigui el mecanisme natiu (artifacts:) el que
lliuri el paquet a CodePipeline, que només avança si l'etapa anterior va acabar bé. La regla general:
si la publicació és un efecte secundari d'un script, algun dia s'executarà quan no tocava; si és
una transició d'estat del pipeline, no pot passar fora d'ordre.
(e) L'alarma mercadofresco-construcciones-fallidas sobre FailedBuilds, amb llindar baix —1 en 5
minuts per a main— i destinació alertas-mercadofresco: el llindar de 3 en 1 hora serveix per detectar una
tendència, però a main una sola fallada mereix avís immediat. Complementàriament, una regla
d'EventBridge sobre CodeBuild Build State Change amb build-status: FAILED avisa en segons amb l'enllaç
directe als registres.
Solució 2
| # | Mesura | Estalvi | Cost | Què es perd |
|---|---|---|---|---|
| 1 | Treure el projecte de la VPC; build-mercadofresco-integracion a part, nocturn |
~7 min | Baixa: menys NAT i ENI | Retroalimentació immediata contra Aurora real |
| 2 | pytest -n auto amb MEDIUM |
~7 min | Puja el preu/min, baixa el total | Res, si les proves estan aïllades |
| 3 | Memòria cau de pip + psycopg2-binary en lloc de compilar |
~3 min | Cap | La roda precompilada, acceptable |
| 4 | Escanejos alhora | ~2 min | Igual en minuts totals | Registres més difícils de llegir |
| 5 | gitCloneDepth: 1 |
~30 s | Cap | git describe per a la versió |
| 6 | pytest-split en 3 construccions en lots |
~2 min | Els mateixos minuts, en paral·lel | Complexitat de configuració |
Primer, la mesura 1, i la justificació és la clau de l'exercici: és la que més temps estalvia i
l'única que a més redueix el cost. Les 40 proves contra el clon d'Aurora aporten valor, però no a cada
push: l'aporten abans de fusionar cap a main i a l'execució nocturna. Amb el 90 % de les
construccions fora de la VPC desapareixen els 30-60 s d'ENI, el trànsit del NAT i bona part de la
lentitud de xarxa. És també la de menys risc: no canvia ni una prova.
Segon, la mesura 2, contraintuïtiva i molt rendible: passar de SMALL a MEDIUM duplica el preu
per minut però redueix el total, perquè 620 proves amb -n auto sobre 4 vCPU gairebé divideixen per quatre el
temps de la bateria. El requisit és que estiguin aïllades: si comparteixen una SQLite o un directori temporal
fix, la paral·lelització les farà fallar de manera intermitent —justament el problema del qual parlàvem—, i
llavors l'arranjament és aïllar-les, no tornar a la sèrie.
Resultat: install 4 → 1 min, pre_build 3 → 1, build 14 → 3, post_build 1. Uns 6 minuts,
amb cost per construcció gairebé igual i menys factura de NAT. I la conseqüència que no és a la taula i
és la més important: amb 6 minuts, el Luis deixa de saltar-se la construcció.
Solució 3
(a) Perquè l'emmascarament és una substitució literal de la cadena del secret a la sortida, no una
anàlisi semàntica. El buildspec interpola ${PASS_AURORA} dins d'una cadena més gran; el resultat és
un valor nou que CodeBuild no coneix, així que en fer echo no troba cap coincidència que
emmascarar i l'imprimeix sencer. És el primer dels tres casos: transformar el valor trenca
l'emmascarament.
(b) Els primers 30 minuts, en ordre. Rotar la contrasenya de mfadmin de proves, perquè sempre
es comença per tallar la validesa del que s'ha filtrat. Determinar qui l'ha pogut llegir, amb CloudTrail
buscant GetLogEvents i FilterLogEvents sobre aquest grup en els últims 6 mesos; l'abast depèn de
quanta gent tingui lectura sobre CloudWatch Logs, que sol ser més de la que un es pensa. Comprovar si
afecta producció —i aquí es veu el valor de la separació de prefixos del rol: CodeBuild no pot
llegir mercadofresco/produccion/rds/mfadmin, així que l'incident queda acotat a proves—. I corregir el
buildspec abans de la següent construcció, o el registre se seguirà escrivint.
(c) No imprimir mai la cadena completa: si necessites traçar, traça només el que no és sensible
(echo "Connectant a ${HOST_AURORA_PRUEBAS}:5432/mf com a mfadmin"). La millora de fons és una altra: si
l'aplicació llegeix el secret de Secrets Manager amb el seu propi rol, el valor no passa mai per una
variable d'entorn del shell i desapareix tota aquesta classe de fuites. La variable d'entorn és còmoda,
però és també la superfície per on s'escapen els secrets.
(d) Tracta els registres històrics com a dades compromeses: exporta el grup a S3 si cal conservar-lo per auditoria, esborra els fluxos afectats —no hi ha edició parcial a CloudWatch Logs— i posa retenció de 30 dies. Com que la contrasenya ja està rotada a (b), l'exposició residual no dóna accés a res: esborrar-los és higiene i compliment, no contenció. Si el secret hagués estat de producció, a més caldria valorar la notificació interna que vam veure a 08-01.
(e) Un filtre de mètrica de CloudWatch Logs sobre /aws/codebuild/* que compti coincidències de
patrons com postgresql://*:*@, AKIA o sk_live_, amb alarma cap a alertas-mercadofresco. És millor
que una comprovació dins del buildspec perquè funciona encara que ningú no se'n recordi de mantenir-la i
cobreix tots els projectes, presents i futurs. És la idea de 05-01: si una dada no hauria d'aparèixer mai
en un registre, posa una mètrica que la compti i alarma així que passi de zero.
Conclusió
«Funciona al meu portàtil» ja no significa res a MercadoFresco. Cada push arrenca un contenidor net que
no sap res del psycopg2 que el Luis va instal·lar a mà el 2024: instal·la les dependències declarades, executa
214 proves, comprova que la cobertura no baixa del 75 %, escaneja les 87 dependències buscant CVE,
busca credencials filtrades i produeix un artefacte versionat i immutable a
mercadofresco-artefactos. El que es desplegui serà aquest ZIP, amb el seu commit i les seves metadades.
Coneixes l'anatomia d'un projecte —origen, entorn, rol de servei, buildspec, artefactes, memòria cau i
registres— i saps que la mida de còmput cal mesurar-la i no suposar-la, perquè MEDIUM pot sortir
més barat que SMALL quan la construcció sap fer servir els quatre nuclis. Saps que el rol de servei
l'executa codi que canvia a cada commit, i que per això el seu abast es limita al prefix
mercadofresco/pruebas/: una construcció no necessita mai credencials de producció. Domines el
buildspec.yml, l'ordre de les fases i les dues trampes que enxampen tothom: que post_build
s'executa encara que build falli —d'aquí la guarda de CODEBUILD_BUILD_SUCCEEDING, sense la qual
publiques artefactes de construccions trencades— i que les portes s'ordenen de més ràpida a més lenta.
Saps injectar secrets amb la sintaxi secret:clau:etiqueta i —més important— per què
l'emmascarament es trenca així que transformes el valor o l'interpoles en una cadena més gran. Tens
proves que verifiquen el que de debò importa, com que la passarel·la es va cridar exactament una vegada
davant d'un missatge duplicat, i els reports que converteixen un XML de JUnit en un històric
consultable. I tens la disciplina que sosté tot això: una prova intermitent s'investiga o s'esborra, mai
no es reintenta; el llindar de cobertura només puja; i una comprovació que no estàs disposat que aturi
un desplegament no és una porta, és decoració.
Saps quan n'hi ha prou amb moto —el 90 % dels casos, en un segon i sense cost— i quan cal el clon
aurora-mf-pruebas-luis, amb l'advertiment que comporta: CodeBuild a la VPC costa 30-60 segons d'ENI
per construcció i el trànsit del NAT, i per això MercadoFresco té dos projectes, un de ràpid a fora i
un d'integració a dins. I saps depurar sense endevinar: els registres, la reproducció local amb la imatge
oficial i codebuild-breakpoint per entrar al contenidor al punt exacte. Tot per uns 23 dòlars
al mes.
Però hi ha una cosa que aquesta lliçó no ha canviat. L'artefacte és allà, verificat, esperant en un
bucket. I per portar-lo a les instàncies de l'ASG asg-mercadofresco-tienda, el Luis continua fent el mateix
que el primer dia: entrar per SSH, copiar el ZIP, descomprimir-lo, reiniciar el servei i mirar el web amb
els dits creuats. Durant els quaranta segons que triga, la instància serveix errors; si n'hi ha dues i les
fa en sèrie, la meitat del trànsit veu una versió i l'altra meitat una altra; i si el ZIP resulta estar trencat, la
tornada enrere consisteix a buscar l'anterior i repetir el ritual amb la botiga caiguda. L'artefacte és bo;
la manera de posar-lo en producció continua sent un ritual manual sense xarxa de seguretat.
A 08-03, «AWS CodeDeploy», això es resol. Veurem les tres destinacions —EC2, Lambda i ECS— i quines
estratègies admet cadascuna; els conceptes d'aplicació, grup de desplegament, revisió i configuració de
desplegament, amb l'agent instal·lat a les instàncies de l'ASG; l'appspec.yml i els seus ganxos del cicle
de vida un a un, amb els scripts reals de MercadoFresco per aturar el servei, escalfar la memòria cau i
comprovar /salud; les estratègies al lloc amb AllAtOnce, HalfAtATime i OneAtATime, el
blue/green amb els grups de destinació de l'ALB, i el canari i lineal per desplegar la Lambda
mercadofresco-cobrar-pago; l'advertiment sobre migracions d'esquema i per què mai no han d'anar al
mateix pas que el codi; i sobretot la peça que tanca el quart problema del curs: la reversió
automàtica quan salta mercadofresco-alb-latencia-alta o falla un ganxo, sense que ningú estigui mirant.
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
