Déploiements du vendredi soir : la tradition qui apprend par la douleur

Cet article vous a aidé ?

La demande de changement est minime. « Juste un réglage de config. » La build est verte. Les tableaux de bord semblent calmes. C’est vendredi, 18h12, et quelqu’un prononce la phrase maudite :
« On le pousse avant qu’on oublie. »

Deux heures plus tard, votre téléphone se transforme en instrument de percussion. Le canal on-call se remplit de captures d’écran de graphes rouges et d’une panique très polie. Les plans du week-end s’évaporent comme un cache mal configuré.

Pourquoi les déploiements du vendredi soir continuent d’arriver

Les déploiements du vendredi ne sont pas un mystère. Ce sont un résultat prévisible des incitations, de la physique du calendrier et de l’optimisme humain.
Les équipes passent la semaine à construire des fonctionnalités, à courir après des deadlines produit et à accumuler des « corrections rapides » comme du linter dans une poche.
Le vendredi arrive et soudain il y a une forte envie de « vider la file » et de partir avec une ardoise propre.

Pendant ce temps, le système de production a son propre calendrier : pics de trafic, jobs batch, latence de réplication, sauvegardes, tempêtes de cron et
fenêtres de maintenance tierces qui ne se coordonnent jamais avec les vôtres. Le vendredi soir est rarement « calme » dans une entreprise distribuée globalement.
Il est juste calme pour les gens qui veulent partir.

Les vrais moteurs (et quoi faire)

  • Compression des deadlines : Un sprint se termine vendredi, pas parce que la physique l’exige, mais parce que les réunions le font. Éloignez le rythme des releases des frontières de sprint.
  • Anxiété de la file : Les équipes craignent une backlog croissante de changements. Réglez cela avec des changements plus petits, pas des sorties plus tard. Livrez moins par changement.
  • Analphabétisme du risque : Les gens confondent « petit diff » et « petit rayon d’impact ». Exigez des déclarations explicites sur le blast radius.
  • Culture du héros : Les incidents du vendredi produisent des « sauvetages » et des histoires de guerre. Récompensez plutôt la prévention : moins de pages vaut mieux que des récupérations spectaculaires.
  • On-call sous-staffé : Vous « pouvez » déployer vendredi parce que quelqu’un est techniquement de garde. Ce n’est pas un plan ; c’est un sacrifice.

Si vous voulez un principe opérationnel unique : ne planifiez pas le risque quand votre capacité de réponse est la plus faible. Le vendredi soir, la
disponibilité en personnel, le contexte et la disponibilité des fournisseurs sont au pire. Ce n’est pas une défaillance morale ; c’est des mathématiques.

Blague #1 : Un déploiement du vendredi, c’est comme jongler des tronçonneuses dans le noir — impressionnant jusqu’à ce qu’il faille un pansement et que le magasin soit fermé à 18h.

Un peu d’histoire : comment on en est arrivé là (faits, pas folklore)

« Ne jamais déployer le vendredi » est souvent traité comme une superstition. Ce n’en est pas une. C’est une heuristique grossière construite à partir de décennies d’expérience opérationnelle — surtout d’époques où revenir en arrière signifiait restaurer des bandes, reconstruire des serveurs ou réveiller un DBA.

Faits et points de contexte (brefs, concrets)

  1. Contrôle de changement en entreprise ancien (années 1980–1990) utilisait souvent des fenêtres de maintenance hebdomadaires, communément le week-end, parce que l’on supposait des interruptions et que les utilisateurs étaient « hors ligne ».
  2. Gestion de changement de type ITIL s’est popularisée dans les grandes organisations pour réduire les pannes, mais beaucoup d’implémentations ont optimisé la paperasserie plutôt que l’apprentissage et l’automatisation.
  3. Les entreprises web-scale dans les années 2000 ont normalisé le déploiement continu parce que l’indisponibilité coûtait du chiffre d’affaires, pas « une maintenance acceptable ». Un déploiement plus rapide a exigé de meilleurs rollbacks et observabilité.
  4. Blue/green deployments sont devenus courants pour réduire le risque de cutover en basculant le trafic entre deux environnements plutôt qu’en modifiant la production en place.
  5. Canary releases ont grandi avec les architectures de services : déployer sur un petit pourcentage, mesurer, puis élargir. C’est une expérience contrôlée, pas un saut dans l’inconnu.
  6. Feature flags ont évolué de « kill switches » à des contrôles complets de release, permettant de découpler déploiement et activation — utile quand votre déploiement arrive avant d’être certain.
  7. Orchestration de conteneurs (notamment Kubernetes) a rendu les rollouts communs et plus simples, mais a aussi rendu l’échec plus rapide : une mauvaise config peut se propager globalement en minutes.
  8. Observabilité est passée des graphes d’hôtes au tracing distribué et à l’alerte basée sur les SLO, rendant les releases plus sûres — mais seulement si les équipes l’utilisent pour valider les changements, pas pour décorer des dashboards.

