Dotika MLOps · Bloc 8 — L'assemblageBlock 8 — The assembly
▶ Slides▶ Slides ← Sommaire← Contents
Bloc 8 · 3 h · théorie 0h30 · lab 2h30Block 8 · 3 h · theory 0h30 · lab 2h30

Le système
vivant
The living
system

Toutes les briques existent. Aujourd'hui, on les fait respirer ensemble : commit → CI → registry → canary → monitoring — et chaque binôme le prouve en direct. Every brick exists. Today we make them breathe together: commit → CI → registry → canary → monitoring — and every pair proves it live.

Où on en estWhere we stand

Sept briques, construites de vos mainsSeven bricks, built with your own hands

Le modèle, l'API, le conteneur, la mémoire, la qualité, le cluster, la vigie : tout a été construit et testé cette semaine. Mais chaque brique a été testée seule — et une collection de briques n'est pas un système. The model, the API, the container, the memory, the quality gate, the cluster, the watchtower: everything was built and tested this week. But every brick was tested alone — and a collection of bricks is not a system.

Aujourd'huiToday

Tout respire ensembleEverything breathes together

Regardez la carte : le flux entre, le cerveau score, l'API répond, le cluster encaisse, la vigie surveille. Un commit suffit à changer la prod — sans qu'aucune main ne touche un serveur. C'est ça, un système assemblé. Look at the map: the stream flows in, the brain scores, the API answers, the cluster absorbs, the watchtower guards. One commit is enough to change prod — without any hand touching a server. That is an assembled system.

Et la preuveAnd the proof

À midi, vous le démontrez en directBy noon, you demonstrate it live

Pas un slide, pas une capture : un vrai commit poussé devant tout le monde, qui traverse toute la chaîne jusqu'au dashboard. Savoir l'expliquer, c'est l'avoir compris — Feynman jusqu'au bout. Not a slide, not a screenshot: a real commit pushed in front of everyone, travelling the whole chain down to the dashboard. If you can explain it, you have understood it — Feynman all the way.

Acte 1 · boucler la boucleAct 1 · closing the loop

La checklist d'assemblage, six jointuresThe assembly checklist, six joints

La transaction de Mme Martin — 03 h 47, Tallinn, 900 € — traverse désormais tout votre système en 300 ms : API → modèle du registry → verdict → feedback analyste → drift surveillé. L'assemblage, c'est vérifier chaque jointure, dans l'ordre : Mrs Martin's transaction — 3:47 a.m., Tallinn, €900 — now crosses your whole system in 300 ms: API → registry model → verdict → analyst feedback → drift watched. Assembly means checking every joint, in order:

JOINTURE 1JOINT 1
Le commit déclenche la CIThe commit triggers the CI
git push, et le pipeline s'allume tout seul — sans clic, sans « lance-le pour moi ».git push, and the pipeline lights up on its own — no click, no “run it for me”.
JOINTURE 2JOINT 2
La CI pousse l'imageThe CI pushes the image
Tests verts → image buildée, taguée avec le commit, envoyée au registry d'images.Green tests → image built, tagged with the commit, shipped to the image registry.
JOINTURE 3JOINT 3
Le cluster déploie en canaryThe cluster deploys as canary
La nouvelle version reçoit d'abord une fraction du trafic — le reste ne bouge pas.The new version first receives a fraction of the traffic — the rest doesn't move.
JOINTURE 4JOINT 4
L'API sert la version Production du registryThe API serves the registry's Production version
Le modèle vient de MLflow, pas d'un .pkl copié à la main. /health annonce sa version.The model comes from MLflow, not a hand-copied .pkl. /health announces its version.
JOINTURE 5JOINT 5
Le monitoring voit toutMonitoring sees everything
Latence, volume, taux d'alerte : le dashboard bouge quand le trafic bouge.Latency, volume, alert rate: the dashboard moves when the traffic moves.
JOINTURE 6JOINT 6
L'alerte drift pointe vers le réentraînementThe drift alert points to retraining
Quand la vigie crie, on sait quoi faire et où : la boucle est bouclée.When the watchtower shouts, we know what to do and where: the loop is closed.
Les 5 pannes classiquesThe 5 classic failures

