test

L’architecture as code : structurer et piloter des systèmes complexes

1. Introduction

La conférence a été ouverte par Pierre-Jean Dousset, accompagné d’Adrien Graux, architectes sur les grands delivery d’Octo. Le comptoir s’inscrit dans la continuité du talk présenté à la Duck Conf de l’année précédente sur l’architecture continue par la pratique, et vise à approfondir le concept d’Architecture as Code.

Objectifs du comptoir :

  • Expliquer pourquoi et comment Octo a adopté l’architecture as code
  • Présenter deux retours d’expérience concrets (REX) :
    • Un projet Greenfield, présenté par Pierre-Jean
    • Un projet Legacy, présenté par Adrien

2. Origine et motivations de l’architecture as code

Pierre-Jean a expliqué le dilemme central qui a conduit à l’adoption de l’Architecture as Code.

D’un côté, il fallait maximiser l’ownership des équipes : éviter que l’architecture ne devienne un goulot d’étranglement, accélérer les décisions et le delivery, fluidifier la collaboration et permettre à l’organisation de passer à l’échelle, sans brider l’autonomie des équipes.

De l’autre côté, il fallait maintenir une vision globale cohérente : s’assurer que l’architecture réelle en production correspond bien à l’architecture intentionnelle définie, et que les différents systèmes et plateformes restent alignés.

La boîte à outils

Pour répondre à ce dilemme entre autonomie des équipes et cohérence globale, Pierre-Jean et Adrien ont défini une véritable boîte à outils de l’Architecture as Code :

  • Vision Globale : offre une vue synthétique du SI sur une temporalité mensuelle. Elle permet de suivre l’évolution des systèmes, de vérifier que l’architecture réelle reste alignée avec l’architecture intentionnelle et d’anticiper les risques à l’échelle de l’organisation.
  • Carte d’identité : fournit une compréhension fine des enjeux locaux, mise à jour chaque semaine. Elle permet aux équipes de visualiser précisément leurs composants, dépendances et flux, tout en restant connectée à la vision globale.
  • Prise de recul : complète la boîte à outils en offrant un espace d’analyse et d’anticipation des risques et évolutions, transformant les données collectées en décisions opérationnelles éclairées.

Grâce à cette boîte à outils, Pierre-Jean et Adrien montrent comment concilier autonomie locale et cohérence globale, en rendant l’architecture observable, versionnée et exploitable au quotidien.


3. L’architecture as code

Maintenant que le dilemme et la boîte à outils sont posés, Pierre-Jean et Adrien nous emmènent dans le vif du sujet : qu’est-ce que l’Architecture as Code ?

L’idée centrale est simple mais puissante : traiter l’architecture comme du code. Concrètement, cela signifie pouvoir décrire, versionner et valider l’architecture, faire évoluer le système de manière automatique et fiable, et éviter les documents statiques rapidement obsolètes. Plutôt que d’avoir des diagrammes qui vieillissent au rythme du code, l’architecture devient un artefact vivant, aligné en permanence avec l’implémentation.

Pour y parvenir, deux piliers structurent l’approche :

3.1 Conventions

L’architecture peut émerger directement du code existant. Les règles sont parfois implicites — via les noms de fichiers, structures ou variables — et parfois explicites. Dans tous les cas, le code raconte l’histoire de son architecture, permettant aux équipes de comprendre le système simplement en explorant le code, sans documents séparés.

3.2 DSL (Domain Specific Language)

Le second pilier repose sur un DSL, un langage spécifique pour déclarer l’architecture. Il s’agit d’un modèle lisible par les humains et par les machines, qui décrit clairement l’organisation du système, ses composants et leurs interactions. Le DSL permet de générer automatiquement visualisations, rapports et contrôles, rendant l’architecture exploitable au quotidien pour les équipes et les architectes.

4. Retour d’expérience Greenfield – Projet de gestion des urgences

Pierre-Jean a présenté un exemple concret où l’Architecture as Code a pleinement démontré son efficacité.

4.1 Contexte du projet

Le projet concerne un système critique pour les secours, où la sécurité, la résilience et l’interopérabilité sont des exigences absolues. Derrière cette mission vitale se cache un écosystème technique complexe : 15 applications, 42 images conteneurisées, 1,5 million de lignes de code et 167 contributeurs.

Le projet a démarré en décembre 2020 avec le premier commit et a progressivement évolué pour devenir un système robuste et opérationnel, capable de répondre aux besoins critiques tout en maintenant la cohérence technique à grande échelle.