L’arc historique est cohérent : plus vous voulez livrer en sécurité, plus vous avez besoin d’automatisation, de feedback rapide et de la capacité d’annuler. Les déploiements du vendredi ne sont pas « interdits » par la tradition ; ils sont déconseillés par la réalité : annuler et obtenir du feedback est plus lent quand tout le monde est parti.

Ce que font les changements du vendredi soir aux systèmes (et aux équipes)

Modes de défaillance techniques que le vendredi accentue

Les systèmes échouent de la même façon le mardi et le vendredi. La différence est le temps‑jusqu’à‑la‑vérité. Le vendredi augmente le temps pour remarquer, décider et récupérer.

  • Défaillances à combustion lente : fuites de mémoire, accumulation de files, contention de verrous et tempêtes de compactage prennent souvent des heures pour devenir évidentes — commodément après que tout le monde s’est déconnecté.
  • Opacité des dépendances : l’ingénieur qui comprend le comportement de timeout du fournisseur de paiement est à table. La doc est « sur le wiki ». Le wiki est « en maintenance ».
  • Risque de rollback : les changements de schéma, migrations avec état et jobs en arrière-plan transforment le rollback en archéologie.
  • Falaises de capacité : les patterns de trafic du vendredi peuvent être bizarres : emails promo, pics d’usage le week-end ou jobs batch qui entrent en collision avec des sauvegardes.
  • Latence humaine : même les répondeurs compétents sont plus lents à 2h du matin. C’est de la biologie, pas de l’incompétence.

Le côté organisationnel : le vendredi cache les mauvais processus

Les déploiements du vendredi sont souvent une odeur de processus : pas de vrai train de release, pas de propriété claire, pas de classification explicite du risque,
pas de rollback répété et pas de « définition de fini » qui inclut l’exploitation.

L’objectif n’est pas « interdire le vendredi ». L’objectif est « rendre le vendredi ennuyeux ». Si vous pouvez déployer vendredi soir et dormir, vous l’avez mérité par
la discipline : petits changements, forte automatisation, rollback rapide et habitude de vérifier la réalité au lieu de faire confiance aux coches vertes.

Playbook de diagnostic rapide : trouver le goulot vite

Quand un déploiement du vendredi prend une mauvaise tournure, la pire chose à faire est de s’agiter. La deuxième pire est d’ouvrir cinq dashboards et
de déclarer : « Tout a l’air bizarre. »

Ce playbook est conçu pour les 15 premières minutes : restreindre l’espace problématique, stabiliser, puis choisir rollback ou roll-forward.

0) D’abord : arrêter d’empirer les choses

  • Mettre en pause les rollouts. Geler les merges. Arrêter le « encore une petite correction ».
  • Annoncer un canal d’incident et un seul leader d’incident.
  • Décider d’une action de sécurité : réduire la charge, désactiver la nouvelle fonctionnalité, vider le trafic ou rollback.

1) Vérifier les symptômes côté utilisateur (2 minutes)

  • Est-ce de la disponibilité ou de la correction ? 500 vs données erronées vs timeouts.
  • Est-ce global ou régional ? Une zone, une région, un locataire, une cohorte.
  • Est-ce corrélé au temps du déploiement ? Comparez le taux d’erreur/la latence au début du rollout, pas « à peu près quand on a livré ».

2) Décider quelle couche échoue (5 minutes)

  • Edge : TLS, DNS, CDN, contrôles de santé du load balancer.
  • App : crash loops, timeouts de dépendance, exhaustion de threads/connexions.
  • Données : verrous DB, latence de réplication, latence de stockage, backlog de files.
  • Plateforme : pression sur les nœuds, réseau, autoscaling, limites de quotas.

3) Trouver le goulot avec « un indicateur par couche » (8 minutes)

Choisissez une métrique ou un log « révélateur » par couche pour éviter de vous noyer :

  • Edge : taux de 5xx à l’ingress, p95 de latence au LB, retransmissions SYN.
  • App : latence par endpoint, comptage des types d’erreurs, nombre de redémarrages.
  • Données : sessions actives DB, requêtes lentes, latence de réplication, attente disque.
  • Plateforme : steal CPU, pression mémoire, évictions de pods kube, erreurs réseau.

4) Choisir rollback vs. roll-forward (et être explicite)

  • Rollback quand le blast radius est élevé, le mode de défaillance inconnu ou la correction non triviale.
  • Roll-forward quand vous avez une correction chirurgicale et la confiance de ne pas aggraver l’incident.

Idée paraphrasée (pas mot pour mot) : Werner Vogels a soutenu que « tout échoue, tout le temps », donc les systèmes résilients supposent l’échec et récupèrent rapidement.

