
Sommaire
Il n’est pas rare de lire que GitOps est un indispensable du Platform Engineering, voire un prérequis.
L’approche est séduisante et pleine de promesses : une source unique de vérité, Git, décrit en tout temps l’état de la plateforme et des applications qui la composent. Le repository fait alors office à la fois de plans de construction et de carnet de santé de l’infrastructure. Pour peu qu’on maîtrise Terraform, Ansible, ArgoCD ou Helm, on peut savoir précisément ce qui tourne en production à tout instant.
Mais cette élégance théorique a un prix : la plateforme doit être capable d’appliquer ces recettes de cuisine sans faille et de rectifier rapidement toute dérive. Sans cette capacité, l’automatisation promise par GitOps peut vite se transformer en source de friction.
Si votre plateforme, comme OXP (voir les articles précédents), repose sur le duo Kubernetes + ArgoCD, votre productivité peut atteindre des sommets. Jusqu’à ce que…
GitOps, les premiers jours du parfait amour
Que vous utilisiez des technologies Infrastructure as Code (IaC) ou un processus de Continuous Delivery basé sur des templates, les premiers pas dans le monde de GitOps sont enchanteurs. À chaque push, de nouveaux éléments se déploient et la plateforme prend vie en une simple ligne de commande.
Sur OXP, grâce au duo ArgoCD + Helm, il devient possible de mettre en place toutes les capabilities natives de la plateforme en quelques heures. La modification des variables templatisées, couplée à l’application automatique des changements par Kubernetes, offre un terrain de jeu idéal pour tester, affiner et itérer rapidement sur le paramétrage des services.
Autre avantage : la collaboration est inscrite dans l’ADN même de Git. Conséquence immédiate ? La construction de la plateforme devient naturellement un exercice collectif. Les modes de travail collaboratif étant souvent déjà bien établis dans l’entreprise, il est simple de reprendre et d’adapter un Git Flow existant pour structurer efficacement les contributions.
En parallèle, les bonnes pratiques de développement associées à Git favorisent une modularité accrue et la réutilisation de blocs de code. La séparation des briques élémentaires de la plateforme se retrouve dans l’architecture même des projets Git, facilitant ainsi l’évolutivité et la maintenance. Cette approche modulaire permet de capitaliser sur des composants existants et d’accélérer le développement de nouvelles fonctionnalités.
L’une des promesses les plus séduisantes de GitOps est aussi l’une des plus faciles à vérifier : une meilleure résilience et une plus grande cohérence. Aux premières étapes du projet, il n’est pas rare de remettre la plateforme à zéro (selon le bon vieux principe Pet versus Cattle) et de la voir se redéployer sans accroc. Cette pratique apporte une véritable tranquillité d’esprit : le Disaster Recovery semble presque garanti… du moins au début ; nous y reviendrons.
Enfin, l’approche GitOps est un allié naturel des équipes de cybersécurité. En centralisant la configuration de l’infrastructure dans un référentiel unique, déclaratif et auditable, cette approche renforce la gouvernance et la traçabilité des changements. Grâce aux permissions Git et aux modèles de contribution bien définis, il devient possible d’appliquer une stratégie de Security by Design dès les premières étapes du développement. L’inclusion précoce des équipes cybersécurité dans le processus limite les risques liés aux erreurs humaines et améliore la conformité globale de la plateforme.
Dans l’enfer de la gestion des secrets
Les premiers nuages apparaissent rapidement : chaque infrastructure repose sur des secrets. Par exemple, les Access Keys / Secret Keys de l’infrastructure, les tokens d’accès aux repositories GitLab à déployer, ou encore les mots de passe initiaux des outils.
Or, qui dit GitOps dit fichiers versionnés. Et avec eux, un risque majeur : exposer ces secrets à un grand nombre d’acteurs. Le concept même de secret vacille dès l’instant où il entre dans Git.
On pourrait rétorquer qu’une gestion fine des accès au sein du repository permet d’atténuer le problème. C’est vrai… en théorie. Mais en pratique, cela devient vite un casse-tête :
- Qui gère ces permissions fines ?
- Ce système est-il décrit as code ?
- Comment évolue-t-il avec l’arrivée de nouveaux membres ?
- Que faire lorsqu’un développeur sans accès doit ajouter un secret ?
Reposer sur un système complexe de permissions et de droits pour gérer les secrets, c’est déjà entamer la fluidité tant promise par GitOps. Un premier clou dans son cercueil.
Deux stratégies pour limiter la casse
Une première approche, largement adoptée, consiste à dépendre d’un Store de secrets externe. La plupart des Cloud Providers proposent des solutions SaaS, tandis que des outils on-prem comme Vault permettent de mieux structurer la gestion des secrets. Cela implique une entorse aux principes de GitOps : les secrets ne vivent plus dans Git, mais dans un store dédié. Cette gestion vient aussi avec des avantages concrets, notamment la gestion de la rotation des secrets de manière centralisée, ou la possibilité de générer des secrets temporaires de type OTP.
Notons que des outils comme ExternalSecrets permettent de coupler un Store avec une injection directe dans les runtimes.
Toutefois, les accès à ce store deviennent eux-mêmes un secret à sécuriser. On peut considérer qu’ils font partie des secrets initiaux de la plateforme, à stocker avec le même niveau de précaution. L’accès via un Service Account permet de déplacer le problème.
Une autre approche repose sur le chiffrement des secrets dans Git, via des outils comme SealedSecrets ou Sops. Les secrets sont alors stockés sous forme chiffrée et déchiffrés au runtime par la plateforme.
Nous avons une préférence pour Sops, qui repose sur une mécanique de clé asymétrique :
- Tout développeur peut chiffrer un secret avec la clé publique.
- Seule la clé privée, stockée dans l’infrastructure, pourra les déchiffrer.
Cette approche, élégante en théorie, introduit cependant un risque majeur : rien n’empêche un développeur distrait d’oublier de chiffrer son secret avant de le committer. Un simple oubli et la catastrophe est immédiate.
Tous les outils ne supportent pas GitOps
L’approche GitOps repose sur une gestion déclarative des ressources, mais tous les outils ne sont pas conçus pour ça. Certains services s’appuient encore massivement sur des bases de données qui ne prennent vie qu’au runtime.
Prenons DependencyTrack : un utilisateur n’existe pas en base tant qu’il ne s’est pas connecté une première fois.
Dès lors, comment déclarer un utilisateur à l’avance ?
Une solution extrême consisterait à automatiser l’interface graphique avec un script headless qui simule un premier login. C’est tellement moche que personne ne ferait ça… si ?
Dans un cadre SSO, cette approche devient vite ingérable.
On pourrait alors passer par une API pour créer ces éléments. Mais encore faut-il que l’infrastructure génère d’elle-même un token d’API dès la création du service. Ce qui est rarement le cas.
Et c’est là que tout part en vrille.
On se tord le cerveau pour respecter une approche GitOps pure, on invente des mécanismes absurdes, et on finit souvent par capituler. La création de la plateforme dans son intégralité redevient dépendante d’une intervention humaine… et un nouveau clou vient sceller le cercueil de la résilience et de l’automatisation.
Le casse-tête de l’idempotence
Pour pallier l'absence de déclarativité de certains services, on pourrait être tenté d'ajouter des Jobs “post-déploiement”, afin de corriger les dérives tout en restant dans l’esprit GitOps. Mais se pose alors une question délicate : l’idempotence.
En effet, Git ne propose pas nativement de mécanisme de réconciliation. Rien ne garantit qu’une opération pourra être rejouée sans erreur. Prenons un exemple simple : la création d’un nouveau repository Git. Si :
- Le groupe existe déjà,
- Le projet est déjà créé,
- L’utilisateur “Owner” n’est pas encore disponible,
… alors tout le workflow s’effondre.
Il est donc crucial de penser l’idempotence à chaque étape. La littérature recommande généralement l’usage d’un orchestrateur, chargé de surveiller et d’assurer la rejouabilité des opérations. Mais ces outils, aussi utiles soient-ils, ne sont pas magiques : ils nécessitent une configuration fine et une bonne prise en main.
Dans Kubernetes, on privilégiera l’écriture d’opérateurs, capables de déclencher des actions conditionnelles en fonction des ressources en place. Cette approche a ses avantages, mais elle introduit aussi une nouvelle opacité : pour un contributeur lambda, ces mécanismes deviennent une boîte noire. Qui décide quand et comment ces opérations s’exécutent ? Pourquoi certaines tâches s’effectuent-elles en coulisses sans intervention explicite ?
Prenons un exemple concret :
Si j’ai besoin de répliquer un secret dans plusieurs namespaces Kubernetes, je peux écrire un opérateur qui le duplique automatiquement à partir d’une annotation. Mais dans Git, ce secret n’apparaîtra qu’une seule fois, tandis que sur la plateforme, il existera en plusieurs occurrences.
Cet écart entre GitOps théorique et GitOps appliqué peut rapidement semer le trouble et compliquer encore la compréhension et la maintenance de la plateforme.
Le multi-environnement et la promotion : bienvenue dans le multiverse
Si vous n’aviez pas encore abandonné tout espoir en GitOps, alors il est temps d’aborder l’ultime défi : la gestion des environnements. Non seulement pour votre plateforme, mais aussi pour les applications qu’elle héberge.
Et disons-le franchement : tout le monde n’est pas un Cloud Provider. L’assemblage de dizaines de composants, chacun avec son propre cycle de vie, relève de l’acrobatie pure.
Avec GitOps, mettre à jour un chart Helm est d’une facilité déconcertante. Mais c’est aussi le moyen le plus simple de dérégler l’horlogerie de votre infrastructure.
Le dilemme de l’upgrade
Que faire lorsqu’une équipe de devs veut absolument la dernière version de Nginx, alors que votre plateforme propose celle d’il y a six mois ?
- Gérer du multi-versioning pour satisfaire tout le monde ?
- Refuser l’upgrade au risque de voir l’équipe partir en shadow IT ?
- Forcer tout le monde à upgrader, en espérant une rétrocompatibilité sans douleur ?
On voit bien que GitOps nous ramène inévitablement aux dilemmes classiques du produit : stabilité vs innovation.
Les stratégies du multi-environnement en GitOps
Autre sujet sensible : comment gérer plusieurs environnements sans sombrer dans le chaos ?
C’est un débat sans fin et les variations nécessaires d’un même composant selon l’environnement flirtent parfois avec le mystique. Plusieurs stratégies existent, mais aucune n’est parfaite :
- Une branche par environnement :
Mauvaise idée. Merge et duplication de code infernaux, maintenance cauchemardesque. - Un repo par environnement :
Bonne isolation, mais duplication de code massive, donc risque accru d’erreurs. - Un seul repo avec des variations dans les fichiers :
C’est l’approche d’ArgoCD, qui permet d’utiliser des générateurs pour récupérer des valeurs dynamiques sur les clusters Kubernetes et adapter les déploiements.
C’est la solution que nous avons retenue sur OXP, mais soyons honnêtes : c’est parfois un véritable casse-tête pour éviter les boulettes.
Conclusion
L'approche GitOps est un accélérateur indéniable, offrant des bénéfices concrets pour les équipes :
- Déploiement simplifié et rapide des nouvelles versions
- Collaboration accrue autour de Git Flow déjà maîtrisés dans l’entreprise
- Modularité des composants, favorisant la réutilisation et l’évolutivité
- Auditabilité et conformité renforcées
Mais tout n’est pas rose et cette approche vient avec son lot de défis épineux, obligeant parfois à relâcher le dogme du “tout Git” :
- La gestion des secrets ne peut pas reposer uniquement sur Git
- Certains produits ne supportent pas la gestion déclarative
- La gestion multi-environnement basée sur des fichiers partagés peut vite tourner au cauchemar
Nous recommandons bien sûr d’adopter cette méthodologie, mais ne croyez pas à la magie noire : aucun livre ne contient la recette parfaite. La mise au point de vos propres processus et bonnes pratiques nécessitera du temps, de la réflexion et une énergie considérable.
