LIEN GITLAB
J’ai eu la chance de pouvoir tester ce pattern en créant une infrastructure as code pour une application existante, bien qu’une petite application, elle m’a montré les forces et faiblesses de notre pattern et les différents cas d’usage.
Parlons un peu de l’application, elle se nomme Ochocast, elle a pour objectif de pouvoir stocker et gérer des vidéos ou encore créer des événements notamment pour l’Octofest.
L’infrastructure que nous allons devoir déployer doit être, comme le pattern l’indique, complètement isolée ainsi il fallait adapter certains composants de l’architecture initial pour les faire fonctionner dans des containers. Ainsi on se retrouve avec l’infrastructure suivante :
On observe 3 containers, le backend avait initialement un dockerfile, le front react qui est déployé avec nginx doit recréer son image à chaque déploiement en prenant en compte les variables dynamiques des ressources pulumi. Et enfin, KeyCloak qui permet une gestion des utilisateurs. À cela s'ajoutent les différents objets de stockage pour nos ressources.
Le main se trouve dans “PulumiResourceDeployment”, c’est ici que sont effectués les différents inputs avec notamment le choix du provider et la prise en compte de la configuration des ressources qui se trouve dans le dossier config.
Les différents use case sont accompagnés, juste au-dessus, de types qui sont composés en 2 parties: les inputs et outputs des use cases, interfaces et ressources de chaque provider. Leur classe mère est donc composée de variables communes entre tous les providers. Par exemple, le nom et port pour le type containers et leur sous classes ajoutent des variables en fonction du cloud provider, comme le cluster ecs pour aws. On garde ainsi une indépendance au provider jusqu’au dernier moment. Lors de la création de ressources, le type passe de la classe mère à la classe fille spécifique.
Nous avons ensuite les Uses cases et interfaces qui servent d'intermédiaire entre les différentes couches.
On observe alors la découpe entre les différentes ressources du cloud provider, le controller et notre input.
On peut aussi effectuer des tests sur l’infrastructure, 2 types de tests existent :
- Les tests unitaires qui MOCK les ressources afin d'éviter le déploiement des ressources et accélérer la phase de test et cela grâce à Jest.
- Les tests d’intégration qui eux utilisent runInPulumiStack, qui appel le code typescript pour le testé avec des appels systèmes.
Bien que structuré de façon claire et logique, on peut quand même observer une complexité initiale plus importante. Ainsi, même si cela permet une séparation claire entre les différentes ressources, la compréhension globale du projet peut s'avérer plus compliquée et complexe.
On retrouve aussi la gestion de la dynamicité qui est une difficulté. Vouloir créer les ressources dynamiques sans connaître leur point d’accès final par exemple, demande une adaptation du code à gérer et créer ses ressources de la bonne façon. Il ne faut pas qu’une ressource soit configurée avant qu'elle ne soit créée. Et la configuration de certaines ressources nécessite de connaître ces endpoints avant leur création, on se retrouve alors avec la nécessité de passer par des intermédiaires comme des load balancers ou alors de les connaître en les fixant avec des noms de domaines fixes par exemple.
On peut donc dire que ce pattern ne s’adapte pas à toutes les infrastructures et ne répond pas à tous les problèmes. Bien que réduisant la complexité pour les gros projets, cette approche peut être inutile pour des petits projets voué à le rester.
L’Infrastructure as Code est aujourd’hui un pilier incontournable de la gestion moderne des systèmes d’information, mais elle souffre encore d’un manque de maturité sur le plan architectural. Face à une complexité croissante, à une dette technique difficilement maîtrisable et à des exigences de scalabilité et de sécurité de plus en plus élevées, il devient impératif de structurer nos approches.
En s’inspirant des patterns éprouvés du développement logiciel, comme la Clean Architecture, le pattern Clean Infrastructure propose une structuration claire, modulaire et évolutive de l’IaC. Il répond à des besoins concrets : réduction de la dette technique, amélioration de la lisibilité, facilitation de la collaboration, et accélération des cycles de livraison. Il ne faut pas oublier que ce pattern ne s'adresse pas à tous comme montré précédemment. Pour comprendre sa nécessité, il faut avoir un projet à grande complexité. L'application de cette méthode perd son sens pour des petits projets.
Mais au-delà du pattern lui-même, c’est une culture d’architecture partagée qu’il faut instaurer, une culture où l’IaC est conçue, revue et maintenue avec la même rigueur que le code applicatif. En effet, même rigueur que le code applicatif nécessite l'adoption, l'adoption de bonnes pratiques, la formalisation de standards d’équipe, et un effort collectif pour rendre l’infrastructure aussi maintenable que le logiciel qu’elle soutient.
L’IaC n’est pas qu’un outil technique : c’est un levier stratégique. Et comme tout levier stratégique, il mérite une fondation solide, un langage commun, et une vision partagée.