Tâches pratiques : commandes, sorties et décisions (12+)

Voici les vérifications rugueuses qui transforment « je pense que c’est la base » en « le primaire est saturé en IO d’écriture et la réplication prend du retard ».
Chaque tâche inclut : une commande, un exemple de sortie, ce que ça signifie et la décision à prendre.

1) Confirmer ce qui a réellement changé (Git)

cr0x@server:~$ git show --name-status --oneline HEAD
8c2f1a7 prod: enable async indexer; tune pool size
M app/config/prod.yaml
M app/indexer/worker.py
M db/migrations/20260202_add_index.sql

Ce que ça signifie : Vous n’avez pas livré « juste de la config ». Vous avez livré du code + de la config + une migration. Ce sont trois surfaces d’échec.

Décision : Traitez-le comme haut risque. Si les symptômes touchent la DB ou les jobs en arrière-plan, priorisez le rollback/la désactivation par feature flag plutôt que « retoucher un paramètre ».

2) Vérifier le statut du déploiement (rollout Kubernetes)

cr0x@server:~$ kubectl -n prod rollout status deploy/api --timeout=30s
Waiting for deployment "api" rollout to finish: 3 of 24 updated replicas are available...

Ce que ça signifie : Les nouveaux pods ne deviennent pas prêts. Ça peut être des crash loops, des probes de readiness échouant ou des timeouts de dépendance.

Décision : Mettez le rollout en pause immédiatement pour éviter l’élargissement du blast radius ; inspectez ensuite les events et logs des pods.

3) Mettre en pause un rollout pour arrêter l’hémorragie

cr0x@server:~$ kubectl -n prod rollout pause deploy/api
deployment.apps/api paused

Ce que ça signifie : Plus aucun pod ne sera mis à jour tant que vous n’aurez pas repris.

Décision : Si les erreurs sont corrélées aux pods mis à jour uniquement, restez en pause et envisagez de monter l’ancienne ReplicaSet.

4) Identifier les crash loops et leur raison

cr0x@server:~$ kubectl -n prod get pods -l app=api -o wide
NAME                     READY   STATUS             RESTARTS   AGE   IP            NODE
api-7f6cf4c8c8-2qkds      0/1    CrashLoopBackOff   6          12m   10.42.1.17    node-a
api-7f6cf4c8c8-9s1bw      1/1    Running            0          2h    10.42.3.22    node-c

Ce que ça signifie : Certains pods sont instables ; le problème peut dépendre de la config ou du nœud.

Décision : Récupérez les logs d’un pod en échec ; comparez la config et l’environnement avec un pod sain.

5) Lire les derniers logs du conteneur en échec

cr0x@server:~$ kubectl -n prod logs api-7f6cf4c8c8-2qkds --previous --tail=50
ERROR: cannot connect to postgres: connection refused
ERROR: exiting after 30s startup timeout

Ce que ça signifie : L’app ne peut pas atteindre la DB (ou la DB refuse les connexions). Ça peut être une policy réseau, un DNS, un endpoint erroné, ou une DB surchargée.

Décision : Vérifiez le service discovery et la connectivité DB depuis le cluster ; vérifiez aussi la santé de la DB et le nombre de connexions.

6) Valider DNS et routage depuis un pod debug

cr0x@server:~$ kubectl -n prod run netdebug --rm -it --image=busybox:1.36 -- sh -c "nslookup postgres.prod.svc.cluster.local; nc -zv postgres.prod.svc.cluster.local 5432"
Server:    10.96.0.10
Address:   10.96.0.10:53

Name:      postgres.prod.svc.cluster.local
Address:   10.96.34.21

postgres.prod.svc.cluster.local (10.96.34.21:5432) open

Ce que ça signifie : DNS fonctionne et le port est ouvert. La connectivité existe ; le refus vu dans les logs peut provenir du process DB, pas du réseau.

Décision : Orientez l’attention sur la charge DB, les max connections, l’authentification ou l’état de basculement.

7) Vérifier les connexions DB et la pression de verrous (PostgreSQL)

cr0x@server:~$ psql -h db-primary -U app -d appdb -c "select count(*) as conns, sum(case when wait_event_type is not null then 1 else 0 end) as waiting from pg_stat_activity;"
 conns | waiting
-------+---------
  497  |     183
(1 row)

Ce que ça signifie : Beaucoup de sessions, beaucoup en attente. C’est là que naissent la latence et les timeouts.

Décision : Identifiez ce sur quoi ils attendent ; envisagez de réduire le nouveau worker, désactiver un nouveau chemin de code, ou augmenter les pools seulement si la DB a la capacité.

8) Trouver les principaux wait events (PostgreSQL)

