Chapitre 1216 minIntermédiaire
Stratégies de déploiement : blue-green, canary et rollback
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- comparer les stratégies de déploiement et choisir la bonne ;
- mettre en place un blue-green ou un canari simple avec Nginx ;
- utiliser un interrupteur de fonctionnalité ;
- revenir en arrière vite et dans le bon ordre après un incident.
4 exercices corrigés1 schéma
Une stratégie de déploiement est la manière de remplacer l'ancienne version d'une application par la nouvelle en production : d'un seul coup, instance par instance, en basculant entre deux environnements (blue-green) ou en exposant d'abord une petite partie des utilisateurs (canary). Elle détermine la coupure de service, le risque pris et la vitesse du retour arrière (rollback). Ce chapitre compare ces stratégies, présente les interrupteurs de fonctionnalité, puis détaille comment revenir en arrière quand un déploiement se passe mal.
Recréation : arrêter, puis démarrer
La stratégie la plus simple : on arrête l'ancienne version, puis on démarre la nouvelle. C'est ce que fait docker compose up -d dans le script du chapitre 11.
- Avantage : simple, une seule version tourne à la fois, aucune question de compatibilité entre versions.
- Inconvénient : une coupure, de quelques secondes à quelques minutes, et un retour arrière qui demande un nouveau redémarrage.
- Quand : une application interne, déployée hors des heures de travail ; un projet de BTS.
Déploiement progressif (rolling update)
L'application tourne sur plusieurs instances derrière un répartiteur de charge (load balancer). On remplace les instances une par une : on en retire une du répartiteur, on la met à jour, on vérifie qu'elle répond, on la remet, puis on passe à la suivante.
- Avantage : pas de coupure, pas de matériel en plus.
- Inconvénient : pendant le déploiement, les deux versions servent des utilisateurs en même temps ; elles doivent être compatibles (même API, même schéma de base). Un retour arrière refait le même chemin à l'envers, instance par instance.
- Quand : c'est la stratégie par défaut de Kubernetes (réglages
maxSurgeetmaxUnavailabled'un Deployment) et de Docker Swarm.
Bleu-vert (blue-green)
On maintient deux environnements de production identiques, le bleu et le vert. Un seul reçoit le trafic. On déploie la nouvelle version sur celui qui est au repos, on le teste tranquillement, puis on bascule tout le trafic d'un coup en changeant la configuration du répartiteur.
Sur un seul serveur, avec Nginx en frontal, le bleu peut écouter sur le port 3001 et le vert sur le port 3002. La bascule consiste à changer une ligne et à recharger Nginx, sans coupure :
# /etc/nginx/conf.d/sorbier-frais-upstream.conf
upstream sorbier_frais {
server 127.0.0.1:3002; # vert, en service ; le bleu (3001) garde l'ancienne version
}
sudo nginx -t && sudo systemctl reload nginx # vérifie la configuration, puis la recharge sans couper les connexions
- Avantage : bascule instantanée, et retour arrière instantané : on rebascule vers l'environnement précédent, toujours démarré.
- Inconvénient : deux environnements à maintenir (le double de ressources pendant le déploiement), et la base de données est généralement partagée : le nouveau schéma doit rester compatible avec l'ancienne version, d'où les migrations par expansion puis contraction (les migrations).
- Quand : une application où une coupure coûte cher et où l'on veut un retour arrière en quelques secondes.
Canari (canary)
Le nom vient des canaris que les mineurs emportaient au fond des galeries : l'oiseau, plus sensible, signalait le gaz avant les hommes. On déploie la nouvelle version sur une petite partie de l'infrastructure, qui reçoit une petite part du trafic (1 %, 5 %, 10 %). On compare ses indicateurs (taux d'erreurs, temps de réponse) à ceux de l'ancienne version. Si tout va bien, on augmente progressivement la part (25 %, 50 %, 100 %) ; sinon, on retire le canari, et seule une petite partie des utilisateurs a été touchée.
Avec Nginx, des poids sur les serveurs de l'upstream suffisent pour un premier canari :
upstream sorbier_frais {
server 127.0.0.1:3001 weight=9; # ancienne version : 9 requêtes sur 10
server 127.0.0.1:3002 weight=1; # canari : 1 requête sur 10, soit 10 %
}
- Avantage : le risque est limité à une fraction des utilisateurs, et la décision repose sur des mesures réelles.
- Inconvénient : il faut une supervision fine, capable de comparer les deux versions, et un routage du trafic pondéré ; les deux versions coexistent longtemps.
- Quand : des applications à fort trafic, où les mesures sont significatives. Les outils comme Argo Rollouts (Kubernetes) automatisent les paliers et le retour arrière selon les indicateurs.
Comparer les stratégies
| Stratégie | Coupure | Ressources en plus | Versions simultanées | Vitesse du retour arrière | Complexité |
|---|---|---|---|---|---|
| Recréation | Oui, courte | Aucune | Non | Lente (redéploiement) | Très faible |
| Progressive | Non | Faibles (une instance de plus) | Oui, pendant le déploiement | Moyenne | Moyenne |
| Bleu-vert | Non | Un environnement complet | Non (bascule franche) | Immédiate | Moyenne |
| Canari | Non | Faibles | Oui, longtemps | Rapide (retrait du canari) | Élevée (supervision, routage) |
Les interrupteurs de fonctionnalité
Un interrupteur de fonctionnalité (feature flag, feature toggle) est une condition dans le code, pilotée par la configuration, qui active ou désactive une fonctionnalité sans redéployer :
if (await drapeaux.estActif('export-pdf', utilisateur)) {
routeur.get('/notes/:id/pdf', exporterPdf);
}
Ils séparent le déploiement de la mise à disposition : le code de l'export PDF part en production désactivé, avec les autres changements ; on l'active ensuite pour l'équipe comptable seulement, puis pour tout le monde. Si un problème apparaît, on coupe l'interrupteur en quelques secondes : c'est un retour arrière de la fonctionnalité, sans toucher au reste.
| Usage | Exemple |
|---|---|
| Lancement progressif | Activer l'export PDF pour 10 % des utilisateurs, puis 100 % |
| Coupe-circuit (kill switch) | Désactiver l'appel au service de géolocalisation s'il est en panne |
| Fusion de code inachevé | Le travail en cours est fusionné tous les jours sur main, mais reste invisible |
| Test A/B | Comparer deux versions d'un écran |
Des outils libres (Unleash, GrowthBook) et le standard ouvert OpenFeature fournissent les interrupteurs, leur interface d'administration et leur historique. Un simple réglage dans la configuration suffit pour commencer. Le revers : chaque interrupteur ajoute un if ; on le supprime du code une fois la fonctionnalité stabilisée, sinon ils s'accumulent en dette technique.
Revenir en arrière : le rollback
Un retour arrière (rollback) remet en service la dernière version qui fonctionnait. Quand la production va mal après un déploiement, la règle est simple : d'abord rétablir le service, ensuite comprendre. On ne débogue pas en direct sur la production.
| Méthode | Comment | Durée | Remarque |
|---|---|---|---|
| Redéployer l'image précédente | deployer.sh sha-3f9c2e1 (ou le workflow ci-dessous) | Une à deux minutes | La méthode de base, possible parce que chaque image est étiquetée et conservée |
| Rebasculer (bleu-vert) | Remettre l'ancien environnement dans le répartiteur | Quelques secondes | L'ancien environnement doit être resté démarré |
| Retirer le canari | Remettre son poids à 0 | Quelques secondes | Seule une partie du trafic a été touchée |
| Couper un interrupteur | Désactiver la fonctionnalité | Quelques secondes | Si le problème est limité à cette fonctionnalité |
| Bouton de la plateforme ou de GitLab | Rollback (PaaS), Re-deploy d'un environnement (GitLab) | Une à deux minutes | Même principe : redéployer un artefact précédent |
git revert puis pipeline | Un commit qui annule le commit fautif, testé et déployé normalement | Le temps du pipeline (10 à 20 minutes) | Plus lent, mais tracé ; à faire après le retour arrière immédiat, pour que main ne contienne plus le défaut |
Un workflow de retour arrière, lancé à la main avec la version voulue :
name: Retour arrière
on:
workflow_dispatch:
inputs:
version:
description: Étiquette de l'image à redéployer, par exemple sha-3f9c2e1
required: true
type: string
environnement:
description: Environnement cible
type: choice
options: [recette, production]
default: production
permissions:
contents: read
jobs:
rollback:
runs-on: ubuntu-latest
environment: ${{ inputs.environnement }}
steps:
- name: Vérifier l'étiquette
env:
VERSION: ${{ inputs.version }}
run: |
[[ "$VERSION" =~ ^(sha-[0-9a-f]{7}|[0-9]+\.[0-9]+\.[0-9]+)$ ]] || { echo "Étiquette invalide"; exit 1; }
- name: Préparer la connexion SSH
env:
SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
KNOWN_HOSTS: ${{ vars.DEPLOY_KNOWN_HOSTS }}
run: |
install -m 700 -d ~/.ssh
printf '%s\n' "$SSH_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
printf '%s\n' "$KNOWN_HOSTS" > ~/.ssh/known_hosts
- name: Redéployer
env:
VERSION: ${{ inputs.version }}
DEPLOY_HOST: ${{ vars.DEPLOY_HOST }}
run: ssh "deploy@$DEPLOY_HOST" "MIGRER=non /opt/sorbier-frais/deployer.sh $VERSION"
MIGRER=non dit au script de ne pas lancer les migrations : l'ancienne version ne connaît pas les migrations les plus récentes, déjà appliquées, et certains outils (Knex, par exemple) refusent alors de s'exécuter, ce qui ferait échouer le retour arrière lui-même. L'environnement production garde ses règles : un retour arrière en production demande aussi une approbation. La valeur saisie passe par une variable d'environnement et est vérifiée avant usage, comme toute donnée fournie par une personne (l'injection de script).
Et la base de données ? Revenir à l'ancien code est facile ; revenir à l'ancien schéma l'est beaucoup moins. Les migrations « descendantes » (down) qui suppriment une colonne détruisent les données écrites entre-temps. D'où trois règles : des migrations compatibles avec la version précédente (expansion, puis contraction), une sauvegarde avant chaque migration en production, et la restauration de cette sauvegarde seulement en dernier recours, en sachant qu'elle efface tout ce qui a été saisi depuis (sauvegarde et PRA).
Après l'incident : le post-mortem
Une fois le service rétabli, l'équipe écrit un court post-mortem : la chronologie (déploiement à 14 h 02, premières erreurs à 14 h 05, retour arrière à 14 h 11), l'impact (combien d'utilisateurs, combien de temps), la cause, et surtout les actions pour que cela ne se reproduise pas : un test ajouté, un contrôle de santé plus complet, une étape de pipeline en plus. Il est sans reproche (blameless) : on cherche ce qui, dans le processus, a laissé passer l'erreur, pas un coupable. C'est la même démarche que la gestion des incidents d'ITIL (gestion des incidents) et que le retour d'expérience après un incident de sécurité (réponse aux incidents).
Exercices
Exercice 1 sur 4 Choisir une stratégie Réussi À revoir
Quelle stratégie de déploiement conseilles-tu dans chaque cas ? Justifie.
- L'application de réservation de salles d'un lycée, utilisée de 8 h à 18 h, sur un seul serveur.
- Le site marchand d'une enseigne, qui ne peut pas se permettre une seconde de coupure et veut pouvoir revenir en arrière instantanément ; elle dispose de deux serveurs identiques.
- Une application mobile bancaire avec deux millions d'utilisateurs, dont l'équipe veut vérifier sur de vraies mesures qu'une nouvelle version ne dégrade rien.
- Une API qui tourne sur un cluster Kubernetes avec six répliques.
Voir la réponseMasquer la réponse de l'exercice 1
- Recréation, le soir ou tôt le matin : quelques secondes de coupure hors des heures d'utilisation ne gênent personne, et c'est la stratégie la plus simple.
- Bleu-vert : un serveur sert le trafic, l'autre reçoit la nouvelle version ; la bascule et le retour arrière sont instantanés. Condition : des migrations compatibles avec les deux versions.
- Canari : une petite part du trafic d'abord, avec comparaison des taux d'erreurs et des temps de réponse ; avec deux millions d'utilisateurs, 1 % représente 20 000 personnes, assez pour des mesures fiables.
- Progressive (rolling update), la stratégie par défaut d'un Deployment Kubernetes : les six répliques sont remplacées par petits groupes, sans coupure.
Tu avais trouvé ?
Exercice 2 sur 4 Les poids d'un canari Réussi À revoir
- Avec
weight=9pour l'ancienne version etweight=1pour le canari, quelle part du trafic reçoit le canari ? Sur 2 000 requêtes, combien en reçoit-il ? - Le canari renvoie une erreur sur 3 % de ses requêtes, l'ancienne version sur 0,2 %. Combien d'erreurs chacune produit-elle sur ces 2 000 requêtes ? Que décides-tu ?
- L'équipe préfère quatre instances de l'ancienne version et une instance canari, toutes de poids 1. Quelle part reçoit le canari ?
Voir la réponseMasquer la réponse de l'exercice 2
- 1 / (9 + 1) = 10 %, soit 2 000 × 0,10 = 200 requêtes.
- Canari : 200 × 0,03 = 6 erreurs. Ancienne version : 1 800 × 0,002 = 3,6 erreurs en moyenne. En nombre, l'écart paraît faible, mais le taux du canari est 15 fois plus élevé (3 % contre 0,2 %) : on retire le canari (poids 0) et on analyse ses journaux avant toute nouvelle tentative.
- 1 / (4 + 1) = 20 %. Pour un premier palier, c'est beaucoup ; des poids (par exemple 19 et 1, soit 5 %) permettent un départ plus prudent.
Tu avais trouvé ?
Exercice 3 sur 4 Remettre le retour arrière dans l'ordre Réussi À revoir
À 14 h 05, après le déploiement de sha-b7e21f4 en production, la supervision signale que 40 % des enregistrements de notes de frais échouent. Remets ces actions dans l'ordre :
a. Écrire le post-mortem et ajouter un test qui reproduit le problème.
b. Lancer le workflow « Retour arrière » avec sha-3f9c2e1.
c. Ouvrir une pull request avec git revert du commit fautif, ou avec un correctif.
d. Vérifier que le taux d'erreurs revient à la normale.
e. Prévenir les utilisateurs et l'équipe qu'un incident est en cours.
f. Analyser les journaux de la version sha-b7e21f4 pour trouver la cause.
Voir la réponseMasquer la réponse de l'exercice 3
e, b, d, f, c, a.
On prévient (e) et on rétablit le service tout de suite (b), sans chercher la cause d'abord. On vérifie que le retour arrière a fonctionné (d). Ensuite seulement, on analyse calmement (f), on corrige dans main par une pull request testée (c), et on tire les leçons (a). Prévenir et rétablir peuvent se faire en parallèle si deux personnes sont disponibles ; dans tous les cas, l'analyse attend que les utilisateurs ne soient plus bloqués.
Tu avais trouvé ?
Exercice 4 sur 4 Interrupteur ou retour arrière ? Réussi À revoir
La version 2.6 de sorbier-frais contient trois changements : une correction de calcul des indemnités, une nouvelle page de statistiques, et l'export PDF, livré derrière l'interrupteur export-pdf, activé pour le service comptable. Le lendemain, l'export PDF fait planter le serveur quand une note contient plus de 50 lignes. Que fais-tu, et pourquoi ne fais-tu pas un retour arrière vers la 2.5 ?
Voir la réponseMasquer la réponse de l'exercice 4
On coupe l'interrupteur export-pdf : la fonctionnalité fautive disparaît en quelques secondes, sans redéploiement. Un retour arrière vers la 2.5 retirerait aussi la correction du calcul des indemnités et la page de statistiques, qui fonctionnent. Ensuite, on corrige l'export dans une pull request (avec un test sur une note de plus de 50 lignes), on déploie une 2.6.1, et on réactive l'interrupteur pour le service comptable.
Tu avais trouvé ?