1 · L'image sert le vieux modèle (vérifiez /health). 2 · CI verte, cluster inchangé (le manifest pointe l'ancien tag — kubectl describe). 3 · Ça tombe en prod (env/secret manquant — kubectl logs). 4 · Canary à 0 % ou 100 % (labels/selectors — kubectl get endpoints). 5 · Dashboard plat (mauvais port scrapé — ouvrez /metrics à la main). Le réflexe : suivre la transaction, remonter la chaîne maillon par maillon. 1 · The image serves the old model (check /health). 2 · Green CI, unchanged cluster (the manifest points to the old tag — kubectl describe). 3 · It crashes in prod (missing env/secret — kubectl logs). 4 · Canary at 0% or 100% (labels/selectors — kubectl get endpoints). 5 · Flat dashboard (wrong port scraped — open /metrics by hand). The reflex: follow the transaction, walk the chain back link by link.

Acte 2 · prouvez-leAct 2 · prove it

Savoir l'expliquer, c'est l'avoir comprisIf you can explain it, you have understood it

Le format : une démo de 5 minutes par binôme — un commit en direct qui traverse la chaîne, puis le dashboard. Une démo qui marche prouve que le système tient ; une explication claire prouve que vous tenez le système. The format: a 5-minute demo per pair — a live commit travelling the chain, then the dashboard. A working demo proves the system holds; a clear explanation proves you hold the system.

min 0–1
Le commit — une modification réelle, poussée en direct devant tout le mondeThe commit — a real change, pushed live in front of everyone
min 1–3
La chaîne — la CI passe, l'image part, le canary monte : vous commentez, brique par briqueThe chain — the CI passes, the image ships, the canary rises: you narrate, brick by brick
min 3–4
La preuve — /predict répond avec la nouvelle version, le registry confirmeThe proof — /predict answers with the new version, the registry confirms
min 4–5
Le dashboard — latence, prédictions, drift : le système vit sous les yeux du publicThe dashboard — latency, predictions, drift: the system lives before the audience's eyes
ReproductibilitéReproducibility
Je clone, je lance : ça tourne ? Un README honnête, un docker compose up qui suffit — le test ultime, appliqué par un inconnu.I clone, I run: does it work? An honest README, a docker compose up that is enough — the ultimate test, applied by a stranger.
TestsTests
Que protège vraiment la CI ? Les tests couvrent-ils l'API et le contrat du modèle ? Un test cassé bloque-t-il le merge ?What does the CI actually protect? Do the tests cover the API and the model's contract? Does a broken test block the merge?
ClartéClarity
Le code se lit-il sans guide ? Des noms qui disent ce qu'ils font, une structure src/ prévisible, pas de code zombie.Does the code read without a guide? Names that say what they do, a predictable src/ structure, no zombie code.
GouvernanceGovernance
Qui a promu le modèle, et où est la trace ? Le passage en Production doit être visible dans MLflow — humain, daté, justifié.Who promoted the model, and where is the trace? The move to Production must be visible in MLflow — human, dated, justified.
Les règles de la revue croiséeThe cross-review rules

On relit le code, jamais le codeur. Chaque revue donne 2 points forts précis et 1 amélioration concrète, déposés en issue sur le dépôt relu. En entreprise, c'est le rituel qui fait progresser le plus vite. We review the code, never the coder. Each review gives 2 precise strengths and 1 concrete improvement, filed as an issue on the reviewed repo. In industry, it is the ritual that makes you progress the fastest.

Acte 3 · et après ? · théorie 0h30Act 3 · what's next? · theory 0h30

Lundi : un notebook. Vendredi : un système en prodMonday: a notebook. Friday: a system in prod