cr0x@server:~$ psql -h db-primary -U app -d appdb -c "select wait_event_type, wait_event, count(*) from pg_stat_activity where wait_event_type is not null group by 1,2 order by 3 desc limit 5;"
 wait_event_type |     wait_event     | count
-----------------+--------------------+-------
 Lock            | relation           |   122
 IO              | DataFileRead       |    44
 Client          | ClientRead         |    17
(3 rows)

Ce que ça signifie : Contention de verrous plus waits IO. Une migration ou une requête chaude est probable.

Décision : Si une migration a été lancée, envisagez d’abandonner/rollback du déploiement et de traiter l’état de migration ; si c’est lié à une requête, identifiez la source et limitez-la.

9) Vérifier si une migration tourne et bloque

cr0x@server:~$ psql -h db-primary -U app -d appdb -c "select pid, state, query from pg_stat_activity where query ilike '%alter table%' limit 3;"
 pid  | state  |                 query
------+--------+----------------------------------------
 8121 | active | ALTER TABLE orders ADD COLUMN foo text;
(1 row)

Ce que ça signifie : Un ALTER TABLE est actif ; selon l’opération, il peut verrouiller et bloquer le trafic.

Décision : Décidez de terminer la requête en acceptant un état de migration partiel, ou de continuer et réduire la charge ; si vous ne pouvez pas compléter en sécurité, rollback du comportement applicatif qui en dépend.

10) Vérifier la latence disque sur l’hôte DB (iostat)

cr0x@server:~$ iostat -xz 1 3
avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          18.44    0.00    6.21   22.17    0.00   53.18

Device            r/s     w/s   rkB/s   wkB/s  await  svctm  %util
nvme0n1         320.0  810.0  51200.0 104000.0  24.7   0.8   92.5

Ce que ça signifie : Iowait élevé et util disque élevé ; un await moyen ~25ms est rude pour une base chaude.

Décision : Identifiez la source d’IO (migration, vacuum, nouvel indexeur). Limitez les jobs en background ; envisagez de revenir sur les changements qui ont augmenté l’amplification d’écriture.

11) Vérifier l’espace filesystem et la pression d’inodes

cr0x@server:~$ df -h /var/lib/postgresql
Filesystem      Size  Used Avail Use% Mounted on
/dev/md0        1.8T  1.7T   62G  97% /var/lib/postgresql

Ce que ça signifie : 97% d’utilisation. Ce n’est pas « acceptable ». C’est « une autovacuum loin du drame ».

Décision : Arrêtez les tâches optionnelles écriture-intensive ; libérez de l’espace (anciennes archives WAL, vieilles sauvegardes) en sécurité ; envisagez une expansion d’urgence. Ne continuez pas à déployer des écritures.

12) Vérifier la mémoire système et le risque OOM

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:            62Gi        57Gi       1.2Gi       1.1Gi       3.8Gi       1.7Gi
Swap:          4.0Gi       3.9Gi       128Mi

Ce que ça signifie : Vous vivez dans le swap. La latence va exploser ; le noyau pagine au lieu de servir.

Décision : Réduisez les workers gourmands en mémoire ; envisagez de revenir sur un changement qui a augmenté la taille des caches ; si nécessaire, déplacez le trafic ou ajoutez de la capacité.

13) Vérifier rapidement le trafic et les erreurs d’un service (logs nginx)

cr0x@server:~$ sudo tail -n 5 /var/log/nginx/access.log
10.20.1.14 - - [02/Feb/2026:18:21:10 +0000] "GET /api/orders HTTP/1.1" 502 173 "-" "mobile/1.9"
10.20.1.15 - - [02/Feb/2026:18:21:10 +0000] "GET /api/orders HTTP/1.1" 502 173 "-" "mobile/1.9"

Ce que ça signifie : Les 502 à l’edge signifient généralement une défaillance en amont : crash d’app, timeouts ou exhaustion de connexions.

Décision : Corréler les pics de 502 avec les redémarrages de pods et les waits DB ; si forte corrélation avec le déploiement, rollback justifié.

14) Vérifier les events kube pour problèmes de scheduling/santé

cr0x@server:~$ kubectl -n prod get events --sort-by=.lastTimestamp | tail -n 8
Warning  Unhealthy  kubelet  Readiness probe failed: HTTP probe failed with statuscode: 500
Warning  BackOff    kubelet  Back-off restarting failed container
Warning  Failed     kubelet  Error: context deadline exceeded

Ce que ça signifie : Les probes échouent et les redémarrages. « context deadline exceeded » indique des dépendances lentes ou des nœuds surchargés.

Décision : Si les probes sont trop strictes, ne les « corrigez » pas en les désactivant ; corrigez la dépendance ou rollbackez. Les checks de santé sont des messagers, pas l’ennemi.

15) Confirmer quelle version sert le trafic (image tag)

