Dans le cadre de mon emploi chez Stack Labs, j'interviens auprès d'une entreprise qui découvre la conteneurisation et qui veut développer son nouveau système sur Google Cloud Platform. L'un des sujets qui leur importe est la montée de version : comment procéder ?
Parmi leurs exigences, ils souhaitaient minimiser la durée d’interruption du service pendant la montée de version, ainsi que l'interrompre en cas de problème.
Notre proposition : le déploiement en canari. Dans ce billet, je vous présente (très) brièvement de quoi il s'agit, ainsi que la démonstration que j'ai préparée avec un collègue pour montrer à nos clients comment ça fonctionne.
Déploiement en canari ?
Le déploiement en canari consiste, pour un serveur Web, à déployer la nouvelle version du serveur (le « Canari ») en parallèle de l'ancienne (la « version primaire »), et de diriger une partie du trafic sur cette nouvelle version. Si le Canari est jugé conforme aux attentes pour les requêtes traitées, alors la portion du trafic qui lui est assignée augmente progressivement, jusqu'à arriver à un seuil critique : dès lors, la version primaire est reconfigurée pour délivrer la nouvelle version, et tout le trafic lui est affecté ; quant au Canari, les ressources qui lui étaient allouées (p. ex. conteneurs) sont libérées.
Ci-suivent quelques liens pour des explications plus approfondies (et illustrées !) :
- Une explication par Danilo Sato, sur le site de Martin Fowler ;
- Un résumé par Amazon Web Services ;
- Une explication par CodeFresh ;
- Une explication par Isac Souza d’Encora.
Après avoir lu ces pages Web, des questions apparaissent. En tout cas, je m'en suis posé plusieurs. Dans les sous-sections suivantes, je vous les présente, et vous explique mes réponses actuelles.
Le Canari est conforme... ?
Déporter le trafic vers le Canari a pour objectif de vérifier s'il est « conforme » ; certes, mais conforme à quoi ?
Cela doit être défini par l'équipe d'exploitation.
Un critère apparemment fréquent est le code de statut en réponse aux requêtes : par exemple, si un large pourcentage des réponses portent un code HTTP 2xx, alors le déploiement peut se poursuivre, et il doit s'interrompre si les codes HTTP 5xx sont majoritaires. Un autre critère est la latence de réponse : si elle est trop élevée, alors le déploiement doit s'interrompre.
Ces critères sont intégrés nativement à des outils d'automatisation des déploiements en canari (p. ex. Flagger), mais cela peut ne pas suffire : des critères orientés métier peuvent être plus pertinents pour valider la conformité du Canari.
Enfin, notons que ce type de déploiement n'est pas nécessairement automatisé. En effet, les opérateurs peuvent à chaque étape sélectionner une population de testeurs pour interagir avec le Canari, et décider quand passer à la prochaine étape (p. ex. après avoir collecté les avis de la population de testeurs, ou mesuré diverses métriques avec des outils de supervision).
Déploiement d'un logiciel... ou de tout le système ?
Les ressources trouvables en ligne ne sont pas claires quant à ce qu'englobe le déploiement en canari. En effet, si les auteurs parlent du déploiement d'un logiciel, leurs illustrations présentent bien le routage entre deux systèmes indépendants : l'un pour la version primaire, l'autre pour le Canari. Considérant les grandes difficultés techniques qui viennent avec la première option (p. ex. compatibilités entre modules, routage entre composants du système), il me semble plus raisonnable que ce soit la seconde option qui soit réellement mise en œuvre dans l'industrie.
Cependant, cela ne vient pas sans défi.
En effet, le déploiement en canari ne s'étend pas toujours à l'ensemble du système. Je prend l'exemple de l'une de mes expériences professionnelles passées : le système est déployé dans un environnement cloud qui compte un cluster Kubernetes et un SGBD déployé par un PaaS. Dans ce contexte, le déploiement en canari ne concernait que les conteneurs déployés dans Kubernetes : le contenu de la base de données était utilisé concurremment par la version primaire et le Canari. Par conséquent, il était important lorsque le Canari modifiait le schéma de la base de données que les deux versions soient compatibles avec cette modification, au risque de perturber le fonctionnement du système lors du déploiement. Ce point d'attention est soulevé dans plusieurs des liens mentionnés plus haut, tel que l'article de Danilo Sato. C'est un exemple de contraintes sur le développement imposé par une pratique d'exploitation du système.
D'autres préoccupations peuvent également survenir selon la nature des composants du système. Par exemple, l'explication d'Encora indique qu'il faut être vigilant si certains composants possèdent un état (stateful) : dès qu'un utilisateur a été dirigé sur l'une des deux versions, il faut qu'il y soit toujours dirigé au cours du déploiement ; et il peut être nécessaire de conserver l'ancienne version primaire quelque temps après la fin du déploiement le temps que les sessions soient fermées.
Démonstration
Afin de présenter le fonctionnement d'un déploiement en canari à mon client, j'ai préparé une démonstration avec un collègue. Vous pouvez retrouver les fichiers de configuration et les instructions sur le dépôt dans le groupe GitLab de Stack Labs.
L’image ci-dessous (très légèrement adaptée d’une image de la documentation de Flagger) illustre la démonstration.
Nous disposons d'un serveur Web qui affiche une unique page avec un dessin de chameau. Nous le déployons dans Google Kubernetes Engine (GKE). En amont du serveur Web, nous déployons toujours dans GKE un Ingress Controller NGINX : il effectue le routage du trafic vers l'instance primaire ou Canari du serveur Web lors d'un déploiement.
Nous voulons mettre à jour le serveur Web. En effet, alors que le fond de la page est beige (version primaire), nous le voulons à présent vert (Canari).
Pour parvenir à déployer la nouvelle version sans interruption du service, nous utilisons le logiciel Flagger qui automatise le processus de déploiement. Pour valider la conformité du Canari, nous nous concentrons sur les codes de statut HTTP, mais Flagger intègre d'autres critères nativement, et permet également de définir des critères personnalisés, grâce à des requêtes sur Prometheus.
Dès le déploiement lancé, la version avec le fond beige cohabite avec celle au fond vert, et une portion croissante du trafic est dirigée vers cette dernière, comme expliqué précédemment.
Les étapes de la démonstration sont détaillées sur le dépôt Git, je vous invite à les parcourir et à réaliser vous-même la démonstration !
Conclusion
Dans ce billet, je vous ai présenté une stratégie de déploiement en continu des logiciels : le déploiement en canari ; et je vous ai proposé quelques instructions pour le pratiquer par vous-même.
Le déploiement en canari est une solution technique parmi d'autres pour déployer un système en continu. Je vous suggère ci-dessous trois lectures pour approfondir le sujet du déploiement en continu. D'abord, le mémoire de Master de Nichil Strasser, qui évalue les outils de déploiement en canari sur le marché. Puis, deux recommandations qui ouvrent les perspectives sur d'autres techniques de déploiement : un dépôt Git d'exemples sur Kubernetes, et un article de Mahdi Konzali qui les vulgarise. Enfin, nous pouvons élargir l’exigence de faible temps d’interruption de service de notre client à la notion de haute disponibilité. Un article de Endo et coll., publié en 2016, balaye plusieurs définitions de la haute disponibilité ainsi que l’état de l’art des moyens de sa mise en œuvre dans un contexte cloud.
Merci d’avoir lu mon article ! Je suis Antoine, ingénieur cloud & doctorant chez Stack Labs. Si vous voulez en savoir plus sur Stack Labs ou rejoindre une équipe de passionnés de tech, n’hésitez pas à nous contacter ici.
Crédits à Julia Craice sur Unsplash pour l’image de couverture.