Les six objectifs du bloc 1 sont cochés — reproductibilité, serving, tracking, CI/CD, déploiement à l'échelle, monitoring. Vous avez fait en une semaine le saut du niveau 0 (tout à la main) au niveau 1 (pipeline automatisé). La suite : Block 1's six goals are checked — reproducibility, serving, tracking, CI/CD, deployment at scale, monitoring. In one week you jumped from level 0 (all by hand) to level 1 (automated pipeline). What comes next:

PERSPECTIVE 1PERSPECTIVE 1
Continuous training — le niveau 2Continuous training — level 2
Le monitoring déclenche le réentraînement automatique : données fraîches, challenger vs champion, promotion si meilleur. Vous avez déjà toutes les pièces.Monitoring triggers automatic retraining: fresh data, challenger vs champion, promotion if better. You already own every piece.
PERSPECTIVE 2PERSPECTIVE 2
Plateformes managéesManaged platforms
SageMaker, Vertex AI, Databricks : les mêmes concepts — registry, pipelines, endpoints, monitoring — gérés pour vous. Vous savez ce qu'il y a sous le capot.SageMaker, Vertex AI, Databricks: the same concepts — registry, pipelines, endpoints, monitoring — managed for you. You know what's under the hood.
PERSPECTIVE 3PERSPECTIVE 3
LLMOps
Les mêmes douleurs avec des modèles géants : versioning de prompts, evals à la place de la PR-AUC, coûts comptés en tokens. Vous connaissez déjà les remèdes.The same pains with giant models: prompt versioning, evals instead of PR-AUC, costs counted in tokens. You already know the cures.
ET ENSUITEAND THEN
Où pratiquerWhere to practise
Refaire le pipeline sur un autre dataset (churn, spam), contribuer à MLflow ou FastAPI, viser une certification cloud ML. Un système par trimestre.Rebuild the pipeline on another dataset (churn, spam), contribute to MLflow or FastAPI, aim for a cloud ML certification. One system per quarter.
À retenir — pour toujoursTakeaway — for good

Tout versionner · automatiser la preuve · déployer progressivement · surveiller après le déploiement · rester simple. Cinq réflexes, une semaine pour les forger, une carrière pour les appliquer. Version everything · automate the proof · deploy progressively · watch after the deployment · stay simple. Five reflexes, one week to forge them, a career to apply them.

La mission du blocThe block's mission

« Démontrer, en direct, un pipeline complet : commit → CI → registry → canary → monitoring — et savoir l'expliquer. » "Demonstrate, live, a complete pipeline: commit → CI → registry → canary → monitoring — and be able to explain it."

Le modèle est en production. Il est surveillé. Il vit. — AI Driven. Human Approved. The model is in production. It is watched. It lives. — AI Driven. Human Approved.

Lab · 2h30 + clôture 0h30Lab · 2h30 + wrap-up 0h30

À vous de jouerYour turn

Deux missions en binômes, puis la clôture. Les durées viennent du plan de cours : Two missions in pairs, then the wrap-up. Durations come straight from the course plan:

1h40
Assembler — le pipeline complet end-to-end, guidé par la checklist des six jointures ; chaque case cochée = une preuve, commitée dans docs/assemblage.mdAssemble — the complete end-to-end pipeline, guided by the six-joint checklist; every checked box = one proof, committed to docs/assemblage.md
pratiquehands-on
1h00
Présenter & relire — démo de 5 minutes par binôme, puis revue croisée avec la grille : 2 points forts, 1 amélioration, en issue sur le dépôt reluPresent & review — 5-minute demo per pair, then cross review with the grid: 2 strengths, 1 improvement, filed as an issue on the reviewed repo
pratiquehands-on
0h30
Clôture & perspectives — le chemin parcouru, continuous training, plateformes managées, LLMOps — et où pratiquer ensuiteWrap-up & perspectives — the road travelled, continuous training, managed platforms, LLMOps — and where to practise next
théorietheory
Definition of done