4.2 Conditions favorables

Le projet a été construit sur six ans, permettant une maturation progressive des pratiques et une adoption naturelle des bonnes conventions. Dès le départ :

  • Conventions strictes de nommage : variables d’habilitation, URLs, domaines métiers, organisation des repositories
  • Mono-repository : toutes les applications dans le même dépôt, favorisant la visibilité et la diffusion naturelle des bonnes pratiques
  • Langage unique : TypeScript pour frontend et backend, simplifiant l’exploration du code
  • Librairie commune : centralisation de la gestion de l’utilisateur connecté
  • Réunions régulières des tech leads : aligner et faire évoluer les conventions au fil du temps

Cette approche a permis de garantir la cohérence et la maîtrise de l’architecture au fur et à mesure de la croissance du projet.

4.3 Collecte, modélisation et visualisation : transformer le code en source vivante

Pour maîtriser un système complexe, il ne suffit pas d’avoir du code ou de la documentation séparée. Pierre-Jean explique que la vision repose sur trois sources de données principales, toutes intelligibles par les humains et interprétables par les machines :

  1. GitLab : suivi de l’évolution des modules, contributeurs et code. Chaque application est reliée à son historique et à ses acteurs, offrant une visibilité immédiate sur les responsabilités et les contributions, et servant de trace historique.
  2. Argo CD et Kubernetes : relient les applications à leur infrastructure. Les charts Kubernetes suivent des conventions strictes, et les événements et commandes sont identifiés via des exchanges nommés nexsis-exchange et nexsis-command, avec des routing keys précises.
  3. Code source : structuré pour raconter l’architecture. Répertoires backend (API) et frontend (front) clairs, variables d’environnement standardisées (<nom_app>_API_URL), gestion centralisée des habilitations et suivi des versions des frameworks. Le code est lisible par les humains, mais facilement exploitable par les machines pour automatiser la collecte et la modélisation.

Toutes ces informations sont agrégées par un script Python et injectées dans une base SQL centrale, source unique de vérité. À partir de cette base, plusieurs formats sont générés automatiquement :

  • Markdown : documentation interne et versionnée
  • HTML : exploration dynamique du système
  • PDF/DAT : diffusion externe ou institutionnelle

L’ensemble est versionné dans GitLab, permettant de revenir dans le temps pour analyser l’état du système à un moment donné, comprendre un incident ou évaluer l’impact d’une évolution.

4.4 Présentation de la boîte à outils

Pierre-Jean nous présente ensuite plusieurs visualisations et explique comment il les utilise sur son projet.

Vision Globale

Schéma d’architecture global : visualiser, comprendre et sécuriser le SI

Un schéma d’architecture global, structuré en plusieurs couches — frontend, backend, composants hébergés, RabbitMQ, et plus encore — met en évidence les dépendances et les flux entre composants, offrant une vision synthétique du système.

Ce document joue un rôle clé dans plusieurs aspects du projet :

  • Onboarding des équipes : il permet aux nouveaux arrivants de comprendre rapidement l’organisation générale du système, les interactions entre composants et la hiérarchie des couches.
  • Règles sur les flux : le schéma sert de support pour formaliser des règles sur les échanges entre applications et détecter automatiquement les violations.
  • Identification des composants critiques : certains composants deviennent sensibles si trop d’éléments dépendent d’eux. Dans l’exemple de Pierre-Jean, une règle fixe que si un composant reçoit plus de 15 connexions entrantes, il est automatiquement identifié comme critique et isolé visuellement dans un layer rouge, facilitant son suivi et sa protection.

Ce schéma d’architecture n’est donc pas seulement un outil de documentation : c’est un instrument d’analyse et de gouvernance, permettant de visualiser le système, appliquer des règles opérationnelles et détecter rapidement les points critiques.

Cartographie des flux événementiels et habilitations

Une visualisation sous forme de matrice montre quelles applications produisent ou consomment tel événement, facilitant une étude d’impact rapide en cas de modification.

Un second tableau recense les habilitations utilisées par chaque application, rendant visibles les accès et permettant d’identifier rapidement les écarts avec les règles de sécurité.

Cartographie des frameworks : sécurité et planification des mises à jour

Un autre tableau détaille les frameworks utilisés par chaque application et leurs versions. Cette visibilité est cruciale pour la cybersécurité, car même une application stable peut devenir un point d’entrée critique si elle utilise une version obsolète.

