TDI ou Test Driven Infrastructure

le 23/08/2011 par Arnaud Mazin
Tags: Software Engineering

Objectif

Une des valeurs portées par le mouvement DevOps réside dans l'ouverture et l'échange des outils, bonnes pratiques, us et coutumes entre Devs et Ops. Essayons donc dans ce billet de tirer profit des bonnes habitudes du TDD et voir dans quelle mesure il y aurait matière à les piquer / adapter dans le monde du run et des infrastructures. Une idée serait de considérer l'infrastructure comme un système testable et donc mettre en place une stratégie systématique de TDI pour Test-Driven Infrastructure. Un changement, un test.

Pour les plus Ops d'entre nous qui n'aurait jamais entendu parler de TDD, rappelons les grandes étapes d'un TDD : On écrit un test, on vérifie qu'il passe bien en rouge dans un premier temps, puis on implémente le moyen le plus simple et le plus rapide pour faire passer le test en vert, suite à quoi on peut rentrer dans des étapes de réusinage pour améliorer le code, tout en conservant le test dans l'état vert.

Qu'aimerait-on tester en infra ?

  • Un changement de configuration (réseau, système, sauvegarde, ordonnancement, application)
  • Une nouvelle version d'une application, d'un patch système, d'une brique d'infra
  • Un script
  • Un déploiement
  • Un processus de production (activation d'un PRA par exemple)

Et là, c'est le drame…

Bien entendu, la complexité réside dans le fait que tester unitairement une infrastructure n'a qu'un intérêt très limité. Tester un nouveau paramètre sur la quantité maximum de mémoire partagée ou le nombre max de descripteurs de fichiers n'a de sens que si l'on est capable de mettre le processus dans les conditions exactes de la prod, ou le plus proche possible.

On ne va pas avoir la prétention de pouvoir tout tester, essayons simplement de proposer quelles pistes actionnables sur le chemin de l'amélioration continue que nous arpentons humblement.

Supervision

La supervision est l'outil de test par excellence puisqu'une fois configuré, il va travailler pour vous, sans cesser d'enchaîner test sur test.

Le fait d'impliquer la supervision dans une démarche de TDD apporte une vertu fondamentale : avant de tester que tout est vert, vous allez avoir la preuve que votre supervision détecte bien un cas non conforme en s'allumant en rouge, avant de repasser en vert. Parmi les outils que l'on rencontre régulièrement et qui ont l'avantage d'une grande ouverture à l'utilisation, citons Nagios et ses nombreux dérivés et Zabbix.

Différents niveaux de test sont réalisables:

  • Techniques : se focaliser sur les quelques tests les plus pertinents qui disent vraiment les choses
  • Fonctionnels, de plus haut niveau possible. La complexité réside dans notre capacité à connaître et donc reproduire un scénario complet et représentatif d'un utilisateur sur une ou plusieurs applications. Des solutions comme cucumber-nagios peuvent alors être employées : elles vont permettre de simplement lancer toute la variété de tests réalisables avec Cucumber simplement à partir de Nagios
  • Longue durée : faire le mariage de ces deux genres d'indicateurs sur plusieurs mois est la clé pour faire une gestion de capacité pertinente et détecter les effets de seuil que votre système manifeste

Page d'auto-test des applications

Le principe de cette idée rencontrée chez différents clients est simple : il s'agit d'exposer (uniquement aux administrateurs et aux développeurs) une URL d'auto-test. Même si elle ne fournit que du simple HTML la page Web contiendra le mot-clé 'KO', si quelque chose ne fonctionne pas. En général, ces pages regroupent des tests de connectivité de l'application avec son environnement :

  • Présence de services type dummy qui traversent toutes les couches
  • Accès à la base de données
  • Annuaires LDAP
  • serveurs SSO
  • Bus de messages
  • autres fournisseurs de services externes (WS dummy...)

Ce genre de page peut et doit être utilisée au moment des mises en production car c'est elle qui va vous dire si l'application se sent bien dans son nouveau chez-soi.

Il est simple de mettre par la suite en place des tests de supervision qui interroge régulièrement cette page et la scrute à la recherche du fameux mot-clé.

Gestion des configurations

(tests de conformité système)

Parmi les outils rentrant dans cette catégorie, citons Puppet, Chef, cfengine (un article précédent fait un rapide panorama de ces logiciels). Pour résumer, disons qu'ils permettent de décrire l'état du système souhaité. Charge à l'outil de mettre le système en conformité.

Les outils basés sur des descriptions de configuration cible travaillent naturellement en suivant le pattern du TDI. Pour chaque item de configuration à atteindre, ils vont systématiquement commencer par tester une conformité (exemple : je teste que sur cette machine, Apache2 est installé, mais surtout pas Exim). En cas de non-conformité (le test passe en rouge), l'outil va prodiguer un certain nombre de soins au malade pour le rendre conforme (désinstaller exim et installer apache2). Le lancement suivant de l'outil détectera que la configuration est conforme et ne fera rien de plus. Tant que la règle reste présente dans la configuration de l'outil, le test continuera à être joué, patiemment…

La présence d'une solution de gestion de configuration n'a pas pour but de rendre le système plus résistant au changement, mais au contraire doit lui permettre d'évoluer rapidement de façon maitrisée. Si un beau jour il devient primordial de tordre le cou à Apache au profit de NGINX ou Lighttpd, en changeant simplement la configuration de notre outil, on va modifier le test afin qu'il devienne : je veux que sur cette machine, lighttpd soit installé, mais surtout pas Apache.

L'utilisation du mode tir à blanc (dry-run) de ces outils permet en outre de faire passer les tests sans pour autant engager les opérations de mise en conformité.

Et les scripts dans tout ça ?

Même si votre direction des opérations a choisi de recourir à des installations des applications sous forme de RPM/Deb/War/Ear, il reste probablement un grand nombre de scripts (shell ou autre) qui quotidiennement font des besognes aussi diverses que les sauvegardes, les rotations de journaux, les déclenchements de travaux de synchronisation avec d'autres systèmes. Un défaut dans du code shell peut facilement avoir des conséquences aussi graves qu'un bug dans une application.

La problématique réside dans le fait que des socles de test comme shunit2 fonctionnent bien pour des tests unitaires, mais c'est rarement dans la logique métier d'un script que réside sa valeur, mais plutôt dans sa robustesse et surtout dans sa capacité à faire un grand écart entre une base de données, des fichiers, des processus… Placer des bouchons tout autour d'un script revient généralement à ne plus tester grand chose. La mise en place de Labs propose donc un socle de test bien plus pertinent.

Tests d'infrastructures complètes : les labs

Pour se rapprocher au maximum de la prod' dans la représentativité de nos tests, on se rend vite qu'il faut reproduire en labo des infrastructures « complexes ».

La situation «simple» mais quelque peu onéreuse consiste à disposer d'autant de plateformes représentatives que nécessaires. Plus raisonnablement, on va désormais profiter de la massive virtualisation des plateformes pour mettre en place des labs plus ou moins complets.

L'enjeu des labs réside dans la capacité à les modéliser, instancier, tester et détruire après usage, chacune de ces étapes devant se faire le plus vite et le plus simplement possible.

En combinant un certains nombre d'outils (chef, capistrano, VirtualBox qui peut entièrement être piloté en ligne de commande), on va parvenir à aider dans la réalisation de ces tâches

  • Instancier 3 VM vierges à partir d'un master
  • Monter un réseau virtuel pour interconnecter les 3 VM en les isolant (si besoin est) du reste du monde
  • Lancer des mise en conformité du socle système (Puppet + Vagrant)
  • Installer les dernières versions des applications
  • Installer un jeu de données sur notre SGBD favori
  • Configurer / Démarrer les services bouchons nécessaires à la chaine
  • Lancer les tests (injecteurs, simulateurs)
  • Collecter et archiver les résultats des tests
  • Éteindre les machines et libérer les ressources

Sur le papier, c'est génial et le simple prolongement de ce que des TU ou un bon GreenPepper propose du côté du développement, mais l'outillage se complexifie au fur et à mesure que l'on ajoute des briques dans notre système à tester.

En effet, pour réaliser les Labs (planification du test, configuration du test, approvisionnement, test, libération des ressources) on se rend compte qu'il va être nécessaire de mettre en œuvre une grande quantité d'outils et de ressources. C'est d'autant plus vrai que l'ouverture d'une telle infrastructure, si possible en libre service, sous-entend un maximum d'automatisation. Des outils comme cucumber-puppet vont permettre de décrire dans un langage quasi naturelle un test tout en déléguant la basse besogne de mise en place de l'infrastructure du test à puppet.

Les temps d'exécution, notamment la phase de mise en place du lab, se comptent généralement en dizaine de minutes, ce qui va vraisemblablement limiter ces tests à ces tâches nocturnes ou manuelles.

Une autre limite des labs réside dans la difficultés à représenter précisément un environnement. Des différences apparaissent généralement entre les environnements de dev / qualif et de production :

  • Nombre de machines
  • Zone de sécurité, DMZ
  • @IP, noms de machine
  • Équipements particuliers (SAN, répartiteur de charge, pare-feu)
  • processus de déploiement (IC vs MeP dirigée par les Ops)

Nous savons tous, pour avoir dit au moins une fois dans notre vie « je ne comprends pas, chez moi, ça marche », que la vraie vie de la prod' nous réserve de belles surprises !

Jusqu'où aller ?

Nous n'en sommes encore qu'à une étape exploratoire dans la définition et la mise en application du principe du TDI. Certaines équipes implémentent deux idées, parfois trois et rarement plus.

J'ai cependant la conviction que les Ops ont beaucoup à apprendre de cette démarche et la route reste longue avant que n'importe quel Ops pense se pose systématiquement la question suivante : « quel est le test permettant de valider le changement que je veux faire ? ».

Chouette, on a encore un peu de pain sur la planche. Un bon socle de départ me semble constitué d'un outil de supervision (nagios, zabbix…) et d'un outil de gestion de configuration (chef, puppet, cfengine). Cerise sur le gâteau, commencer à coupler les deux.