[Devoxx FR 2013] Architecting for Continuous Delivery

DevoxxFrance-partenaire2013-200pxLaissez-moi vous raconter une petite histoire…

Tout a commencé il y a environ 2 mois de cela. Sans trop savoir comment, mon équipe et moi nous sommes retrouvés à devoir migrer une application d’une plateforme de production à une autre. Ce déménagement a été l’occasion de revoir nos pratiques de déploiement et de mettre en place plusieurs nouveaux outils pour garantir la constance et la robustesse de nos livraisons.

Maintenant, avance rapide jusqu’au Devoxx FR 2013. En consultant le programme, je m’aperçois qu’une conférence adresse justement la problématique du déploiement logiciel. Piqué au vif et curieux de savoir si notre réflexion était partie dans la bonne direction, je décide d’assister à cette conférence.

Notre intervenant pour cette conférence fut Axel Fontaine, consultant freelance et fondateur/lead developper de Flyway, un framework de migration de bases de données écrit en Java.

Taille vs. fréquence de déploiement. Des paramètres forcément antinomiques ?

La présentation commence par un sondage à main levée sur la fréquence à laquelle nos projets partent en production. Pas de suspense, pas de surprise, la taille des projets déployés est inversement proportionnelle à leur fréquence de livraison.

Pourtant des sites comme Facebook, Flicker, Etsy ou Stack Overflow sont capables de faire des déploiements pluri-journaliers et ces derniers sont loin d’être négligeables en termes de trafic et de données manipulées.

Partant de ce constat, pourquoi n’arriverions-nous pas à appliquer ces méthodes à notre échelle ?

Quelques prérequis

Selon Axel, réussir son processus de Continous Delivery repose tout d’abord sur certains prérequis :

  • Un processus de développement moderne et surtout itératif (Hello Scrum Kanban et consorts)
  • Un build automatisé accompagné d’un repository d’artéfacts
  • Un outil de versionning pour tous et pas seulement pour les développeurs
  • Des tests solides et automatisés, organisés hiérarchiquement comme peuvent l’être les tests Small, Medium et Large actuellement en place chez Google (cf. cet article)

Le premier axe de réflexion commence avec le déploiement automatisé et surtout avec la question “Que déploie-t-on ?”

Que déploie-t-on ?

Par réflexe, tout développeur répond « du code ». Certes mais pas uniquement. Il faut généralement y ajouter :

  • De la configuration,
  • Des évolutions de structure que l’on désigne aussi sous le nom de delta de base de données.

Le triptyque code / configuration / base de données est ce que vous devrez réellement regrouper pour constituer un “deployment package”. Et c’est ce package qui sera effectivement transmis aux équipes opérationnelles. Nous pouvons commencer à nous réjouir, nous avons déjà le contenu de notre livraison. Quoique…

Avoir un package de déploiement n’est pas tout, il faudrait peut-être songer à le déployer en vrai, n’est-ce pas ? Pas de problème me direz-vous, vous l’avez créé. Vous savez donc comment l’utiliser. Mais êtes-vous bien sûr que vous serez aux commandes le jour de l’installation ? Vous pouvez tomber malade, être à des milliers de kilomètres, avoir démissionné, être enlevé par des aliens ou je ne sais quoi d’autre encore.

Et même, êtes-vous vraiment sûr de vouloir abandonner vos activités de codage pour devoir régulièrement superviser les mises en production ? En ce qui me concerne, non car ce n’est pas mon métier. D’autres le font beaucoup mieux que moi.

Mais pourtant, aussi simple, épuré et intuitif que votre artéfact puisse être, il y aura toujours quelqu’un pour le trouver inutilisable, l’accuser de logique corrompue et tenter de lui faire des opérations farfelues.

Bref, le problème entre la chaise et le clavier sera toujours présent et il se peut même que vous endossiez ce rôle à certains moments. Laissez donc l’improvisation de côté et prenez le temps de formaliser les étapes du déploiement sous forme d’un script, d’une documentation ou tout autre medium décrivant pas à pas la procédure basique, à savoir l’enchaînement backup / stop / install / start.

