Dans le développement logiciel nous concevons facilement que l’objet du développement étant le logiciel, que ce dernier puisse s’installer dans des environnements différents en fonction de l’étape du processus de création allant du poste du développeur à la mise en production finale. Si l’on se focalise uniquement sur l’aspect développement, l’environnement d’exécution n’est qu’un support et ne fait pas partie du développement du logiciel même. Ainsi les étapes du processus de création qui sont les branches du référentiel de sources, ne nécessitent pas toujours que l’environnement soit permanent: la production qui accueille la dernière version taguée issues de la branche master doit être permanente mais un environnement de revue qui accueille le dernière version d’une branche de bug n’a pas vocation à l’être. C’est le concept d’environnement à la demande qui peut facilement être bien géré avec les conteneurs.

IaC
Avec le DevOps qui amène à rapprocher l’infrastructure support du monde des développeurs et finalement à concevoir l’infrastructure support également comme du code, se pose alors le traitement de l’infrastructure comme n’importe quel autre composant logiciel:
- il faut le versionner
- il faut y apporter des modifications tracées par des tickets
- il faut le tester unitairement
- il faut le passer en revue
- il faut le déployer en preprod (staging)
- enfin le déployer en production
Si les 2 premiers éléments ne posent pas de difficulté, les suivants dépendent de la maturité de l’équipe DevOps. En effet mettre sur Git le code de l’IaC (par exemple les sources terraform et ansible) va de soi. Modifier ce code via le système de ticket de Gitlab par exemple n’est pas non plus une contrainte insurmontable: je veux ajouter de la mémoire sur une machine ou changer le port d’écoute d’un service, j’ouvre un ticket, je tire ma branche de bug, je modifier le code de l’IaC, je merge ma branche de bug. Rien d’insurmontable et salvateur dès que plus d’un Ops travaille sur l’infrastructure.
La suite est plus problématique. Il serait tentant de faire suivre le code IaC le même chemin que le code applicatif en le déployant d’environnement en environnement mais le code l’IaC a pour objet même infrastructure donc l’infrastructure qui supporet le logiciel ne peut pas supporter infrastructure elle-même.
Objet | Logiciel | Infrastructure |
support (déployé sur) | Environnement | ? |
feature | dev | ? |
tag | production | ? |
Prenons l’exemple simple où l’on veut modifier la version d’un intergiciel comme Tomcat ou bien la taille d’un disque. Dans le code de l’IaC on va modifier cette définition. On versionne le nouveau code de l’IaC puis comme tout code, on veut le tester. Or le code source de l’infrastructure définie l’ensemble de l’infrastructure: donc appliquer la nouvelle version modifie la production également. On peut tenter d’éviter cela en séparant le code de l’infrastructure par environnement mais on retombe dans le travers de devoir modifier, par application du nouveau code, un environnement réellement en utilisation fusse-t-il un environnement de développement. On reste également limité dans l’impossibilité de pouvoir tester l’ensemble de l’infrastructure ou même de tester « localement » une modification comme « ajouter de la mémoire pour l’environnement de production » avec du code IaC qui porte la modification vraiment dans la définition de l’environnement de production.
Support de l’IaC
Comme il est souvent le cas, il faut revenir à la définition.
Pour le développement classique l’objet est le logiciel. L’objet se déploie dans un environnement selon l’étape du développement. Chaque environnement est un support de déploiement. L’ensemble des environnements définissent l’infrastructure du projet.
Il faut penser l’IaC comme un projet de développement où l’objet est l’infrastructure. L’infrastructure se « déploie » dans un « environnement » selon l’étape du développement de l’IaC. Une version taguée de l’IaC a pour vocation à être appliquée en réel c’est-à-dire dans le monde réel, en modifiant toute l’infrastructure réelle ce qui signifie être sur les machines réelles de l’infrastructure du projet logiciel. Mettre en production l’IaC c’est modifier les environnements du projet de développement logiciel.
En phase amont du projet IaC, aucun environnement de l’infrastructure réelle du projet logiciel ne doit être impacté.
En phase amont, branche develop, feature où autre qu’un tag sur la branche master, l’infrastructure réelle de l’application ne doit pas être touchée quel que soit l’environnement modifié dans le code IaC. En effet le code n’est pas fini et testé, donc ne doit pas être déployé en production (la production pour l’IaC c’est le monde réel ie l’infrastructure réelle utilisée par le projet logiciel).
Il en découle que pour faire de l’IaC un vrai projet de développement, il faut s’outiller pour pouvoir:
- tester unitairement
- faire en revue
- appliquer l’IaC dans un « environnement » preprod
Aucune des actions ci-dessus ne se fait sur les environnement réels de l’infrastructure du projet logiciel !
Monde
Afin de lever l’ambiguïté sur la notion d’environnement support pour le logiciel et celle d’environnement support pour l’infrastructure, je choisi d’appeler monde l’environnement support pour l’infrastructure.
Objet | Logiciel | IaC |
support (déployé sur) | Environnement | Monde |
feature | dev | temporaire |
tag | production | réelle |
Pour tester l’IaC il faut créer un monde temporaire c’est-à-dire une infrastructure temporaire constitué de l’ensemble des environnements du projet logiciel.

Dans un contexte Cloud, pour pouvoir tester une version du code IaC il faut pouvoir instancier des tenants temporaires afin d’y créer une infrastructure temporaire. Si on n’est pas dans le Cloud, on pourra créer des VM afin de produire monde temporaire dans lequel tester son IaC qui dans ce cas se limitera à la partie configuration (ansible par ex.).
Monde temporaire par VM ou conteneur ?
J’appelle monde temporaire un ensemble de machines qui reproduisent l’infrastructure réelle et sur lesquelles et grâce auxquelles des tests sont faits dans le cadre de développement du projet IaC. Je pense également l’automatisation de ces tests dans le cadre du CI/CD. Le choix de la technologie pour produire ces mondes dépends de la phase (ou branche) dans laquelle se trouve le code IaC et du contenu du code IaC: création de l’infrastructure et/ou configuration ?
Tout d’abord si le code IaC contient la partie production de l’infrastructure via par exemple terraform alors tester l’IaC signifiera utiliser un tenant temporaire ou des ressources instances temporaires quelle que soit l’étape dans le développement de l’IaC.
Si en revanche le code IaC ne fait que de la configuration (via ansible par exemple), la nature des nœuds de l’infrastructure à savoir VM ou conteneur n’est pas un prérequis à l’application de la configuration. Dans ce cas le choix entre VM et conteneur est possible.
Ainsi pour des tests unitaires d’une application de configuration (role ansible par ex) ou sur une branche de bug (ou feature pour positiver) on pourra préférer utiliser des conteneurs pour la rapidité de démarrage. Au contraire sur une branche d’intégration (develop) ou pour vérifier une dernière fois avant le grand saut sur le monde staging on préférera utiliser une copie des machines réelles sous forme de VM.
Outils
Voici quelques outils pour la mise en œuvre de ces idées:
- test unitaire des roles ansible : molecule
- test de l’infra une fois tout l’IaC appliquée : testinfra
- créer une infra VM à partir d’un inventaire ansible: voir mon POC de projet IaC de configuration
Tags: Ansible CI/CD devOps Docker IaC molecule terraform testinfra