cr0x@server:~$ kubectl -n prod get deploy/api -o jsonpath='{.spec.template.spec.containers[0].image}{"\n"}'
registry.internal/prod/api:8c2f1a7

Ce que ça signifie : Vous pouvez maintenant aligner « incident commencé » avec « version en service ». Finies les disputes basées sur les impressions.

Décision : Si seule la nouvelle version est corrélée aux erreurs, rollback vers le tag connu‑bon.

16) Revenir en arrière sur le déploiement (Kubernetes)

cr0x@server:~$ kubectl -n prod rollout undo deploy/api
deployment.apps/api rolled back

Ce que ça signifie : Kubernetes rétablit le spec du ReplicaSet précédent. Il n’annule pas les migrations DB ni les effets secondaires.

Décision : Si l’incident impliquait le schéma ou des jobs en arrière-plan, stabilisez l’app après le rollback puis traitez le nettoyage du niveau données délibérément.

Trois micro-récits de la vie en entreprise

Micro-récit 1 : L’incident causé par une mauvaise hypothèse

Une entreprise de taille moyenne gérait un service d’analytique client sur Kubernetes. L’équipe voulait réduire la latence de cold-start pour un endpoint populaire.
Ils ont ajouté un cache warmer qui s’exécutait au démarrage : lancer quelques requêtes communes, remplir le cache, et vous êtes prêts pour le pic.
Ça fonctionnait en staging. Ça fonctionnait dans un test de production calme.

L’hypothèse était simple : « Quelques requêtes communes » seraient bon marché. Mais « communes » impliquait une jointure de deux grandes tables et le scan de partitions récentes.
Le warmer s’exécutait sur chaque nouveau pod, et le déploiement du vendredi a augmenté le nombre de replicas pour gérer l’usage du week-end.

À 19h, le rollout a commencé. Les nouveaux pods sont montés, ont exécuté le warmer, et ont frappé la base de données comme une équipe de natation synchronisée composée de marteaux.
Le CPU DB a grimpé, puis l’IO, puis les waits de verrous. L’app a commencé à timeouter, ce qui a déclenché des retries, qui ont multiplié le trafic, qui ont déclenché l’autoscaling,
qui a lancé plus de pods, qui ont exécuté plus de warmers. Une boucle fermée. Bien ficelée.

L’ingénieur on-call a vu « connection refused » et a supposé un problème réseau. Il a redémarré le proxy DB.
Cela a empiré : tempêtes de reconnexion en plus d’une charge déjà élevée. Ce n’est qu’après avoir regardé les wait events qu’ils ont vu la contention de verrous et les waits IO,
et les warmers apparaissaient partout dans les logs de requêtes.

La correction n’était pas brillante. Ils ont livré un feature flag : cache warming désactivé par défaut en production, activable uniquement après vérification de la headroom DB.
Plus tard ils l’ont repensé pour préchauffer à partir d’un dataset précalculé, pas de joins live. Ils ont aussi ajouté une règle : tout job de démarrage qui touche une dépendance partagée
doit être limité en taux et testé sous conditions de rollout à l’échelle.

Micro-récit 2 : L’optimisation qui a retourné sa veste

Une autre organisation avait une passerelle de stockage objet interne en face d’un cluster de stockage. Leur problème : latence d’écriture sous charges de pointe.
L’optimisation proposée : augmenter la concurrence. Plus de threads workers, files plus profondes, plus gros batches. Le vendredi semblait « sûr » car le trafic était modéré.

Le changement a été déployé avec un tweak de config : pool de workers doublé et la passerelle a commencé à bufferiser des chunks plus volumineux en mémoire avant flush.
Les métriques se sont immédiatement améliorées dans un benchmark synthétique. En production, la première heure était excellente : débit en hausse, p95 en baisse.
On a posté des graphes de célébration. Quelqu’un a suggéré d’appliquer ça à toutes les régions.

Puis la pression mémoire a commencé à monter. La passerelle tenait maintenant plus d’écritures en vol par connexion, et les clients étaient plus enclins à retenter
parce que ça semblait rapide. Les pauses du garbage collector se sont allongées. Le noyau a commencé à récupérer la mémoire agressivement. Finalement la passerelle
est entrée dans une boucle OOM-kill, mais seulement sur un sous-ensemble de nœuds avec un tuning kernel plus ancien. Le vendredi soir a fait que la seule personne qui se souvenait
de ces nœuds n’était pas réveillée.

L’« optimisation » réduisait la latence jusqu’à basculer en effondrement. Le rollback a restauré la stabilité mais laissé un bazar : uploads multipart partiellement écrits,
clients confus et un backlog qu’il a fallu des heures à résorber.