Un pipeline démontré en direct, une checklist prouvée, une revue donnée et une revue reçue. Rien de déclaratif — que des preuves. C'est la definition of done de la semaine entière. A pipeline demonstrated live, a proven checklist, a review given and a review received. Nothing declarative — only proof. This is the definition of done for the whole week.

Pas à pas · en autonomieStep by step · self-paced

Faites-le vous-même, de A à ZDo it yourself, start to finish

Ce guide déroule l'assemblage final en solitaire : chaque jointure de la checklist devient une commande de vérification et son point de contrôle. Prérequis : les blocs 4 à 7 terminés — la CI du bloc 6 qui pousse sur ghcr.io, le MLflow du bloc 5 en marche (alias @production), et le cluster kind du bloc 7 encore debout (kind get clusters doit lister mlops). Partout dans les commandes, remplacez your-github-user par votre identifiant GitHub. This guide walks the final assembly solo: every joint of the checklist becomes one verification command and its checkpoint. Prerequisites: blocks 4 to 7 finished — block 6's CI pushing to ghcr.io, block 5's MLflow running (@production alias), and block 7's kind cluster still up (kind get clusters must list mlops). Everywhere in the commands, replace your-github-user with your GitHub username.

Mission 1 — Assembler, jointure par jointure (1h40)Mission 1 — Assemble, joint by joint (1h40)

1Jointure 1 — le commit déclenche la CIJoint 1 — the commit triggers the CI

Un commit vide suffit pour prouver la jointure : le pipeline doit s'allumer tout seul. Si gh n'est pas installé, ouvrez l'onglet Actions du dépôt dans le navigateur. An empty commit is enough to prove the joint: the pipeline must light up on its own. If gh is not installed, open the repo's Actions tab in the browser.

cd fraud-detection
git checkout main
git pull
git commit --allow-empty -m "chore: end-to-end assembly check"
git push origin main
gh run watch
Vous devriez voir : le run se terminer avec le statut « success » — chaque job vert, sans clic de votre part.You should see: the run finish with status "success" — every job green, without a single click from you.
2Jointure 2 — l'image est sur GHCR, taguée du commitJoint 2 — the image is on GHCR, tagged with the commit

Le tag est le commit : traçable jusqu'à la ligne de code. Si le pull répond « denied », faites docker login ghcr.io avec un token portant le scope read:packages. The tag is the commit: traceable to the line of code. If the pull answers "denied", run docker login ghcr.io with a token carrying the read:packages scope.

TAG=$(git rev-parse --short HEAD)
echo "$TAG"
docker pull ghcr.io/your-github-user/fraud-api:$TAG
docker images ghcr.io/your-github-user/fraud-api
Vous devriez voir : l'image listée avec le tag exact du commit que vous venez de pousser.You should see: the image listed with the exact tag of the commit you just pushed.
3Jointure 3 — le cluster déploie la nouvelle image en canaryJoint 3 — the cluster deploys the new image as a canary

La CI construit, mais c'est vous qui chargez dans kind — le cluster ne lit pas votre Docker local. Puis le canary du bloc 7 reçoit le tag du commit. The CI builds, but you do the loading into kind — the cluster does not read your local Docker. Then block 7's canary receives the commit's tag.

kind load docker-image ghcr.io/your-github-user/fraud-api:$TAG --name mlops
kubectl apply -f k8s/deployment-canary.yaml
kubectl set image deployment/fraud-api-canary fraud-api=ghcr.io/your-github-user/fraud-api:$TAG
kubectl rollout status deployment/fraud-api-canary
kubectl get pods -l track=canary
Vous devriez voir : le pod canary Running 1/1 — et kubectl get deployment fraud-api-canary -o wide affiche l'image au tag du commit.You should see: the canary pod Running 1/1 — and kubectl get deployment fraud-api-canary -o wide shows the image at the commit's tag.
4Jointure 4 — l'API sert models:/fraud-detector@productionJoint 4 — the API serves models:/fraud-detector@production

