1. Mon serveur s’arrête à chaque déploiement, quel est le problème ?

Lorsque je gère des projets personnels, je me retrouve souvent sur des environnements aux ressources limitées (instances micro de GCP, Raspberry Pi, etc.). J’ai plusieurs machines en service : des serveurs puissants pour l’inférence et l’entraînement d’IA, ainsi que de petites VM qui ne font que tourner un serveur DNS. Le Raspberry Pi 5 a une place particulière pour moi : il consomme peu d’électricité même en fonctionnement continu et offre✔ des performances solides. Si les autres serveurs me donnent l’impression d’être du bétail à surveiller, le Pi ressemble plutôt à un animal de compagnie auquel on s’attache.

Mais en surchargeant cet « animal », le CPU atteint 100 % lors du déploiement à cause du Celery Worker. Lorsque les deux groupes Blue et Green sont démarrés simultanément pour un déploiement sans interruption, le nombre de workers double, ce qui dépasse les capacités du système. Réduire le nombre de workers ralentit le traitement, mais le laisser tel quel provoque des plantages : un vrai dilemme.

Illustration d’un script d’automatisation sur un PC low‑spec

Pour résoudre ce problème, j’ai créé un script de déploiement Blue‑Green personnalisé qui minimise la consommation de ressources tout en garantissant la stabilité.


2. Stratégie de résolution : économiser les ressources, augmenter la fiabilité

Un déploiement Blue‑Green classique lance les deux environnements en même temps, mais j’ai conçu la stratégie suivante pour réduire la charge CPU :

  1. Arrêt anticipé des services en arrière‑plan (Celery) : avant de lancer la nouvelle version du serveur web, on stoppe les workers et beats lourds de l’ancienne version afin de libérer du CPU.
  2. Démarrage par étapes : on déploie d’abord Web + Redis, on effectue les vérifications de santé, puis on ajoute les autres services.
  3. Human‑in‑the‑loop : après l’automatisation, un administrateur confirme visuellement le bon fonctionnement avant de supprimer l’ancienne version.

En analysant les plantages, il apparaît que les workers Celery, dès leur initialisation, reçoivent et exécutent immédiatement plusieurs tâches, ce qui fait exploser le CPU. Diminuer la concurrence du worker aurait pu régler le souci, mais cela aurait ralenti le traitement asynchrone pendant le déploiement.

L’idée qui m’est venue : pendant le redeploiement, suspendre temporairement les workers Celery pour libérer du CPU, puis déployer le nouveau code sans interruption.


3. Exploration du code principal

L’ensemble du script est disponible dans mon dépôt GitHub. Voici quelques parties essentielles.

① Isolation du projet avec Docker Compose

L’option docker compose -p permet de créer deux projets (ou espaces de noms) distincts, blue et green, à partir du même fichier de configuration.

dc() {
  # Définir dynamiquement le nom du projet (-p) pour isoler les environnements
  docker compose -f "$COMPOSE_FILE" "$@"
}

② Vérifications de santé rigoureuses

On ne bascule le trafic vers la nouvelle version que si le service répond correctement.

health_check() {
  # Réessayer jusqu’à 10 fois pour vérifier qu’une requête sur le port renvoie 200 OK
  if curl -fsSIL --max-time "$HEALTH_TIMEOUT" "$url"; then
    ok "Health check passed"
    return 0
  fi
}

③ Gestion des échecs et récupération rapide

Si la nouvelle version pose problème, on relance immédiatement l’ancienne afin que les utilisateurs ne subissent aucune interruption. On utilise stop plutôt que rm -f pour les workers et le beat, ce qui libère rapidement le CPU tout en permettant une reprise rapide en cas d’incident.


4. Astuce d’exploitation : la philosophie « vérifier avant de supprimer »

Le script ne supprime pas automatiquement l’ancienne version ; il affiche un message à l’administrateur :

"Le déploiement a réussi. Connectez‑vous pour vérifier le résultat. S’il n’y a aucun problème, copiez la commande ci‑dessous pour nettoyer l’ancienne version."

Cette petite barrière empêche les 1 % d’erreurs que l’automatisation pourrait manquer.


5. Conclusion

Ce script regroupe toutes les réflexions nécessaires pour obtenir la meilleure efficacité possible avec des ressources limitées. Bien qu’il soit simple, il me satisfait pleinement et je suis convaincu que d’autres développeurs aux contraintes similaires y trouveront leur compte.

Liens utiles :