La leçon n’était pas « ne jamais optimiser ». C’était « optimiser avec garde‑fous ». Ils ont ajouté des limites par tenant, des caps sur les octets en vol,
et exigé un test de charge qui reproduit la concurrence de production, pas un benchmark de labo. Ils ont aussi créé un petit « pool canari » de nœuds qui reçoit toujours
les changements de config en premier, avec une surveillance renforcée sur la mémoire et les temps de pause GC.

Micro-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Un service adjacent aux paiements avait l’habitude stricte : chaque déploiement comprenait une validation post-déploiement scriptée depuis un hôte neutre.
Pas depuis le laptop d’un dev. Pas depuis l’intérieur du cluster. Depuis une machine de validation verrouillée dans le même réseau que les clients réels.
Elle vérifiait DNS, TLS, quelques endpoints critiques et un flux d’achat synthétique qui ne touchait jamais de l’argent réel.

Un vendredi soir, un déploiement de routine a mis à jour la config de terminaison TLS. Tout « semblait » correct : pods sains, CPU normal, taux d’erreur bas.
Mais en quelques minutes, le support client a commencé à voir des échecs épars provenant de certains clients mobiles.

La validation ennuyeuse l’a détecté avant les graphes : échecs de handshake TLS pour une suite de chiffrement client spécifique. Le déploiement avait accidentellement supprimé
un cipher nécessaire pour des appareils plus anciens. Parce que le script de validation simulait plusieurs profils clients, il a signalé la régression immédiatement.

Ils ont rollbacké en moins de dix minutes. Pas d’héroïsme. Pas d’appel interminable. La partie la plus dramatique était que quelqu’un s’est autorisé à mâcher en silence.
Le vrai gain : ils ont évité un incident lent qui se serait répandu sous forme de « paiements aléatoires échouant » sur tout un week-end.

Cette équipe était taquinée pour être old‑fashioned. Elle était aussi la seule à régulièrement profiter de week-ends sans interruption.
L’ennui était le but.

Blague #2 : Le moyen le plus rapide de découvrir des dépendances non documentées est de déployer un vendredi et d’attendre qu’elles se présentent.

Erreurs courantes : symptôme → cause racine → correction

Les incidents du vendredi soir ont des motifs récurrents. En voici qui reviennent, avec des corrections spécifiques qui changent les résultats.

1) Symptom : pic de latence p95, CPU normal

  • Cause racine : attente IO ou contention de verrous ; l’app est inerte car elle attend le disque ou des verrous DB.
  • Correction : Vérifiez iowait et les wait events DB ; limitez les jobs en arrière-plan ; évitez « ajouter des threads ». Revenir sur des migrations qui introduisent des écritures lourdes.

2) Symptom : 502/504 au load balancer après le deploy

  • Cause racine : pods non prêts, crash loops ou timeouts en amont dus à une dépendance surchargée.
  • Correction : Pausez le rollout, inspectez les échecs de readiness, comparez nouveaux et anciens pods. Rollback si la régression de dépendance n’est pas claire en 10–15 minutes.

3) Symptom : taux d’erreur qui augmente lentement sur 30–90 minutes

  • Cause racine : fuite mémoire, croissance de files, exhaustion de pool de connexions ou amplification de retries.
  • Correction : Vérifiez mémoire, redémarrages, profondeur des files et compteurs de retries. Désactivez le nouveau chemin via feature flag ; réduisez les retries et ajoutez du jitter.

4) Symptom : « connection refused » ou « too many clients » sur la DB

  • Cause racine : tempête de connexions après rollout, mismatch tailles de pool, max_connections DB atteint ou proxy surchargé.
  • Correction : Limitez les pools appli ; ajoutez un connection pooler ; déployez lentement ; assurez-vous que les probes de liveness ne provoquent pas de tempêtes de restart.

5) Symptom : une seule région est cassée

  • Cause racine : config spécifique à la région, secret manquant, mauvais DNS ou capacité inégale.
  • Correction : Différenciez config et secrets entre régions ; validez la résolution DNS depuis cette région ; ne faites pas de « rollback global » si le problème est localisé.

6) Symptom : rollback ne répare pas

  • Cause racine : effets irréversibles : changement de schéma, corruption de données, jobs en file, cache empoisonné ou backlog de files.
  • Correction : Ayez des étapes « rollback plus remédiation » : arrêter les runners, vider les files, restaurer les caches ou exécuter des migrations compensatoires.

7) Symptom : alertes bruyantes mais les utilisateurs disent que tout va bien

  • Cause racine : alerting basé sur des erreurs internes sans contexte SLO ; canaris non exclus ; explosion de cardinalité métriques.
  • Correction : Liez les alertes à l’impact utilisateur ; gardez des signaux séparés pour canary et baseline ; limitez la cardinalité des labels.

8) Symptom : nouveaux pods sains, mais débit en baisse

  • Cause racine : throttling au niveau nœud (limits CPU), voisin bruyant IO ou changement de network policy augmentant la latence.
  • Correction : Vérifiez throttling et pression nœud ; déplacez les workloads ; vérifiez le throttling cgroup CPU ; revoyez les diffs de network policy.