Tout ceci pour dire que si vous pensez que la responsabilité du développeur s’arrête au moment où l’artéfact est construit puis transmis aux équipes opérationnelles, alors vous commettez une grave erreur. Et, accessoirement, je ne donnerais pas cher de votre peau en face d’une équipe d’opérationnels ayant passé la nuit à s’arracher les cheveux à cause de votre war bancal fourni sans la moindre explication.

Ce qu’il faut finalement retenir est l’idée que le développeur s’insère dans une chaîne de valeur et que, comme pour toute autre chaîne, c’est le maillon le plus faible qui détermine la résistance globale. Une fois ce concept bien ancré, Axel se permet de rentrer plus en détails dans les solutions techniques à mettre en place en décrivant notamment les différentes typologies des configurations.

Typologie des configurations

Axel met l’accent sur le fait qu’il n’existe pas qu’une configuration mais au contraire plusieurs configurations dont les portées et les cycles de vie ne sont pas forcément calqués sur votre application. Il en identifie principalement quatre :

  • Les configurations dépendantes de l’environnement seul,
  • Les configurations dépendantes à la fois de l’environnement et de l’application,
  • Les configurations dépendantes de l’application uniquement,
  • Les configurations relatives à la sécurité.

Mais alors que faire pour chacune de ces typologies ?

Dans le cas des configurations uniquement liées à l’environnement, les objectifs principaux sont la cohérence et la reproductibilité. En effet, la redondance, le load balancing et le clustering font qu’une configuration doit être facilement dupliquée d’une machine à une autre et ce, sans observer de déviation. A ce titre, la standardisation des pratiques doit s’imposer pour éviter la trop grande influence du facteur humain. Le meilleur moyen de s’assurer de la reproductibilité reste alors de stocker ces différentes configurations dans un outil de versioning, mais à disposition des opérationnels cette fois. Et surtout d’interdire la fameuse réplique “Il suffira d’éditer le fichier de configuration en production et puis c’est tout”.

Pour les configurations dépendantes de l’environnement et de l’application, le fait d’être lié à l’artéfact incite à laisser ces configurations dans l’artéfact même. Néanmoins, cette double dépendance va forcément entraîner la multiplication des fichiers de configuration puisqu’il faudra alors définir un jeu complet par environnement. Se pose alors la question de la sélection du bon ensemble dans le bon environnement. Axel évoque plusieurs pistes comme la sélection lors du build, l’utilisation de variables d’environnement (système ou arguments de la JVM) ou encore les liens symboliques pointant au bon endroit sur le filesystem.

Enfin, pour les configurations relevant uniquement de l’application, le piège est de vouloir en faire trop en anticipant des changements hypothétiques. C’est le fameux “Mais ça pourrait changer un jour, non ?”. Dans ce cas, autant rester pragmatique. Sans idée précise de la fréquence à laquelle vous devrez apporter des modifications, créer une architecture modulaire ou externaliser la configuration sera aussi utile que d’aller consulter une voyante et ne réussira qu’à vous faire perdre plus de temps. Et si au final la configuration venait à changer, alors il faudrait de toute manière relivrer.

Les configurations de sécurité étant une problématique à part, elles ne furent pas abordées par Axel.

Le delta de la BDD

Après avoir répondu à la question “Que déployer ?” vient la question de l’ordonnancement et plus particulièrement lorsque des modifications sont apportées à la structure de vos bases de données. En effet, deux scripts peuvent vouloir travailler sur les mêmes objets. Dès lors, comment s’assurer que ces derniers ne vont pas laisser la base dans un état structurellement incohérent ?
Ordonnancer ces modifications suppose au préalable de savoir d’où l’on part et où on souhaite se rendre. Partant de ce besoin, plusieurs solutions sont évoquées par Axel mais dans les grandes lignes le principe reste identique. Il convient en effet de stocker des métadonnées supplémentaires afin de définir un état structurel de la base.
Les solutions évoquées furent Flyway et Liquibase mais il existe bien évidemment d’autres alternatives et pas uniquement basées sur du SQL pur. Le but d’Axel était surtout de nous démontrer que même les scripts d’ alter de base de données devaient être inclus dans le processus d’outillage des livraisons alors qu’ils sont actuellement les parents pauvres de la démarche. Une fois ce point bien assimilé, Axel nous propose d’examiner ensuite les impacts des branches sur le processus de livraison.