Le modèle vient du registry MLflow, pas d'un .pkl copié à la main. On compare ce que dit l'API à ce que dit le registry — les deux doivent raconter la même histoire. The model comes from the MLflow registry, not a hand-copied .pkl. Compare what the API says with what the registry says — both must tell the same story.

kubectl port-forward service/fraud-api 8000:80 &
sleep 2
curl -s http://localhost:8000/health
python -c "from mlflow import MlflowClient; print('production alias:', MlflowClient(tracking_uri='http://localhost:5000').get_model_version_by_alias('fraud-detector', 'production').version)"
Vous devriez voir : /health avec "status":"ok" et le modèle chargé, et la version pointée par l'alias @production — celle que le cluster sert réellement.You should see: /health with "status":"ok" and the model loaded, and the version pointed at by the @production alias — the one the cluster actually serves.
5Jointure 5 — /metrics est bien scrappéJoint 5 — /metrics is actually scraped

Deux vérifications : l'endpoint répond, et Prometheus le voit en UP. Si le port-forward de Prometheus du bloc 7 est tombé, relancez-le d'abord. Two checks: the endpoint answers, and Prometheus sees it UP. If block 7's Prometheus port-forward dropped, restart it first.

curl -s http://localhost:8000/metrics | grep http_requests_total | head -3
kubectl port-forward service/prometheus 9090:9090 &
sleep 2
curl -s http://localhost:9090/api/v1/targets | grep -o '"health":"[a-z]*"'
Vous devriez voir : des lignes http_requests_total côté API, et "health":"up" côté Prometheus.You should see: http_requests_total lines on the API side, and "health":"up" on the Prometheus side.
6Jointure 6 — la vigie de drift tourneJoint 6 — the drift watchtower runs

Le script du bloc 7 doit tourner et rendre un verdict exploitable : son code de sortie est précisément ce qu'un cron ou une CI transforme en alerte de réentraînement. Block 7's script must run and return an actionable verdict: its exit code is precisely what a cron job or a CI turns into a retraining alert.

python scripts/check_drift.py
echo "exit code: $?"
Vous devriez voir : OK (exit code 0) ou ALERT (exit code 1) — dans les deux cas la boucle est fermée : la vigie sait crier.You should see: OK (exit code 0) or ALERT (exit code 1) — either way the loop is closed: the watchtower knows how to shout.
7Le test de bout en bout, scénariséThe end-to-end test, scripted

Changez un vrai paramètre du modèle et suivez la modification maillon par maillon jusqu'au cluster. Adaptez le sed si votre train.py nomme le paramètre autrement — l'important est : un changement réel, un commit, et la chaîne complète sans toucher un serveur. Change a real model parameter and follow the change link by link down to the cluster. Adapt the sed if your train.py names the parameter differently — what matters is: one real change, one commit, and the full chain without touching a server.

sed -i.bak 's/C=1.0/C=0.5/' src/train/train.py
git add src/train/train.py
git commit -m "experiment: lower regularization to C=0.5"
git push origin main
gh run watch
TAG=$(git rev-parse --short HEAD)
docker pull ghcr.io/your-github-user/fraud-api:$TAG
kind load docker-image ghcr.io/your-github-user/fraud-api:$TAG --name mlops
kubectl set image deployment/fraud-api-canary fraud-api=ghcr.io/your-github-user/fraud-api:$TAG
kubectl rollout status deployment/fraud-api-canary
curl -s http://localhost:8000/health
Vous devriez voir : Actions vert, l'image au nouveau tag, le canary à jour, /health qui répond — la chaîne entière traversée par un seul commit.You should see: green Actions, the image at the new tag, the canary updated, /health answering — the whole chain crossed by a single commit.

Mission 2 — Présenter & relire (1h00)Mission 2 — Present & review (1h00)

8Le déroulé minuté de la démo : docs/demo_script.mdThe demo's minuted script: docs/demo_script.md

Une démo de 5 minutes se prépare comme un déploiement : un déroulé écrit, un plan B, des rôles. Écrivez le gabarit, versionnez-le, puis répétez une fois entière, chrono en main. A 5-minute demo is prepared like a deployment: a written run sheet, a plan B, roles. Write the template, version it, then rehearse once end to end, stopwatch in hand.