Grâce à ces informations, l’équipe peut prioriser les mises à jour, planifier la maintenance et transformer la gestion des versions en un processus proactif.

Cartographie des flux événementiels et habilitations

  • Une matrice des événements montre quelles applications produisent ou consomment chaque événement, facilitant l’étude d’impact rapide
  • Une vue des habilitations rend visibles les accès et permet d’identifier les écarts avec les règles de sécurité

Cartographie des frameworks

  • Tableau détaillant frameworks et versions par application
  • Permet de prioriser les mises à jour et transformer la gestion des versions en processus proactif de cybersécurité

Visualisation des composants RabbitMQ

  • Vue claire du vHost, exchanges, bindings, queues et applications consommatrices
  • Permet d’identifier les composants critiques et d’anticiper l’impact des modifications

Carte d’identité locale

Schéma centré sur une application

Une visualisation se concentre sur une application et ses dépendances directes : RabbitMQ (vhost, exchanges, queues), bases de données et services associés. Elle permet de comprendre rapidement les interactions critiques et de communiquer clairement avec les équipes sur le fonctionnement et la portée d’une application.

Visualisation des composants et habilitations

Une autre vue montre les backend, batchs, domaines métiers et habilitations réellement utilisés par une application. Ces informations aident à anticiper les impacts des évolutions et à mieux communiquer avec les équipes.

Visualisation des messages et flux

Enfin, une vue détaillée des messages consommés et émis par l’application, avec les vHosts, exchanges et queues associés, permet de savoir quelles applications seront impactées par une évolution des messages.

Prise de recul

Répartition du code

Pierre-Jean présente deux treemaps montrant l’évolution du code au cours de l’année. Certaines parties ont beaucoup évolué, ce qui raconte l’histoire de l’application qui grandit et se transforme. Ces visualisations permettent de prendre du recul, réfléchir à l’organisation du code et échanger avec les équipes pour mieux comprendre les choix réalisés.

Passage des applications en MCO

Une visualisation identifie les applications qui n’ont pas évolué depuis plusieurs mois. Ces informations peuvent guider leur passage vers des équipes dédiées à la TMA, déchargeant les équipes stratégiques et recentrant les efforts sur les évolutions critiques.

Composants sans contributeur

Enfin, une visualisation recense les composants sans contributeurs actifs, permettant de détecter les zones à risque. Si un composant critique apparaît dans la liste, il est nécessaire de prévoir une phase de reprise en main avant toute évolution.

5 Retour d’expérience Legacy

Retour d’expérience Legacy – Adrien Graux

Adrien enchaîne avec le REX Legacy et commence par poser le contexte du système d’information concerné.

Il s’agit d’un SI avec près de 30 ans d’histoire, composé d’environ 15 produits, représentant une soixantaine d’applications, utilisées par des millions d’utilisateurs. C’est un SI fortement exposé, soumis à des contraintes réglementaires importantes, avec des évolutions fréquentes, souvent urgentes. Les enjeux de visibilité sont élevés : ce sont des applications grand public, en évolution continue côté métier.

Sur le plan technique, l’infrastructure est gérée as code, déployée sur un cloud privé, avec Ansible pour la configuration. La stack est majoritairement composée de Java côté backend et de React côté frontend.

La plateforme a fait l’objet d’une refonte partielle en 2019. Cette refonte a été menée en trois silos, ce qui a permis d’aller vite, mais a aussi introduit une hétérogénéité des pratiques : technologies similaires, mais versions différentes, usages divergents, conventions variables. Chaque silo avançait à son rythme.

Aujourd’hui, la refonte est largement terminée, le SI est en production et continue de vivre. Cela a fait émerger une forte volonté de standardiser et d’urbaniser l’existant, afin de faciliter la maintenance et de reprendre la maîtrise globale du système. C’est dans ce contexte que des travaux d’architecture structurants ont été lancés.

Collecte des données et modélisation

Adrien explique ensuite comment le système est observé et modélisé. Trois sources de données principales sont exploitées :

  1. GitLab, qui permet de récupérer les applications, les projets et les contributeurs, et donc d’avoir une vision claire de qui travaille sur quoi.
  2. Le code source, qui constitue la source la plus importante. Il permet de détecter les technologies utilisées, leurs versions, certains patterns (batchs, planifications, usages techniques), et de collecter des informations très proches de la réalité du système.
  3. Les dépendances techniques, décrites avec un DSL spécifique.

