Tu as migré ton application sur AWS — React sur CloudFront, Node.js sur EC2 avec Auto Scaling, PostgreSQL sur RDS, Redis sur ElastiCache. L'infrastructure est solide. Mais maintenant arrive la question inévitable : comment déployer sans faire tomber le site ?
Si chaque déploiement signifie quelques secondes (ou minutes) de downtime, tu perds des utilisateurs, la confiance et de l'argent. Le zero-downtime deployment n'est pas un luxe — c'est un standard. Dans cet article, nous explorons deux stratégies de déploiement sans interruption sur AWS (Rolling et Blue/Green), nous les comparons et montrons comment les intégrer avec GitHub Actions ou GitLab CI/CD.
Pourquoi l'application tombe-t-elle lors du déploiement ?
Sur un VPS classique, le déploiement ressemble généralement à ceci : tu te connectes en SSH, tu fais git pull, tu lances npm install, tu redémarres le processus Node.js. Entre l'arrêt de l'ancien processus et le démarrage du nouveau, l'application ne répond plus. Peut-être 5 secondes, peut-être 30 — ça dépend de la durée du build et du démarrage.
Sur AWS avec ALB et Auto Scaling Group, les choses sont différentes. Tu as plusieurs instances EC2 derrière un load balancer. Le truc, c'est de mettre à jour les instances une par une (ou par batches) pour qu'au moins une partie d'entre elles serve le trafic à tout moment. Il existe deux stratégies principales pour ça.
Stratégie 1 : Rolling Deployment
Le rolling deployment met à jour les instances une par une (ou par batches) au sein du même Auto Scaling Group.
Le processus fonctionne ainsi : AWS CodeDeploy récupère la nouvelle version du code et l'envoie à la première instance EC2. L'ALB retire cette instance de la rotation (deregistration), le code est mis à jour, l'app redémarre, puis l'ALB la réajoute une fois le health check passé. Le processus se répète pour chaque instance.
En pratique, si tu as 4 instances, à tout moment au moins 3 servent le trafic. Les utilisateurs ne voient rien.
Avantages : pas besoin de ressources supplémentaires (tu ne doubles pas l'infrastructure), c'est simple à configurer, et le coût reste identique. Inconvénients : le déploiement dure plus longtemps (chaque instance se met à jour séquentiellement), et pendant quelques minutes tu exécutes deux versions de l'app simultanément — il faut s'assurer qu'elles sont compatibles.
Configuration CodeDeploy pour Rolling : dans le deployment group, tu définis le type sur « In-place » et tu sélectionnes l'Auto Scaling Group. Dans « Deployment settings », tu choisis CodeDeployDefault.OneAtATime pour une sécurité maximale ou CodeDeployDefault.HalfAtATime pour la vitesse. L'ALB gère automatiquement la deregistration/registration.
Stratégie 2 : Blue/Green Deployment
Blue/Green est la stratégie premium. Au lieu de mettre à jour les instances existantes, tu crées un ensemble complètement nouveau d'instances (l'environnement « green ») avec la nouvelle version, tu les testes, puis tu bascules tout le trafic de l'ancien ensemble (l'environnement « blue ») vers le nouveau.
Le processus : CodeDeploy crée un nouvel Auto Scaling Group avec des instances qui exécutent la nouvelle version. Les nouvelles instances s'enregistrent sur un Target Group séparé de l'ALB. Une fois que toutes les nouvelles instances passent les health checks, l'ALB redirige le trafic de l'ancien Target Group vers le nouveau — instantanément. Si quelque chose ne va pas, le rollback est un simple switch retour vers le Target Group d'origine.
Avantages : rollback instantané (les anciennes instances tournent encore), tu peux tester l'environnement green avant de basculer le trafic, tu n'exécutes jamais deux versions simultanément. Inconvénients : pendant quelques minutes tu paies double (deux ensembles d'instances tournent en parallèle), et le setup est plus complexe.
Rolling vs. Blue/Green — Quand utiliser quoi ?
Le rolling deployment convient aux applications qui tolèrent l'exécution simultanée de deux versions, aux petites équipes qui veulent de la simplicité, et aux situations où le budget compte (pas de ressources supplémentaires).
Blue/Green est le bon choix pour les applications avec des SLA stricts, quand tu as besoin d'un rollback instantané (sous 1 minute), ou quand tu veux valider manuellement la nouvelle version avant de basculer.
Pour notre app Node.js + PostgreSQL + Redis, la recommandation pratique est de commencer par le rolling deployment. C'est plus simple, moins cher, et couvre 90 % des besoins. Passe à Blue/Green quand tu as une raison concrète — par exemple une migration de base de données qui nécessite des tests avant le cutover.
La pièce centrale : AWS CodeDeploy
Quelle que soit la stratégie, AWS CodeDeploy orchestre le processus de déploiement sur les instances EC2. Tu le configures une fois, puis tu le déclenches depuis GitHub Actions ou GitLab CI/CD.
CodeDeploy utilise un fichier appspec.yml à la racine du projet qui définit ce qui se passe à chaque étape du déploiement :
version: 0.0
os: linux
files:
- source: /
destination: /home/app/myapp
hooks:
BeforeInstall:
- location: scripts/stop_server.sh
timeout: 60
AfterInstall:
- location: scripts/install_dependencies.sh
timeout: 120
ApplicationStart:
- location: scripts/start_server.sh
timeout: 60
ValidateService:
- location: scripts/health_check.sh
timeout: 60
Les scripts font exactement ce qu'on attend : stop_server.sh arrête le processus Node.js (graceful shutdown), install_dependencies.sh exécute npm ci --production, start_server.sh démarre l'app, et health_check.sh vérifie que l'endpoint /health renvoie 200.
Un détail critique : le graceful shutdown. Quand l'ALB retire une instance de la rotation, le paramètre deregistration_delay (par défaut 300 secondes) permet aux requêtes en cours de se terminer. Assure-toi que ton app Node.js traite correctement le signal SIGTERM — finalise les requêtes actives, ferme les connexions DB et Redis, puis s'arrête.
Intégration avec GitHub Actions
Flow complet : push sur la branche main → GitHub Actions exécute les tests → le build est packagé et uploadé sur S3 → CodeDeploy est déclenché → les instances EC2 sont mises à jour.
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [main]
permissions:
id-token: write
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS Credentials (OIDC)
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
aws-region: eu-central-1
- name: Package and upload to S3
run: |
zip -r app-${{ github.sha }}.zip . -x '.git/*'
aws s3 cp app-${{ github.sha }}.zip \
s3://my-deploy-bucket/app-${{ github.sha }}.zip
- name: Trigger CodeDeploy
run: |
aws deploy create-deployment \
--application-name my-app \
--deployment-group-name production \
--s3-location bucket=my-deploy-bucket,key=app-${{ github.sha }}.zip,bundleType=zip \
--description "Deploy ${{ github.sha }}"
Note importante sur l'authentification : l'exemple utilise OIDC (OpenID Connect) au lieu des access keys stockées en secrets. Tu configures un Identity Provider dans IAM qui fait confiance à GitHub, et GitHub Actions reçoit des credentials temporaires à chaque run. Zéro secret à faire tourner, zéro risque de fuite.
Intégration avec GitLab CI/CD
Même logique, syntaxe différente. GitLab CI/CD utilise le fichier .gitlab-ci.yml :
# .gitlab-ci.yml
stages:
- test
- deploy
variables:
AWS_DEFAULT_REGION: eu-central-1
test:
stage: test
image: node:20-alpine
script:
- npm ci
- npm test
deploy_production:
stage: deploy
image: amazon/aws-cli:latest
only:
- main
before_script:
- apt-get update && apt-get install -y zip
script:
- zip -r app-${CI_COMMIT_SHA}.zip . -x '.git/*'
- aws s3 cp app-${CI_COMMIT_SHA}.zip
s3://my-deploy-bucket/app-${CI_COMMIT_SHA}.zip
- aws deploy create-deployment
--application-name my-app
--deployment-group-name production
--s3-location bucket=my-deploy-bucket,key=app-${CI_COMMIT_SHA}.zip,bundleType=zip
--description "Deploy ${CI_COMMIT_SHA}"
environment:
name: production
url: https://myapp.example.com
Pour l'authentification, GitLab supporte aussi OIDC avec AWS. L'alternative est de définir AWS_ACCESS_KEY_ID et AWS_SECRET_ACCESS_KEY comme variables CI/CD protégées dans Settings → CI/CD → Variables.
GitHub Actions vs. GitLab CI/CD — Comparaison rapide
Les deux plateformes font très bien le travail. Les différences pratiques sont minimes : GitHub Actions utilise du YAML avec une structure de jobs et steps, a un marketplace riche avec des actions prédéfinies, et s'intègre nativement si le code est déjà sur GitHub. GitLab CI/CD a un YAML plus compact, propose des environments avec suivi visuel des déploiements, inclut un Container Registry intégré, et est idéal si tu utilises déjà l'écosystème GitLab.
Le choix dépend de l'endroit où vit ton code, pas des capacités CI/CD. Les deux peuvent déclencher CodeDeploy de la même façon.
Checklist avant le premier déploiement
Quelques points à vérifier avant la mise en production. L'endpoint /health dans ton app Node.js doit vérifier la connexion DB et Redis, pas seulement renvoyer 200. Le health check de l'ALB doit être configuré sur cet endpoint, avec un intervalle de 15 secondes et un seuil de 2 health checks. Le graceful shutdown doit être implémenté — l'app doit traiter SIGTERM correctement. Le deregistration_delay sur le Target Group doit être réglé à au moins 30 secondes (par défaut 300 est trop long pour la plupart des apps). Les migrations de base de données doivent être exécutées séparément, avant le déploiement, et doivent être rétrocompatibles. Et last but not least : un mécanisme de rollback automatique doit être configuré — CodeDeploy peut faire un rollback automatique si un déploiement échoue.
Conclusion
Le zero-downtime deployment n'est pas de la rocket science — c'est une combinaison de services AWS correctement configurés (ALB + ASG + CodeDeploy) avec un pipeline CI/CD qui les orchestre. Commence avec le rolling deployment, automatise avec GitHub Actions ou GitLab CI/CD, et ajoute de la complexité (Blue/Green) seulement quand tu en as vraiment besoin.
Le plus important : n'essaie pas de tout faire dès le début. Un rolling deployment qui fonctionne bat un blue/green à moitié configuré chaque jour de la semaine.
Publié sur teninvent.ro — TEN INVENT S.R.L. propose des services d'implémentation CI/CD et d'infrastructure AWS. Contacte-nous pour une évaluation de ton pipeline de déploiement.