mkdir -p docs
cat > docs/demo_script.md <<'EOF'
# 5-minute demo script

## min 0-1 - the commit
- show the one-line change (git diff)
- git push, live, in front of the audience
- announce what the pipeline is about to do

## min 1-3 - the chain
- GitHub Actions: tests green, image built, pushed to ghcr.io
- terminal: kind load + kubectl set image on the canary
- kubectl get pods -l track=canary: the new pod becomes ready

## min 3-4 - the proof
- curl /health: the API answers from the cluster
- MLflow UI: the production alias and the served version match

## min 4-5 - the dashboard
- Prometheus: request rate and latency moving with live traffic
- one closing sentence: what would trigger a rollback, and how

## fallback plan
- keep a screen recording of one previous green run
- decide who drives and who narrates before starting
EOF
git add docs/demo_script.md
git commit -m "docs: 5-minute demo script"
Vous devriez voir : le gabarit commité — et une répétition complète qui tient dans les 5 minutes, pas 8.You should see: the template committed — and one full rehearsal that fits within 5 minutes, not 8.
9La grille de revue croisée : docs/review_grid.mdThe cross-review grid: docs/review_grid.md

On relit le code, jamais le codeur. La grille structure la revue : cinq critères, des preuves observées, et le verdict — 2 points forts, 1 amélioration — déposé en issue sur le dépôt relu. Review the code, never the coder. The grid structures the review: five criteria, observed evidence, and the verdict — 2 strengths, 1 improvement — filed as an issue on the reviewed repo.

cat > docs/review_grid.md <<'EOF'
# Cross review grid

Reviewed repo:
Reviewers:
Date:

| Criterion | Question to answer | Score /5 | Evidence seen |
|---|---|---|---|
| Reproducibility | Clone and run: does it work with the README alone? | | |
| Tests | Do the tests cover the API and the model contract? Does a red test block the merge? | | |
| Clarity | Does the code read without a guide? Predictable src/ layout, no zombie code? | | |
| Governance | Is the model promotion traced in MLflow (who, when, why)? | | |
| Observability | Does the dashboard move when the traffic moves? | | |

## Verdict
- Strength 1:
- Strength 2:
- One concrete improvement:

File the verdict as an issue on the reviewed repo: 2 strengths, 1 improvement.
EOF
git add docs/review_grid.md
git commit -m "docs: cross review grid"
git push origin main
Vous devriez voir : la grille versionnée et poussée — chaque binôme en remplit une sur le dépôt d'un autre binôme.You should see: the grid versioned and pushed — each pair fills one in on another pair's repo.
Si ça coinceWhen it breaks

CI verte, mais le cluster sert l'ancienne version — le manifest du canary pointe un vieux tag : comparez kubectl get deployment fraud-api-canary -o wide avec git rev-parse --short HEAD ; le tag de l'image doit être celui du dernier commit. ErrImagePull / ImagePullBackOff sur le canary — CI verte mais image jamais chargée dans kind : rejouez kind load docker-image … --name mlops — le cluster ne lit ni votre Docker local ni GHCR sans secret. /health répond, mais avec le mauvais modèle — l'alias du registry a été oublié : repointez @production (set_registered_model_alias, bloc 5) puis kubectl rollout restart deployment/fraud-api. Green CI, but the cluster serves the old version — the canary manifest points to an old tag: compare kubectl get deployment fraud-api-canary -o wide with git rev-parse --short HEAD; the image tag must be the latest commit's. ErrImagePull / ImagePullBackOff on the canary — green CI but the image never loaded into kind: rerun kind load docker-image … --name mlops — the cluster reads neither your local Docker nor GHCR without a secret. /health answers, but with the wrong model — the registry alias was forgotten: repoint @production (set_registered_model_alias, block 5) then kubectl rollout restart deployment/fraud-api.