L’ensemble de ces données est collecté via un script Python, qui les parse, les normalise et les stocke dans un modèle commun, servant de base à la documentation et aux visualisations.

Pourquoi un DSL spécifique ?

Adrien explique ensuite le choix de créer un DSL maison.

L’objectif n’était pas de réinventer un langage d’architecture générique, mais de modéliser de la manière la plus simple possible les dépendances d’une application. Le besoin principal était de réduire au maximum l’effort de maintien dans le temps, car dans ce type de démarche, le risque majeur est d’avoir des données qui ne sont plus à jour.

Plusieurs approches ont été testées :

  • Une approche par conventions, rapidement abandonnée : avec 30 ans d’histoire et des pratiques hétérogènes, il était trop difficile d’imposer des conventions à l’échelle du SI.
  • Une approche basée sur les fichiers de configuration, notamment côté Java, pour détecter automatiquement les dépendances. Là encore, trop de cas particuliers et d’exceptions.

Adrien a donc fait le choix d’un DSL minimaliste et très spécialisé, dédié uniquement à la description des dépendances applicatives. Les solutions existantes, jugées trop verbeuses et trop complexes, présentaient un risque fort de non-adoption ou de non-maintenance.

Ce DSL se concentre sur l’essentiel :

  • ce qu’est l’application,
  • comment elle est exposée,
  • ce qu’elle utilise comme observabilité et services communs,
  • et surtout la liste de ses dépendances, décrites simplement par un nom et un type.

Génération des visualisations

Une fois les données collectées et stockées, un second script Python consomme le modèle pour générer un site statique (HTML, CSS, JavaScript).
Les schémas sont produits à l’aide de la librairie Python Diagrams.

Tous les résultats (données, visualisations, site généré) sont versionnés dans GitLab, ce qui permet non seulement la diffusion, mais aussi le retour dans le temps pour analyser l’état du SI à un instant donné.

Exploitation : règles de flux et contrôles

À partir de ces données, des règles de contrôle ont été mises en place, notamment sur les flux réseau.
Un rôle Ansible permet de vérifier si les flux attendus sont bien ouverts, en se basant sur les dépendances déclarées dans le DSL. Si une dépendance existe, le flux correspondant peut être testé automatiquement.

Démonstration de l’outil

Adrien présente ensuite le rendu concret de l’outil :

  • Une vue globale listant tous les projets, avec des informations sur les contributeurs et l’activité.
  • Une vue détaillée par application, montrant l’état du code, les contributeurs actifs, les technologies et leurs versions.
  • Une détection de patterns techniques, comme les batchs, enrichie suite à un incident de production afin de détecter certains écarts (par exemple l’absence de mécanismes de verrouillage).
  • Une vue de dépendances locales, générée à partir du DSL, montrant ce dont une application a besoin pour fonctionner : bases de données, middleware, S3, API Management, etc.
  • Une vue dédiée au suivi de l’obsolescence technologique, permettant de suivre les versions Java, Gradle, Spring, React, et d’identifier rapidement les mises à jour critiques liées à la sécurité.
  • Une vue de tests de flux, permettant d’exécuter automatiquement des contrôles à chaque mise en production ou en cas de doute.

Enseignements et convictions

Adrien conclut avec plusieurs enseignements clés :

  • L’architecture as code doit être mise en place de manière incrémentale, guidée par les besoins réels des équipes.
  • La meilleure source de vérité reste le code source, car elle reflète l’implémentation réelle.
  • La démarche repose sur trois étapes claires :
    1. Collecter les données depuis différentes sources,
    2. Modéliser dans un format commun,
    3. Visualiser et exploiter ces données.

Les gains observés sont nombreux :

  • Moins de temps passé à produire de la documentation manuelle,
  • Une documentation plus fiable car basée sur le code,
  • Des décisions d’architecture facilitées,
  • Moins de sollicitations entre équipes,
  • Une meilleure maîtrise globale du SI,
  • Et surtout, de nouveaux usages possibles une fois les données centralisées.

Adrien évoque enfin l’apport de l’IA, utilisée comme accélérateur : analyse de larges volumes de code, aide à la décision sur les analyses à mettre en place, et génération de scripts d’analyse sur mesure, sans avoir besoin de maintenir une équipe dédiée en permanence.

Qu’ils soient Greenfield ou Legacy, l’expérience montre qu’une démarche incrémentale et guidée par les besoins réels des équipes permet d’atteindre cohérence, lisibilité et évolutivité, tout en conservant l’autonomie des équipes.