Checklists / plan étape par étape (déployer en sécurité ou ne pas déployer)

Décision pré‑vendredi : ce déploiement doit‑il avoir lieu ?

  • Classifiez le changement : sans état vs avec état ; touche le schéma ou non ; change les dépendances ou non.
  • Demandez « quel est le blast radius ? » Nommez les systèmes et l’impact utilisateur pire‑cas en un paragraphe.
  • Vérification du rollback : Pouvez‑vous l’annuler en moins de 15 minutes ? Si non, ce n’est pas un déploiement du vendredi ; c’est une planification d’incident.
  • Vérification staffing : Y a‑t‑il un deuxième ingénieur disponible ? Pas « joignable ». Disponible.
  • Vérification dépendances fournisseurs : Changez‑vous quelque chose nécessitant un support externe ? Si oui, ne livrez pas tard le vendredi.

Étapes : un flux de déploiement plus sûr

  1. Geler le périmètre : pas de commits de dernière minute. Taggez le candidat release.
  2. Vérifier les artefacts : confirmez que les digests/tags d’image correspondent à ce que vous avez testé.
  3. Exécuter les contrôles préflight : santé DB, espace disque, latence de réplication, profondeur des files, budgets d’erreur.
  4. Activer un kill switch : feature flag ou toggle config qui désactive le nouveau comportement sans redéploiement.
  5. Canary d’abord : 1–5% du trafic. Surveillez les signaux clés pendant 10–20 minutes, pas 60 secondes.
  6. Monter les échelons prudemment : rythme de rollout lent ; évitez les restarts synchronisés ; gatez chaque étape sur des métriques.
  7. Validation post‑déploy : contrôles scriptés depuis une perspective externe.
  8. Déclarer « fini » explicitement : quand les métriques sont stables et que la fenêtre de rollback est encore ouverte.
  9. Rédiger la note : ce qui a changé, comment désactiver et quoi surveiller — tant que les détails sont frais.

Checklist de rollback (parce que vous en aurez besoin un jour)

  • Arrêter le rollout : pausez les déploiements et les auto-scalers s’ils amplifient le problème.
  • Désactiver le nouveau comportement en premier : feature flag off. C’est plus rapide que redeployer.
  • Rollback des composants sans état : revenir sur les pods/services applicatifs.
  • Stabiliser la couche données : arrêter les migrations et les runners qui écrivent.
  • Vider les files délibérément : ne déversez pas un backlog sur une DB malade.
  • Confirmer la récupération : contrôles synthétiques côté utilisateur, taux d’erreur, latence et tendance du backlog.

Politiques qui fonctionnent vraiment (sans transformer les ingénieurs en bureaucrates)

La plupart des politiques « pas de déploiement le vendredi » échouent parce qu’elles sont des règles morales déguisées en technique.
Les ingénieurs vont contourner des règles morales. Surtout quand la pression produit arrive avec une deadline.

1) Remplacez « pas le vendredi » par « changements classés par risque »

Autorisez les déploiements à faible risque n’importe quand : changements sans état avec rollback prouvé, sans schéma, sans nouvelle dépendance et forte couverture canary.
Restreignez les changements à haut risque (schéma, stockage, auth, réseau, flux de paiement) à des fenêtres avec staff complet et couverture fournisseur.

2) Faites du rollback une exigence produit

Si la fonctionnalité ne peut pas être désactivée rapidement, elle n’est pas prête pour la production. Ce n’est pas une préférence ops ; c’est une exigence de sécurité utilisateur.
Les feature flags ne servent pas qu’à expérimenter. Ce sont des disjoncteurs face à la latence organisationnelle.

3) Liez les droits de déploiement à l’observabilité et aux runbooks

Si vous ne pouvez pas répondre « que devrais‑je voir dans les métriques si ça marche ? » vous n’êtes pas prêt à livrer.
Chaque déploiement doit porter ses propres étapes de vérification : quels graphes, quels logs, quel signal de budget d’erreur.

4) Traitez les migrations comme des livrables séparés

Les changements de schéma doivent être mis en scène, rétrocompatibles et découplés du comportement applicatif.
Déployez du code qui peut fonctionner à la fois en pré- et post-migration. Ensuite migrez. Ensuite basculez le comportement.
Le vendredi soir n’est pas le moment de découvrir que votre ORM a généré un DDL bloquant.

5) Normalisez le « stop » comme un succès

Vous avez besoin d’une culture où annuler un déploiement est considéré comme compétent, pas lâche.
Si quelqu’un dit « je n’aime pas les signaux », vous arrêtez. Si la direction punit cela, vous aurez plus d’incidents du vendredi.
Ce n’est pas une prédiction. C’est une déclaration comptable.

