DevOps, CI/CD et conteneurs
Pipelines de livraison continue : étapes, artefacts et stratégies de déploiement
Intermédiaire11 min de lectureMis à jour
Cette page a été traduite de l'anglais avec l'aide de l'IA, puis vérifiée par rapport à l'original. Lire la version anglaise
Un pipeline de déploiement est le chemin automatisé qui mène d'un commit à une release en production, chaque étape apportant une confiance supplémentaire dans le changement. Ce guide explique comment concevoir les étapes, pourquoi on construit un artefact une seule fois avant de le promouvoir d'environnement en environnement, comment versionner les releases et faire évoluer un schéma de base de données sans interruption, et quand choisir un déploiement rolling, blue-green ou canary.
Ce que vous allez apprendre
- Distinguer intégration continue, livraison continue et déploiement continu
- Concevoir un pipeline qui construit l'artefact une seule fois et promeut ce même artefact d'environnement en environnement
- Versionner les artefacts avec le versionnage sémantique et les stocker dans un dépôt d'artefacts
- Appliquer des migrations de base de données expand-and-contract qui restent compatibles avec la version en cours d'exécution
- Choisir entre déploiement rolling, blue-green et canary, et prévoir le rollback
L'intégration continue prouve que le code compile et que ses tests passent. C'est nécessaire, mais très loin d'être suffisant pour une release : l'artefact packagé doit encore être configuré pour un environnement, déployé à côté d'une base de données dont le schéma devra peut-être évoluer, vérifié face aux vraies dépendances, puis basculé sous trafic réel sans perdre de requêtes. Un pipeline de déploiement automatise ce chemin du commit à la production, chaque étape apportant une preuve supplémentaire que le changement est sûr. La livraison continue, c'est l'état dans lequel ce pipeline inspire suffisamment confiance pour que n'importe quel build vert puisse partir en production d'une simple pression sur un bouton ; le déploiement continu, c'est quand on retire le bouton. Ce guide porte sur la conception de ce pipeline.
Livraison, déploiement et définition de « livrable »
Trois termes sont souvent confondus :
- Intégration continue — chaque merge déclenche automatiquement un build et les tests.
- Livraison continue — chaque build qui passe le pipeline est packagé, versionné et vérifié dans des environnements proches de la production, si bien qu'il peut partir en production à tout moment sur décision manuelle.
- Déploiement continu — chaque build qui passe part en production automatiquement.
L'écart entre le deuxième et le troisième relève d'un choix métier, pas d'un choix technique. Ce qui n'est pas négociable, c'est le rôle du pipeline : montrer, pour chaque commit, s'il est livrable, et faire de la mise en production une action de routine plutôt qu'un événement. Si une release passe encore par un tableur d'étapes manuelles et un week-end sacrifié, vous avez un serveur de CI, pas de la livraison continue.
Les étapes d'un pipeline
Un pipeline fait passer un même changement par une série d'étapes qui troquent de la vitesse contre de la confiance. Voici une séquence représentative pour un service backend :
| Étape | Environnement | Rôle | Validation |
|---|---|---|---|
| Commit | Runner de CI | Compilation, tests unitaires, analyse statique, packaging, publication de l'artefact | Automatique |
| Intégration | Runner de CI avec conteneurs | Tests contre une vraie base de données, un vrai broker et les contrats des services dépendants | Automatique |
| Acceptation | Environnement de test dédié, déployé à partir de l'artefact | Tests fonctionnels de bout en bout, scans de sécurité | Automatique |
| Staging / préproduction | Dimensionnement et forme des données proches de la production | Tests de performance, smoke tests, tests exploratoires manuels si besoin | Automatique ou approbation manuelle |
| Production | Environnement réel | Déploiement progressif, vérification de santé, rollback en cas d'échec | Approbation manuelle (livraison) ou automatique (déploiement) |
Deux propriétés comptent davantage que la liste exacte. D'abord, les étapes s'exécutent dans l'ordre, en mode fail-fast : un échec à l'étape de commit empêche tout ce qui suit de s'exécuter, si bien que les échecs peu coûteux sont signalés en quelques minutes et que les environnements coûteux ne sont pas gaspillés. Ensuite, chaque étape après la première travaille sur le même artefact, déployé avec la même automatisation que celle utilisée en production. Déployer dans l'environnement d'acceptation avec le script de déploiement de production, c'est précisément tester ce script.
Construire une fois, promouvoir partout
La règle qui conditionne tout le reste : construire l'artefact une seule fois, puis le promouvoir. L'étape de commit produit un jar, une image de conteneur ou une archive zip de fichiers statiques — avec une version unique — et l'envoie dans un dépôt d'artefacts. Les étapes suivantes récupèrent cet artefact précis par sa version et le déploient. Rien n'est recompilé.
Ce qui en découle :
- L'artefact ne doit contenir aucune valeur propre à un environnement. Les URL de base de données, les identifiants, les feature flags et les noms d'hôte sont injectés au moment du déploiement via des variables d'environnement, des fichiers de configuration montés ou un service de configuration. C'est exactement le principe « config » de l'application twelve-factor.
- L'artefact a besoin d'un emplacement stable : Sonatype Nexus, JFrog Artifactory, GitHub Packages, ou un registre de conteneurs comme Harbor ou Amazon ECR. Le dépôt fait autorité : il dit ce qui existe et ce qui a été déployé, et où.
- L'artefact doit être immuable. Republier la version
2.3.1avec un contenu différent, c'est mentir à tous les environnements qui l'ont déjà récupérée. Les registres de conteneurs le garantissent avec les digests (sha256:…), les dépôts d'artefacts avec des dépôts « release » qui refusent l'écrasement. - La traçabilité devient triviale : une version correspond à un commit, à un numéro de build et à un ensemble de déploiements.
Versionnage
Choisissez un schéma et appliquez-le mécaniquement. Deux dominent.
Le versionnage sémantique (MAJOR.MINOR.PATCH) exprime la compatibilité : un patch corrige des bugs, une mineure ajoute des fonctionnalités rétrocompatibles, une majeure casse la compatibilité. C'est le bon choix pour les bibliothèques et pour toute API dont dépendent d'autres équipes. Les préversions portent un suffixe — 2.4.0-rc.1 — et les métadonnées de build un suffixe introduit par +.
Les versions fondées sur le numéro de build ou le commit (1.0.437, 2026.09.07-a1b2c3d) conviennent aux services qui sont uniquement déployés, jamais consommés comme dépendance. La version répond à « de quel commit s'agit-il ? » plutôt qu'à « qu'est-ce qu'elle casse ? ».
Quel que soit le schéma, c'est le pipeline qui attribue la version, pas l'éditeur de texte d'un développeur. Avec Maven, cela revient à retirer -SNAPSHOT au moment de la release avec le release plugin, versions:set ou la propriété CI-friendly ${revision} ; pour les conteneurs, cela revient à taguer l'image avec la version et à inscrire le digest dans le manifeste de déploiement.
# CI-friendly Maven versioning: the pipeline supplies the revision
mvn -B -Drevision=1.4.$BUILD_NUMBER deploy
# Tag the image twice: a human-readable version and the commit
docker build -t registry.example.com/shop/orders:1.4.$BUILD_NUMBER \
-t registry.example.com/shop/orders:$GIT_COMMIT .
docker push --all-tags registry.example.com/shop/orders
Migrations de base de données
Les bases de données sont la partie la plus difficile de la livraison continue, car un schéma, contrairement à un conteneur, ne se remplace pas simplement. Deux outils dominent dans l'écosystème Java — Flyway (scripts SQL versionnés) et Liquibase (changelogs en XML, YAML ou SQL) — et tous deux fonctionnent de la même manière : les scripts de migration sont versionnés à côté du code, chacun porte une version, l'outil consigne ceux qui ont été appliqués dans une table de métadonnées et, au démarrage ou lors d'une étape du pipeline, applique dans l'ordre ceux qui manquent.
-- src/main/resources/db/migration/V12__add_order_channel.sql
ALTER TABLE orders ADD COLUMN channel VARCHAR(20);
UPDATE orders SET channel = 'web' WHERE channel IS NULL;
La discipline qui rend les migrations sûres s'appelle expand and contract. Une modification de schéma que la version précédente du code ne supporte pas casse les déploiements rolling (anciennes et nouvelles instances tournent en même temps) et rend le rollback impossible. Découpez donc chaque changement incompatible en étapes compatibles :
Étendre
Ajoutez la nouvelle colonne, table ou index sans rien supprimer. La version en cours d'exécution l'ignore.Déployer un code qui écrit dans les deux
La nouvelle version écrit dans l'ancienne et la nouvelle structure, et lit dans l'ancienne. Le rollback est sans danger : l'ancien code trouve toujours tout ce dont il a besoin.Migrer l'historique
Une migration ou un batch recopie les données historiques dans la nouvelle structure.Déployer un code qui lit la nouvelle structure
Désormais, plus rien ne dépend de l'ancienne colonne, hormis la double écriture.Contracter
Dans une release ultérieure, cessez d'écrire dans l'ancienne structure et supprimez-la.
Cela demande plus de releases qu'un simple ALTER TABLE ... RENAME, et c'est précisément le but : chaque release est petite, compatible avec ses voisines et réversible.
Stratégies de déploiement
Une fois l'artefact et le schéma prêts, la dernière étape consiste à basculer le trafic. Les stratégies diffèrent par leur coût en capacité, leur exposition et la rapidité du rollback.
Recreate arrête l'ancienne version, puis démarre la nouvelle. C'est simple, et c'est la seule option quand deux versions ne peuvent réellement pas coexister, mais cela implique une interruption de service. Acceptable pour des traitements batch internes, pas pour une API publique.
Rolling remplace les instances quelques-unes à la fois — c'est le comportement par défaut des Deployments Kubernetes, piloté par maxSurge et maxUnavailable. Pas d'interruption ni de capacité supplémentaire, mais l'ancienne et la nouvelle version servent du trafic simultanément pendant toute la durée du déploiement : le changement doit donc être compatible dans les deux sens (ce que garantit la discipline expand-and-contract).
# Deployment excerpt: rolling update that never drops below full capacity
spec:
replicas: 6
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2 # up to 8 pods during the rollout
maxUnavailable: 0 # never fewer than 6 ready pods
template:
spec:
containers:
- name: orders
image: registry.example.com/shop/orders@sha256:3f1c… # immutable reference
readinessProbe:
httpGet: { path: /actuator/health/readiness, port: 8080 }
C'est la readiness probe qui rend le rolling sûr : Kubernetes n'envoie du trafic à un nouveau pod qu'une fois sa sonde passée au vert, et ne retire un ancien pod que lorsque suffisamment de nouveaux sont prêts.
Blue-green fait tourner deux environnements complets. Blue sert la production ; green reçoit la nouvelle version, passe les smoke tests, puis le routeur ou le load balancer bascule tout le trafic vers green. Le rollback consiste à rebasculer. Le prix à payer : une capacité doublée pendant la bascule et une base de données partagée par les deux couleurs, ce qui exige là encore des changements de schéma compatibles.
Canary envoie un faible pourcentage du trafic (1 %, puis 10 %, puis 50 %) vers la nouvelle version en surveillant le taux d'erreur et la latence, puis poursuit ou interrompt le déploiement automatiquement. C'est la stratégie la moins risquée pour les services exposés aux utilisateurs, mais elle exige de bonnes métriques et une couche de répartition du trafic — un service mesh, un ingress controller avec routage pondéré, ou un outil comme Argo Rollouts ou Flagger.
Les feature flags sont orthogonaux : le code est déployé pour tout le monde, mais la fonctionnalité reste désactivée jusqu'à ce qu'un flag l'active pour une cohorte. Les flags découplent le déploiement de la mise à disposition et permettent un « rollback » instantané en basculant le flag, au prix de chemins de code morts qu'il faudra tôt ou tard nettoyer.
Rollback et vérification
Tout pipeline doit pouvoir répondre à la question « que se passe-t-il quand la production est cassée ? » en quelques minutes, sans cellule de crise.
- Faire un roll forward en redéployant l'artefact précédent. Comme les artefacts sont immuables et versionnés, la version précédente est une entrée connue et saine pour la même étape de déploiement.
kubectl rollout undofait exactement cela pour un Deployment ; en blue-green, c'est un changement au niveau du routeur. - Ne jamais faire de rollback de la base de données. Avec expand-and-contract, le code précédent fonctionne avec le nouveau schéma ; une « down migration » sur des données de production est bien plus risquée que le bug auquel vous cherchez à échapper.
- Automatiser le contrôle de santé après le déploiement. Un smoke test qui appelle quelques endpoints, puis une courte période d'observation du taux d'erreur, interceptent la plupart des mauvaises releases avant qu'un utilisateur ne les signale. Argo Rollouts et Flagger rendent l'interruption automatique ; un pipeline plus simple peut exécuter un script et faire échouer l'étape.
Approbations et conformité
Les environnements réglementés exigent souvent un approbateur distinct, une piste d'audit et un enregistrement de changement. Un pipeline y répond mieux qu'une réunion : l'étape input d'un pipeline Jenkins ou une règle de protection d'environnement dans GitHub enregistre qui a approuvé quoi et quand, la version de l'artefact et le commit figurent dans les logs, et le script de déploiement est lui-même versionné et soumis à revue. Ce dont les auditeurs ont besoin, c'est d'une preuve de contrôle, et un pipeline automatisé en produit bien plus que n'importe quel processus manuel.
Erreurs fréquentes
- Des builds propres à chaque environnement. Un
mvn package -Pprodqui fige les URL de production dans le jar signifie que le staging a testé autre chose. Externalisez la configuration. - Des artefacts snapshot en production. Une
1.4-SNAPSHOTpeut changer à votre insu entre le staging et la production. Uniquement des versions release. - Des étapes manuelles cachées dans le pipeline. Une étape qui dit « exécuter le script SQL joint au ticket » n'est pas automatisée. Si un humain doit faire quelque chose, le pipeline doit le faire à sa place et le consigner.
- Tester le déploiement pour la première fois en production. Déployez dans chaque environnement en amont avec l'automatisation de production. Les scripts de déploiement ont eux aussi des bugs.
- Compter sur les down migrations pour revenir en arrière. Elles sont rarement testées et souvent destructrices. Concevez plutôt des changements de schéma compatibles avec les versions suivantes.
- Déployer en rolling sans readiness checks. Une mise à jour rolling où chaque pod se déclare prêt dès le démarrage du processus sert des erreurs depuis des instances qui n'ont pas fini leur montée en charge. Branchez la readiness probe sur quelque chose de significatif.
- Considérer le pipeline comme terminé. Le lead time s'allonge insidieusement à mesure qu'on ajoute des étapes. Mesurez le délai du commit à la production et éliminez les temps d'attente.
Points clés à retenir
- Un pipeline de déploiement est la séquence ordonnée et automatisée d'étapes qui prouve que chaque commit est livrable ; la livraison continue, c'est disposer de ce pipeline, le déploiement continu, c'est le laisser mettre en production sans demander.
- Construisez l'artefact une seule fois, versionnez-le, stockez-le de façon immuable et promouvez les mêmes octets dans chaque environnement, la configuration étant injectée au déploiement.
- Attribuez les versions dans le pipeline : versionnage sémantique pour tout ce dont d'autres dépendent, versions fondées sur le build ou le commit pour ce qui est simplement déployé.
- Appliquez les changements de base de données sous forme de migrations versionnées, en étapes expand-and-contract, pour que deux releases consécutives soient compatibles dans les deux sens et qu'un rollback ne touche jamais au schéma.
- Choisissez la stratégie de déploiement selon le risque et la capacité : rolling pour la plupart des services, blue-green pour une bascule et un rollback instantanés, canary quand les métriques permettent de juger une fraction du trafic.
- Un rollback, c'est redéployer l'artefact précédent en quelques minutes ; vérifiez automatiquement chaque déploiement avec des smoke tests et une surveillance du taux d'erreur.
Sources et lectures complémentaires
Questions fréquentes
- Quelle est la différence entre livraison continue et déploiement continu ?
- La livraison continue signifie que chaque changement qui passe le pipeline est prouvé déployable et peut partir en production en une seule action, mais c'est un humain qui décide du moment. Le déploiement continu supprime cette décision : chaque build vert est mis en production automatiquement. La livraison est un prérequis du déploiement ; beaucoup d'équipes soumises à une réglementation ou exposées aux clients s'arrêtent volontairement à la livraison pour pouvoir choisir le moment des mises en production.
- Pourquoi ne faut-il pas reconstruire l'application pour chaque environnement ?
- Parce que l'artefact testé en staging serait alors différent de celui qui tourne en production : une autre exécution du compilateur, une résolution des dépendances potentiellement différente, et toute valeur propre à l'environnement figée dedans. Construisez un seul artefact, stockez-le avec une version et injectez les différences entre environnements au moment du déploiement, par la configuration. Un passage au vert en staging devient alors une preuve portant sur les octets exacts qui partent en production.
- Comment déployer une modification de base de données sans interruption de service ?
- Découpez-la en étapes rétrocompatibles. Ajoutez d'abord la nouvelle colonne ou table, déployez un code qui écrit dans l'ancienne et la nouvelle structure, migrez les données existantes, déployez un code qui ne lit plus que dans la nouvelle structure, puis supprimez l'ancienne dans une release ultérieure. Chaque déploiement reste compatible avec la version précédente du code, si bien qu'un rollback n'exige jamais de rollback du schéma.
- Quand une canary release est-elle préférable au blue-green ?
- Optez pour un canary quand vous pouvez observer le taux d'erreur et la latence de la nouvelle version sur une fraction du trafic réel et que vous voulez augmenter le risque progressivement. Le blue-green est plus simple et offre une bascule et un rollback instantanés, mais il expose tous les utilisateurs d'un coup et exige le double de capacité pendant la bascule. Si vos métriques ne sont pas assez fiables pour juger un canary, un blue-green avec rollback rapide est le choix le plus sûr.