Stratégie de déploiement Blue/Green

Comment réussir sa stratégie de déploiement sans peine ?

Stratégie de déploiement Blue/Green

Nous trouvons dans la littérature beaucoup d'articles qui mettent en avant la définition du Blue/Green ou qui expliquent d'une manière très succincte l'implémentation d'un service « hello world » déconnectée de la réalité du terrain. L'objectif de cet article est de mettre en évidence les éléments à identifier pour réussir efficacement cette stratégie.

Mais avant de rentrer dans le vif du sujet, reprenons une définition type du mode Blue/Green :

Le déploiement blue/green stipule que la version B (green) est déployée à côté de la version A (blue) avec le même nombre d'instances. Après avoir testé que la version B répond à toutes les exigences, le trafic est basculé de la version A vers la version B.

N.B. : Que veut dire « répondre à toutes les exigences » ? Je reviendrai sur cette hypothèse plus bas.

Il est certain que l'objectif du B/G est d'assurer une continuité de service, cependant, toutes les stratégies de déploiement, hormis le « recreate », garantissent cette continuité. Dans cet article, je ne vais pas donner le détail de toutes les stratégies ni leurs cas d'utilisation que j'aborderai ultérieurement dans un autre billet.

La clé de réussite réside dans la collaboration et l'implication de toute l'équipe : métier, dev et ops. Cette équipe doit d'abord se pencher sur la conception d'un tel déploiement afin de définir un processus complet répondant à leurs attentes.


Ci-après quelques points majeurs à aborder par l'équipe pour établir une démarche viable autour du B/G :

Périmètre du B/G

Prenons l'exemple d'une application regroupant plusieurs composants : Répartiteurs de charge, base de données, cache, stockage de fichier, frontend et backend. L'équipe ne doit pas traiter ces composants dans un même et unique pipeline sous aucun prétexte.

Il est vrai que la définition évoque « le même nombre d'instances » et peut porter à confusion. Cependant, ce nombre d'instances est lié à la version d'un composant et non pas à la totalité des composants ni à l'environnement dans sa globalité.

N.B. : Ne pas confondre composant et instances de composant. Si un composant est déployé en plusieurs instances, le pipeline doit impacter toutes les instances de ce même composant.

Le fait de dupliquer la totalité de l'environnement mène à une complexité ingérable voire à une désynchronisation des données et forcément à une interruption de service. En conséquence, c'est un anti-pattern de mélanger les concepts dans un même pipeline et il est fortement recommandé de fuire cette mauvaise pratique.

💡
Faut-il dupliquer le cluster Kubernetes pour mettre en place cette stratégie de déploiement ? A cette question, la réponse est de toute évidence NON ; c'est une approche totalement rédhibitoire.

Par ailleurs, certains composants n'exigent pas du tout ce type de stratégie. Par exemple, la mise à jour du frontend ne requiert pas du B/G et n'implique pas une migration de base de données non plus. Idem pour le backend, qui nécessite une mise à jour potentielle du schéma mais en aucun cas, une migration de base de données (passage de PostgreSQL v12 à v14). Donc il est inutile de mélanger les topologies dans un même pipeline. Cela s'applique également à toutes les stratégies et non uniquement au B/G.

Opter pour un pipeline par topologie facilite grandement la mise en place et le déploiement. Ainsi, l'équipe peut adopter la bonne stratégie de déploiement pour chaque composant. Exemple, un pipeline pour la migration de base de données en mode B/G ou RollingUpdate et un autre pour le backend en mode Canary.

Phase initiale vs Phase de mise à jour

Est-ce qu'il faut un seul pipeline pour les deux phases ? L'équipe doit prendre une décision qui dépend fortement des outils mis à disposition et de la technologie utilisée.

Il est indispensable de pouvoir distinguer facilement entre les environnements ou les namespaces. Tout dépend si le déploiement est en mode VM ou Conteneurisé par exemple.

De plus, Il faut pouvoir détecter l'existence ou non d'un déploiement préalable et de trouver le moyen facile de mettre à jour le statut final à la fin de l'exécution du pipeline.

Sur un projet, je me basais sur les adresses de mes machines dans la configuration de mon HAProxy - haproxy.cfg - afin de détecter les serveurs applicatifs; sur un autre projet, un simple fichier YAML regroupait les informations utiles au déploiement.

Rétrocompatibilité du système de persistance

Un élément très important, sans lequel aucune stratégie ne peut réussir, concerne le système de persistance : schéma de base de données, structure de fichiers, gestion des propriétés ou structure des bus événementiels (topics)...

Tout changement modifiant la structure des données mettra en péril le retour arrière en cas d'erreur; l'ancienne version n'étant plus compatible avec la nouvelle version. D'où la nécessité de définir un processus de rétrocompatibilité détaillant la gestion de suppression et/ou de modification de la structure en question.

En cas de suppression, par exemple, l'équipe optera pour une suppression logique impliquant uniquement le code de la nouvelle version, puis une suppression physique quelques versions plus tard.

Le métier et les devs doivent respecter minutieusement ce processus, et c'est pour cette raison, j'insiste toujours sur l'utilité de la collaboration entre le métier, les devs et les ops.

Gestion des sessions

L'objectif d'une stratégie de déploiement est la continuité de service, par conséquent, la bascule d'une version vers une autre ne doit pas entraîner la déconnexion des utilisateurs.

D'où la nécessité de sauvegarder la session ou les informations de connexion de manière transparente et indépendante qui n'impactera pas les utilisateurs en cas de bascule.

Par exemple, les données de session peuvent être stockées dans un cache type redis ou dans une base de données.

Décommissionner l'environnement Blue

L'équipe doit décider à quel moment l'ancienne version (blue) est à supprimer et surtout comment y procéder. Le fait que la définition évoque la validation des exigences, il est convenable de les définir et de décider quel moyen et/ou quel outil utiliser pour les valider.

💡
Le décommissionnement peut être fait automatiquement à la fin de la recette métier, manuellement en cliquant sur un bouton, par événement à la clôture d'un ticket ou après un temps défini qui mettra un terme au pipeline, etc...

Une fois le décommissionnement est terminé, la version Green deviendra alors la version Blue et le retour arrière vers l'ancienne version ne sera plus possible que par le lancement d'un nouveau déploiement.

A noter que la plupart des projets ne possèdent pas une couverture de tests fonctionnels suffisante et dans la plupart du temps, les recettes métiers sont manuelles. Par conséquent, les Ops ne peuvent pas prendre cette décision de manière unilatérale.

Retour arrière en cas d'erreur

Le retour arrière en cas d'erreur, en rebasculant le trafic vers la version A, n'est possible que si les deux environnements sont toujours actifs.

L'équipe doit préciser la manière de décommissionner le Green pour rebasculer vers le Blue, le temps d'apporter une correction ou une amélioration de la nouvelle version.

💡
Le retour arrière peut être fait automatiquement à la détection d'une erreur, manuellement en cliquant sur un bouton, par événement à l'échec de la recette métier ou après un temps de non confirmation de la fin du pipeline, etc...

Conclusion

Cette liste non exhaustive des points à élucider avant d'entamer l'écriture d'un pipeline est primordiale voire obligatoire. Sans oublier l'étroite collaboration entre le métier, les devs et les ops pour définir les exigences attendues et évaluer la nécessité d'un Blue/Green et ce, composant par composant selon leur contexte et leur topologie.