FAQ

1) « Ne jamais déployer le vendredi » est‑ce vraiment un bon conseil ?

En règle générale, c’est grossier mais protecteur. La meilleure règle est : ne déployez pas quand vous ne pouvez pas répondre.
Les équipes mâtures peuvent déployer n’importe quel jour parce qu’elles ont construit un rollback rapide, des canaris et des vérifications. La plupart des équipes n’en sont pas encore là.

2) Qu’est‑ce qui compte comme un changement « sûr pour le vendredi » ?

Changements sans état avec un chemin de rollback prouvé, pas de modification de schéma, pas de montée de dépendances, pas de nouveaux jobs en arrière-plan et un feature flag pour désactiver le comportement.
De plus : vous devez avoir un script de validation post‑déploiement que vous exécuterez réellement.

3) Les canary deployments suffisent‑ils pour rendre le vendredi sûr ?

Seulement si votre canary est représentatif et vos signaux sont significatifs. Si le trafic canari n’exerce pas les chemins de code risqués,
vous ne faites que retarder la panne jusqu’à la montée du trafic.

4) Pourquoi les rollbacks n’aident parfois pas ?

Parce que beaucoup de défaillances ne sont pas dans la couche sans état. Migrations de données, empoisonnement de cache, jobs en file et écritures partielles restent après un rollback.
Il faut des actions compensatoires : arrêter les écrivants, vider en sécurité et réparer l’état.

5) Faut‑il préférer rollback ou roll‑forward ?

Rollback quand le mode de défaillance est flou ou que l’impact utilisateur est élevé. Roll‑forward quand vous avez une petite correction bien comprise et la confiance de ne pas prolonger l’incident.
L’erreur est de décider par fierté plutôt que par blast radius.

6) Quel est le meilleur investissement unique pour réduire les incidents du vendredi ?

Un script de validation post‑déploiement reproductible plus un kill switch. Cette paire convertit le « on espère » en « on a vérifié », et raccourcit drastiquement les incidents.

7) Comment arrêter les exceptions « juste cette fois » ?

Rendez les exceptions coûteuses et visibles : exigez un écrit de risque explicite, un lead d’incident nommé en standby et un plan de rollback revu avant livraison.
Les exceptions doivent ressembler à la planification d’une opération, pas à la commande de plats à emporter.

8) Que faire si la business exige des releases le vendredi ?

Traitez alors le vendredi comme une fenêtre de release staffée : on-call plus un deuxième ingénieur, décideurs disponibles et gel des autres travaux risqués.
Si l’entreprise veut des releases le vendredi mais ne finance pas la capacité de réponse, ce n’est pas une exigence. C’est un pari.

9) Les feature flags créent‑ils leurs propres risques ?

Oui : dérive de configuration, flags oubliés et complexité. Gérez les flags avec une propriété, des dates d’expiration et des logs d’audit.
Mais le bénéfice opérationnel est énorme : les flags transforment des pannes en toggles.

10) Comment savoir si nous sommes « mûrs » pour déployer le vendredi ?

Quand vos incidents de déploiement sont rares, courts et ennuyeux : détection rapide, rollback clair et récupération vérifiée.
Si votre MTTR se mesure en heures et que vos postmortems mentionnent « on n’avait pas accès », vous n’y êtes pas.

Conclusion : prochaines étapes à faire cette semaine

Les déploiements du vendredi soir ne sont pas mauvais. Ils sont juste honnêtes. Ils révèlent ce que votre processus prétendait ne pas savoir :
le rollback n’est pas réel, la validation est ad hoc, les migrations font peur et la connaissance opérationnelle de l’équipe est enfermée dans quelques têtes.

Si vous voulez moins de week‑ends dévorés par des « petits changements », faites ces étapes :

  1. Créez une politique de niveaux de risque qui restreint les changements stateful/à fort blast radius aux fenêtres staffées.
  2. Ajoutez un kill switch pour chaque nouveau comportement risqué, et testez‑le comme une vraie fonctionnalité.
  3. Rédigez un script de validation post‑déploiement qui s’exécute en dehors du cluster et vérifie le parcours utilisateur.
  4. Entraînez‑vous au rollback en plein jour : chronométrez‑le, documentez‑le et corrigez ce qui est lent.
  5. Rendez les migrations ennuyeuses en les découpant : rétrocompatibles, en étapes et observables.

Le but final n’est pas « pas de déploiements le vendredi ». C’est « pas de surprises le vendredi ». Vous gagnez ça par la discipline, pas par la chance.

← Précédent
Debian 13 « Could not resolve host » : DNS/proxy/IPv6 — le chemin de diagnostic le plus rapide
Suivant →
Proxmox « Trop de fichiers ouverts » : quelle limite augmenter, et pour quel service

Laisser un commentaire