Environnements de test à la demande: bonne ou mauvaise idée ?
De nombreuses équipes dev et ops travaillent ensemble dans le but de pouvoir déployer rapidement des environnements de tests, par exemple pour valider une pull request sur une application. Mais cette pratique est-elle vraiment intéressante ?
Les environnements à la demande
Les environnements de test à la demande sont souvent considérés comme le saint Graal dans un pipeline de CI/CD. Ces environnements sont souvent utilisés pour plusieurs choses.
Test de pull request
Un développeur crée une branche, travaille dessus, et crée ensuite une pull request. Automatiquement ou sur une action sur l’outil d’intégration continu (Gitlab, Jenkins…) un environnement contenant la version du code de la pull request est déployé, et accessible sur une adresse donnée. Le développeur peut jouer avec son environnement qui sera ensuite supprimé une fois la pull request mergée.
QA
C’est un peu comme le point précédent mais à destination d’une équipe QA, de product owners… Un environnement est créé et sert de base pour lancer une série de tests (manuels par exemple) pour voir si une fonctionnalité est correctement implémentée ou non, et correspond au cahier des charges.
Le problème des environnements à la demande
Mettre en place ce type de solutions peut sembler intéressant. Mais avec l’expérience je me demande finalement si les environnements à la demande sont vraiment une bonne idée.
Complexité de mise en oeuvre
Mettre en place la machinerie pour déployer des environnements à la demande est difficile. Bien sûr, dans le cas d’une simple application, c’est facile. Mais une application a généralement des dépendances, comme par exemple:
-
Une base de données (SQL par exemple).
-
Des queues ou bus de messages (RabbitMQ, Kafka…).
-
D’autres applications lorsqu’on a une architecture orientée services, sans parler des architectures microservices où le nombre de dépendances peut exploser.
-
Des dépendances d’infrastructures, pour rendre l’environnement accessible sur une URL unique par exemple.
Le troisième point sur les services dépendants mérite d’être développé. On voit en effet souvent deux stratégies lorsqu’il faut déployer un environnement à la demande.
La première est de déployer toutes les dépendances à côté du service dont l’on veut tester le code. Si vous avez 40 dépendances (ou dépendances de dépendances, car quand s’arrêter dans ce cas ?),vous devez les déployer à chaque fois qu’un développeur veut tester une pull request dans un nouvel environnement.
L’avantage ici est de pouvoir tester son service en totale isolation, en étant sûr d’être "tout seul" sur son environnement, et d’avoir un environnement complet (toutes les applications déployées) à disposition.
La seconde est d’avoir un environnement complet déjà déployé et de "brancher" le service devant être testé sur cet environnement d’une manière ou une autre. Cette solution est intéressante car plus facile à mettre en place mais a un problème majeur: l’environnement peut se retrouver pollué par tous ces services de test, que ce soit au niveau de la base de données, des queues de messages, ou à cause de bugs générés entre services testés.
Gestion des données
Créer un environnement prêt à être testé demande généralement d’initialiser des données: création d’utilisateurs, initialisation d’entités nécessaires au bon fonctionnement de la plateforme, création de scénarios de tests spécifiques… Générer ces données peut se retrouver difficile, notamment dans une architecture microservice avec beaucoup de base de données. Si vous avez par exemple 5 bases de données, les 5 devront avoir des données ayant une certaine cohérence lors du démarrage des applications. De plus, ces données peuvent être différentes selon la fonctionnalité à devoir tester.
Créer correctement les jeux de test puis les déployer de la bonne manière n’est donc pas trivial.
Coût
Déployer une stack complète quand elle ne se compose que d’un service ne coûte pas cher. Mais avec 10, 50, 100… services à déployer par environnement cela n’est plus vrai.
Le coût des environnements à la demande peut vite devenir prohibitif.
Le coût de la mise en place des environnements à la demande et de la maintenance du système de déploiement dans le temps est aussi à prendre en compte, notamment en main d’oeuvre.
A chaque nouvelle technologie dans votre stack, vous vous demandez "mais comment intégrer cela de manière efficace dans mes environnements à la demande ?".
Peu à peu, vos choix seront conditionnés par le fait de pouvoir facilement ou non les intégrer dans ces environnements.
Alternatives ?
Serait-il possible de se passer d’environnements à la demande ? Certaines entreprises l’ont pas le choix. Je ne pense pas que Netflix déploie l’entièreté de ses services à chaque pull request par exemple.
J’ai travaillé dans le passé dans une entreprise où les programmes avaient en dépendance (et interagissaient avec) du hardware. Difficile d’avoir des hyperviseurs ou des routes reflectors à la demande par exemple. Nous discutions aussi beaucoup de comment tester efficacement nos services.
Car au final qu’apportent ces environnements ? Pour les développeurs, de la confiance. La confiance que l’application démarre correctement, la confiance qu’elle continue de fonctionner comme attendue lorsque déployée avec le reste de la stack, la confiance de pouvoir l’exercer en même temps que l’ensemble de la plateforme et de manière isolée.
Pouvons-nous apporter autrement cette confiance ? Dans un monde où de plus en plus d’entreprises basculent sur des architectures microservices, n’est-il pas contradictoire de ne pouvoir tester un service qu’en déployant l’ensemble de la plateforme ? Ne passons-nous pas à côté de l’intérêt même du microservice, c’est à dire du fait de pouvoir travailler en isolation sur son service et par la mise en place de contrats clairs avec l’extérieur ?
Je me dois de dire que je ne crois pas non plus à des environnements de test complexes mais locaux (via du docker-compose ou Kubernetes local par exemple). On a les mêmes inconvénients que précédemment sauf que maintenant on est limité par les ressources de l’ordinateur du développeur, et vous aurez toujours un pourcentage non négligeable de personnes chez qui cela ne marchera pas pour une raison X ou Y, quoi que vous fassiez.
Les environnements à la demande, bien pratiques, ne nous ralentiraient-ils pas sur le long terme ? J’ai beaucoup parlé de pull requests dans cet article, quid du trunk-based development par exemple ?
Je n’ai pas de solutions magiques à proposer. Features flags pour merger vite mais ne pas activer la fonctionnalité (ou l’activer qu’à quelques utilisateurs internes), programmation par contrat (et générateurs de données basés sur les contrats pour les test), patterns de déploiements (blue/green, canary, API gateway…), test d’intégration automatisés… sont autant de choses qui peuvent être intéressantes à pousser.
La partie QA et gestion des données de test est également un vrai problème mais posez vous la question: pourquoi c’est un problème ? Trop de données créées "à la main" (en opposition à un format déclaratif) donc environnements impossibles à reconstruire ? QA qui rentrent "en conflit" car les mêmes comptes sont utilisés ?
Une partie de la solution est sûrement de se demander à chaque fois que l’on a besoin d’un environnement à la demande de pourquoi on en a besoin, et sur ce qu’il faudrait pour s’en passer. En répétant l’opération un certain nombre de fois des patterns devraient commencer à émerger.
Conclusion
Le saint Graal serait des environnements à la demande pour les équipes de développement. En réalité, est ce que le saint Graal ne serait pas de pouvoir s’en passer complètement ? Je suis assez persuadé aujourd’hui par le dernier point.
Add a comment
If you have a bug/issue with the commenting system, please send me an email (my email is in the "About" section).