Déclarer un Application ArgoCD à la main pour chaque service fonctionne très bien avec dix équipes. Avec cent, chaque nouveau microservice devient un ticket manuel, chaque changement de convention (ajout d’un label, d’une annotation) devient une modification à répliquer partout, et personne ne remarque qu’un Application a été oublié tant que le service en question ne se déploie plus. Le problème n’est pas ArgoCD : c’est l’absence de génération automatique là où la répétition manuelle devient elle-même la source d’erreur.

ApplicationSet : générer plutôt que déclarer

Un ApplicationSet ne décrit pas un déploiement, il décrit comment en générer plusieurs à partir d’une source de vérité : une liste explicite, le contenu d’un dossier Git, ou l’inventaire de clusters connus d’ArgoCD lui-même.

# Un Application par dossier détecté sous apps/, sans déclaration manuelle
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: team-services
spec:
  generators:
    - git:
        repoURL: https://github.com/acme/gitops-config.git
        revision: main
        directories:
          - path: apps/*
  template:
    metadata:
      name: "{{path.basename}}"
    spec:
      source:
        repoURL: https://github.com/acme/gitops-config.git
        path: "{{path}}"
      destination:
        namespace: "{{path.basename}}"

Ajouter un service revient à ajouter un dossier dans le dépôt de configuration : l’Application correspondante apparaît automatiquement, sans PR sur la définition ArgoCD elle-même. Un changement de convention se fait une fois dans le template, et se propage à tous les Applications générés.

Le vrai problème que ça déplace : l’isolation entre équipes

Générer automatiquement des Applications ne résout rien si chaque équipe peut, via son propre dépôt Git, définir un déploiement qui touche le namespace d’une autre équipe. Le contrôle ne se fait plus au niveau du déploiement individuel mais au niveau du périmètre que chaque équipe a le droit de toucher, ce qui est exactement le rôle d’un AppProject :

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: team-payments
spec:
  sourceRepos:
    - https://github.com/acme/payments-gitops.git
  destinations:
    - namespace: "payments-*"
      server: https://kubernetes.default.svc
  clusterResourceWhitelist: []   # aucune ressource cluster-scope autorisée
  namespaceResourceWhitelist:
    - group: "apps"
      kind: "Deployment"
    - group: ""
      kind: "Service"

Un AppProject restreint trois axes à la fois : quels dépôts Git peuvent servir de source, quels namespaces peuvent être ciblés, et quels types de ressources peuvent être créés. Sans cette contrainte, un ApplicationSet mal scopé permet à n’importe quelle équipe de déployer une ressource cluster-scope (une ClusterRole, par exemple) depuis son propre dépôt, ce qui rend le multi-tenant purement théorique.

Le piège du générateur trop permissif

Un générateur Git basé sur un pattern large (apps/*) fait confiance à la structure du dépôt pour délimiter les équipes. Si deux équipes partagent le même dépôt de configuration sans séparation stricte par sous-dossier et sans AppProject correspondant, n’importe quelle PR peut créer un Application qui cible le namespace d’une autre équipe. La séparation logique en apparence (des dossiers différents) ne vaut une isolation réelle que si elle est appliquée par un contrôle technique (AppProject + RBAC ArgoCD), jamais par convention seule.

L’app-of-apps : un cran de plus, un risque de plus

Le pattern app-of-apps (un ApplicationSet racine qui génère d’autres ApplicationSets) pousse l’automatisation un cran plus loin, utile pour des plateformes qui gèrent elles-mêmes leur propre outillage GitOps. Le risque grandit avec la profondeur : une erreur dans le générateur racine se propage à tous les niveaux en dessous, potentiellement plusieurs centaines d’Applications, avant qu’une boucle de réconciliation n’ait la chance de la corriger. Chaque niveau d’indirection ajouté doit se justifier par une réduction de charge opérationnelle réelle, pas par élégance architecturale. Cette même automatisation déclarative prolonge directement ce que décrit l’article sur le déploiement déclaratif avec ArgoCD, passé à l’échelle de dizaines d’équipes plutôt que d’une seule application.

À retenir

Un ApplicationSet résout un problème de répétition manuelle, pas un problème de sécurité : générer automatiquement des Applications sans AppProject correspondant ouvre une isolation multi-tenant purement décorative. La contrainte technique (dépôts autorisés, namespaces ciblables, types de ressources) doit exister au même niveau que la génération automatique, sinon l’automatisation propage les erreurs aussi vite qu’elle propage les bonnes configurations.