Les features toggles ou branches par abstraction

Traditionnellement, lorsqu’une nouvelle fonctionnalité majeure doit être mise en place, se pose la question de savoir s’il convient de créer une branche ou pas. Néanmoins, l’utilisation d’une branche fait bondir en flèche la complexité du processus de livraison car, à partir du moment où cette dernière est créée, vous devrez a minima reporter tout bugfix du tronc vers la branche, merger ces modifications et tester à la fois branche et tronc. Autant d’opérations coûteuses et faiblement automatisables.

Entrent en scène les feature toggles. L’idée est de fournir un code dans lequel des nouvelles sections seront activables sur commande sans pour autant toucher à l’existant et surtout sans devoir créer de branche dans le processus de livraison. Ainsi, même si un bugfix doit être déployé au plus vite, les nouveautés ne viendront pas interférer dans le fonctionnement actuel car elles auront été inhibées au préalable. Puis, une fois votre nouvelle fonctionnalité déployée (avec succès) en production, rien ne vous empêchera alors de faire disparaître ces switchs, voire de refactorer. Ce concept d’activation à la demande se retrouve aussi sous le nom de “mise en production cachée”.

Pour finir, Axel aborde la question de la transparence du déploiement pour l’utilisateur.

Un déploiement transparent

Cette question se pose principalement lorsque l’on souhaite que l’utilisateur puisse garder sa session alors même que vous réalisez vos opérations de déploiement. Une approche simpliste serait d’attendre que les nœuds du système soient dans un état permettant le déploiement sans pertes. Mais ceci est illusoire car il se peut très bien que cet état ne se présente jamais. Partant de ce constat, Axel évoque deux solutions.

Premièrement, déployer de manière parallèle sur une autre chaîne puis, progressivement, dévier la charge d’une chaîne vers l’autre.

Deuxièmement, répliquer temporairement l’état d’un nœud et faire en sorte d’utiliser le réplicat et non plus l’original aussi longtemps que la mise à jour durera. Ce système est particulièrement adapté à la conservation des sessions entre un serveur web et un serveur d’application et peut se concrétiser sous la forme d’un cache allant conserver les sessions déjà existantes. Memcache fut d’ailleurs évoqué pour jouer ce rôle.

Au final…

Ce fut une présentation très agréable et bien maîtrisée qui collait à la rigueur toute germanique de notre présentateur. Tout au long de son discours, Axel s’est attaché à montrer que la responsabilité d’un développeur ne s’arrêtait pas une fois son war ou son ear créé. Bien sûr, ceci oblige à prendre en compte beaucoup plus de paramètres en amont et à changer certaines habitudes tenaces mais avec les outils actuels le temps que vous investirez dans votre processus de déploiement sera largement compensé. Je peux vous l’assurer, rien ne vaut la tranquillité d’esprit apportée par un processus de déploiement fiable dans lequel on a pleinement confiance.

Et pour la petite histoire, oui les solutions mises en place par mon équipe et moi rejoignaient celles présentées par Axel, l’honneur est donc sauf 🙂

Pour aller plus loin

  • La vidéo de cette présentation, enregistrée au BeJUG de Leuven, Belgique.

http://www.parleys.com/#play/2443

  • How Facebook releases software. Tech Talk, Chuck Rossi, 2011/03/26.

http://vimeo.com/56362484

  • How does Etsy manage development and operations ? Etsy technical blog, Chad Dickerson, 2011/02/04.

http://codeascraft.etsy.com/2011/02/04/how-does-etsy-manage-development-and-operations/

  • How Google Tests Software – Part Five. Google testing blog, James Whittacker, 2011/03/23

http://googletesting.blogspot.fr/2011/03/how-google-tests-software-part-five.html

  • Flipping out. Flickr technical blog, 2009/12/02, Ross Harmes.

http://code.flickr.net/2009/12/02/flipping-out/

  • Flyway, un outil de migration de base de données en Java.

http://flywaydb.org/

  • Liquibase, un autre outil de migration de base de données.

http://www.liquibase.org/

Nombre de vue : 54

AJOUTER UN COMMENTAIRE