Ressources
GitOps en production : Argo CD ou Flux, santé des applications et nettoyage des orphelins
GitOps en production : choisir entre Argo CD et Flux, lire Synced, Healthy et Degraded, traiter la dérive et nettoyer les orphelins sans casser la production.
Par Corentin Mas, publié le · 24 min de lecture
Base d'expérience : Méthode et documentation officielle d'Argo CD 3.5.3 et de Flux 2.9.5 (documentation et code aux tags publiés), sans retour d'expérience client ni déploiement nommé.
Relecture factuelle : Claude Code (revue indépendante déléguée par Corentin Mas, 28/09/2026), le
Un cluster piloté en GitOps finit par poser les mêmes questions, rarement pendant la démonstration : pourquoi une application reste « Degraded » alors que ses pods répondent, pourquoi un composant retiré du dépôt tourne encore, pourquoi une dérive réapparaît après chaque synchronisation. Argo CD et Flux appliquent la même boucle de réconciliation, mais avec un vocabulaire d'état, une politique de suppression et une vision des objets non créés par eux qui diffèrent.
Faits datés
Ce guide tranche le choix entre les deux outils par des critères d'exploitation, puis traite ce qui fait tenir une plateforme après sa mise en service : lire santé et synchronisation, traiter la dérive sans l'éteindre, nettoyer les orphelins sans supprimer ce qui sert encore. Cette lecture est établie sur Argo CD 3.5.3 (dernière version stable, publiée le 14 septembre 2026) et sur Flux 2.9.5 (dernière version, publiée le 31 août 2026 : kustomize-controller 1.9.5, helm-controller 1.6.4) ; la documentation et le code cités ont été vérifiés le , aux tags de ces versions.
Vérifié le
La boucle de réconciliation : ce qu'elle garantit et ce qu'elle laisse ouvert
OpenGitOps, projet Sandbox de la CNCF (Cloud Native Computing Foundation), résume la méthode en quatre principes (version 1.0.0) : l'état désiré est déclaratif ; il est versionné et immuable, avec un historique complet ; des agents logiciels le tirent automatiquement depuis la source ; ces agents observent en continu l'état réel et tentent d'y appliquer l'état désiré. Argo CD et Flux implémentent cette boucle dans le cluster : un contrôleur lit une source (dépôt Git, dépôt Helm, artefact OCI), produit les manifestes, les compare à l'état vivant et applique l'écart.
Les deux outils divergent dès la correction de la dérive. Argo CD compare en continu, mais ne corrige une modification faite directement dans le cluster que si la synchronisation automatique est active avec selfHeal: true ; sinon, il l'affiche comme OutOfSync. Le kustomize-controller de Flux exécute à chaque intervalle (.spec.interval) un dry-run de server-side apply et corrige la dérive, sauf si la Kustomization est suspendue.
La boucle garantit que les objets déclarés et suivis convergent vers le dépôt, et qu'un écart devient visible. Elle laisse ouverts quatre sujets à traiter à part :
- Les objets qu'elle n'a jamais appliqués. Une ressource créée à la main n'entre ni dans le diff ni dans le prune ; le chapitre 5 y revient.
- Les données. Un
git revertreconstruit des déclarations, pas une base ni un volume : un service à état se restaure par ses propres sauvegardes. - Le retour arrière. La documentation d'Argo CD interdit le rollback d'une Application en synchronisation automatique : le retour arrière passe par un commit.
- La preuve fonctionnelle. Healthy signifie que les contrôles de santé passent, pas qu'un parcours utilisateur aboutit.
L'organisation des dépôts, l'amorçage d'un cluster et la gestion des secrets sont hors du périmètre de ce guide.
Argo CD ou Flux : critères de choix
Les deux projets couvrent l'essentiel : sources Git, Helm et OCI, Kustomize, synchronisation automatique, suppression des objets retirés, notifications. Ils diffèrent par leur modèle d'exploitation, que le tableau compare sans classement.
| Critère | Argo CD 3.5.3 | Flux 2.9.5 |
|---|---|---|
| Interface | Interface web, API et CLI ; une installation « core » sans interface ni SSO existe | CLI flux et objets Kubernetes, sans interface dans les contrôleurs ; interfaces tierces listées par le projet (Flux Operator, Headlamp, Backstage, Capacitor) |
| Unité de déploiement | Application (source, destination, projet), générée en série par ApplicationSet | Une source (GitRepository, OCIRepository, HelmRepository), puis une Kustomization ou une HelmRelease |
| Droits des humains | RBAC propre à Argo CD (argocd-rbac-cm, rôles de projet), utilisateurs via SSO ou comptes locaux | RBAC Kubernetes : agir sur un objet Flux est un droit sur l'API du cluster |
| Isolement des équipes | AppProject : dépôts, destinations et kinds autorisés ; synchronisation avec les droits du contrôleur, sauf impersonation (bêta depuis 3.5.0, destinationServiceAccounts) | spec.serviceAccountName impersonné ; verrouillage par --no-cross-namespace-refs, --default-service-account et --no-remote-bases |
| Helm | Rendu par helm template, sans release visible par helm ls ; hooks de test Helm non pris en charge ; Helm 4.2 depuis la 3.5 | helm-controller pilote de vraies releases, en Helm 4 depuis Flux 2.8 : installation, mise à niveau, tests, remédiation (RetryOnFailure ou RemediateOnFailure), désinstallation |
| OCI | Images OCI et charts Helm OCI comme source d'Application | OCIRepository et flux push artifact ; charts OCI recommandés pour les HelmRelease |
| Ordonnancement | Phases, vagues et hooks à l'intérieur d'une Application | dependsOn entre Kustomizations ou entre HelmReleases, avec readyExpr en CEL (Common Expression Language) |
| Santé | Contrôles intégrés (Go et bibliothèque Lua), personnalisables en Lua dans argocd-cm | kstatus ; healthChecks, wait et expressions CEL healthCheckExprs |
| Dérive | OutOfSync visible en continu, corrigé si selfHeal ; exclusions par ignoreDifferences | Kustomization corrigée à chaque intervalle, exclusions par .spec.ignore depuis 2.9 ; détection de dérive désactivée par défaut sur les HelmRelease |
| Orphelins | Surveillance par AppProject (orphanedResources) | Aucun équivalent dans la spécification ; prune limité à l'inventaire |
| Notifications | Argo CD Notifications : déclencheurs, modèles, catalogue | notification-controller : Provider, Alert, Receiver pour les webhooks entrants |
| Mise à jour d'images | Argo CD Image Updater, projet argoproj-labs distinct, présenté par son dépôt comme en développement actif et déconseillé pour les charges critiques | image-reflector-controller et image-automation-controller (API v1), qui committent dans Git |
Trois questions tranchent la plupart des cas.
Qui regarde l'état, et avec quels droits ? Si des équipes produit doivent voir l'état et déclencher des synchronisations sans accès direct à l'API du cluster, l'interface et le RBAC d'Argo CD répondent à ce besoin. Le prix est un second système de droits à gouverner, et un contrôleur qui, sans impersonation, synchronise avec ses propres privilèges : la documentation prévient qu'Argo CD compromis donne alors un accès cluster-admin. Flux s'appuie sur le RBAC du cluster ; il faut en revanche construire la lecture de l'état : événements, alertes, interface tierce.
Que doit garantir Helm ? Argo CD utilise Helm comme moteur de rendu : pre-install et pre-upgrade deviennent tous deux des hooks PreSync, et les hooks de test ne sont pas pris en charge. Une équipe qui dépend de helm test, des rollbacks Helm ou de l'historique des releases conservera cette sémantique avec le helm-controller de Flux.
Comment s'exprime l'ordre ? Argo CD ordonne les ressources d'une Application par vagues et hooks ; Flux ordonne des Kustomizations entières par dependsOn, qui attend que la dépendance soit prête. Le découpage des dépôts suit l'un ou l'autre modèle, et se révise mal après coup.
Deux contrôleurs qui appliquent le même objet se disputent ses champs : un seul outil GitOps par couche et par cluster reste la règle prudente.
Ce choix se tranche mieux sur un inventaire réel (équipes, charts, sources, droits) que sur une grille générique : nous choisissons l'outil après les règles de gouvernance qu'il doit appliquer, comme pour toute plateforme Kubernetes gouvernée.
Lire santé et synchronisation sans tout masquer
Trois signaux chez Argo CD, une condition chez Flux
Argo CD publie trois informations indépendantes. Le statut de synchronisation vaut Synced, OutOfSync ou Unknown. La phase de la dernière opération vaut Running, Succeeded, Failed, Error ou Terminating. La santé vaut Healthy, Suspended, Progressing, Missing, Degraded ou Unknown. La santé d'une Application est la pire de ses ressources immédiates, dans cet ordre, et elle ne s'hérite pas : un Deployment n'est pas malade parce qu'un de ses pods l'est. Depuis la 3.0, la santé de chaque ressource n'est plus écrite dans le status de l'Application : un script qui la lisait par kubectl doit passer par argocd app get ou réactiver controller.resource.health.persist.
Flux résume l'état dans des conditions compatibles kstatus : Ready à True, False ou Unknown, avec une raison (HealthCheckFailed, DependencyNotReady, PruneFailed, BuildFailed, ArtifactFailed), Reconciling pendant le travail et Stalled en cas de blocage ; une HelmRelease ajoute une condition Drifted quand la détection de dérive est active.
Tableau des états et de la première action
| Signal | Ce qu'il établit | Ce qu'il n'établit pas | Première action |
|---|---|---|---|
| Argo CD : Synced et Healthy | Ressources suivies conformes à Git, hors exclusions, et contrôles de santé passés | Qu'un parcours utilisateur fonctionne, ni qu'aucun objet non suivi n'existe | Recette fonctionnelle ; surveillance des orphelins |
| OutOfSync et Healthy | Un écart : commit non appliqué, dérive, mutation par un contrôleur, ou objet à supprimer | Que l'écart soit grave | argocd app diff ; classer l'écart : à synchroniser, à corriger dans Git, à exclure, à supprimer |
| Synced et Degraded | Tout est appliqué, mais une ressource signale un échec : ScaledObject à Ready False, dernier Job d'un CronJob en échec, HTTPRoute refusée | Que le service soit indisponible | argocd app get pour trouver la ressource ; corriger la cause, sinon exception nommée |
| Progressing qui ne finit pas | Un contrôle n'a pas conclu : Ingress sans status.loadBalancer, APIService indisponible | Qu'il suffise d'attendre | Lire le statut de la ressource ; corriger son contrôle de santé |
| Missing (Application) | Depuis 3.4, toutes les ressources manquent | Qu'une ressource isolée manque | Synchroniser ; alerter sur OutOfSync plutôt que sur Missing |
| Unknown avec ComparisonError | Argo CD ne sait pas produire ou comparer les manifestes | L'état réel des workloads | Lire les conditions ; réparer la source, l'accès au dépôt ou au cluster |
| Opération Failed ou Error | La dernière synchronisation a échoué | Que l'état antérieur ait été rétabli | argocd app get --show-operation, corriger, resynchroniser |
| OrphanedResourceWarning, SharedResourceWarning | Objets non suivis dans le namespace de destination ; objet revendiqué par plusieurs Applications | Qui les a créés | Chapitre 5 ; FailOnSharedResource=true pour bloquer le partage |
| Flux : Ready False, HealthCheckFailed | Manifestes appliqués, mais un contrôle a échoué ou expiré (timeout) | Quelle ressource, sans lire le message | flux events --for Kustomization/<nom> ; flux tree kustomization <nom> |
| Flux : Ready False, DependencyNotReady | Une dépendance dependsOn n'est pas prête : rien n'est appliqué | Que cette Kustomization soit fautive | Remonter la chaîne des dépendances |
| HelmRelease : Drifted True | Dérive détectée en mode warn ou enabled | Qu'elle ait été corrigée : le mode warn se contente de signaler | Lire l'événement ; corriger, ou ignorer par une règle ciblée |
D'où vient un Degraded chez Argo CD
Argo CD évalue lui-même quelques types : Deployment, StatefulSet, DaemonSet et ReplicaSet sont sains quand la génération désirée est observée et que les réplicas à jour atteignent le nombre voulu ; un PVC doit être Bound ; un Service LoadBalancer et un Ingress doivent publier une adresse dans status.loadBalancer.ingress. Depuis la 3.2, un CronJob dont le dernier Job a échoué est Degraded. Pour les ressources personnalisées, Argo CD embarque une bibliothèque de scripts Lua par groupe et kind. Deux exemples lus au tag v3.5.3 : un ScaledObject KEDA est Degraded si sa condition Ready vaut False ou si Fallback vaut True ; une HTTPRoute Gateway API l'est si un parent la refuse (Accepted à False) ou si ses références ne se résolvent pas (ResolvedRefs à False). Un APIService n'est jamais Degraded : sans condition Available à True, il reste Progressing.
Exemple : si la source de métriques d'un ScaledObject KEDA devient indisponible, sa condition Ready peut passer à False ou Fallback à True, et son Application passe Degraded. Le signal est exact pour l'autoscaling ; il n'établit pas, à lui seul, que le service est indisponible. La réponse adaptée est de rétablir ou de remplacer la source de métriques, pas de couper l'alerte.
Écrire un contrôle de santé Lua
Quand une ressource personnalisée n'a pas de contrôle intégré, ou qu'il se trompe, un script Lua déclaré dans argocd-cm prend la main, y compris sur les contrôles écrits en Go. La documentation recommande de s'appuyer sur observedGeneration pour éviter les oscillations. L'exemple vise un kind fictif :
# Exemple synthétique : extrait de argocd-cm, Argo CD 3.5.3
data:
resource.customizations.health.plateforme.example.net_BaseDeDonnees: |
hs = {}
if obj.status == nil or obj.status.conditions == nil then
hs.status = "Progressing"
hs.message = "Statut pas encore publié par le contrôleur"
return hs
end
if obj.status.observedGeneration ~= nil and obj.status.observedGeneration ~= obj.metadata.generation then
hs.status = "Progressing"
hs.message = "Modification pas encore observée par le contrôleur"
return hs
end
for i, condition in ipairs(obj.status.conditions) do
if condition.type == "Ready" then
hs.message = condition.message
if condition.status == "True" then
hs.status = "Healthy"
elseif condition.status == "False" then
hs.status = "Degraded"
else
hs.status = "Progressing"
end
return hs
end
end
hs.status = "Progressing"
hs.message = "Condition Ready absente"
return hsLes bibliothèques Lua standard sont désactivées par défaut (resource.customizations.useOpenLibs.<groupe>_<kind>). Le script se teste hors cluster contre un objet exporté, avant tout déploiement : argocd admin settings resource-overrides health ./objet.yaml --argocd-cm-path ./argocd-cm.yaml.
Contrôles de santé chez Flux
Flux évalue la santé avec kstatus. .spec.healthChecks nomme les objets à attendre ; .spec.wait: true attend tous les objets appliqués et ignore alors healthChecks ; .spec.timeout borne l'attente. Pour une ressource personnalisée, .spec.healthCheckExprs fournit des expressions CEL évaluées dans l'ordre inProgress, failed, current.
# Exemple synthétique : Flux 2.9.5, kustomize-controller 1.9.5
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: catalogue
namespace: flux-system
spec:
interval: 10m
retryInterval: 2m
timeout: 5m
sourceRef:
kind: GitRepository
name: plateforme
path: ./clusters/production/catalogue
prune: true
dependsOn:
- name: operateurs-donnees
healthChecks:
- apiVersion: apps/v1
kind: Deployment
name: catalogue-api
namespace: catalogue
- apiVersion: plateforme.example.net/v1
kind: BaseDeDonnees
name: catalogue
namespace: catalogue
healthCheckExprs:
- apiVersion: plateforme.example.net/v1
kind: BaseDeDonnees
# suppose que le contrôleur publie status.observedGeneration
inProgress: "status.observedGeneration != metadata.generation"
failed: "status.conditions.exists(c, c.type == 'Ready' && c.status == 'False')"
current: "status.conditions.exists(c, c.type == 'Ready' && c.status == 'True')"L'exemple emploie exists : chaque expression ne devient vraie que si une condition Ready existe avec le statut attendu. Une expression qui lit un champ absent (par exemple status avant la première publication par le contrôleur) échoue à l'évaluation et fait attendre la Kustomization jusqu'à timeout : tester les expressions sur un objet réel. prune: true est un champ obligatoire, pas une valeur par défaut : chaque Kustomization déclare explicitement son choix.
Masquer au plus étroit
Face à un état faux ou inutile, l'ordre de préférence est constant :
- Corriger la cause : source de métrique, configuration, contrôleur.
- Corriger le contrôle de santé du kind, en Lua ou en CEL.
- Exclure une ressource nommée : annotation
argocd.argoproj.io/ignore-healthcheck: "true"côté Argo CD ; retrait dehealthCheckscôté Flux. - Ne jamais couper l'alerte d'une Application entière, ni celle d'une racine qui relaie la santé de ses enfants.
Dérive : corriger, exclure étroitement ou déléguer
La documentation d'Argo CD énumère les causes d'un OutOfSync qui survit à une synchronisation réussie : champ inconnu retiré par l'API, prune désactivé, contrôleur ou webhook de mutation qui réécrit l'objet, fonction Helm aléatoire comme randAlphaNum, HPA qui réordonne spec.metrics. Chaque cause appelle une réponse différente ; une exclusion ne vaut que si un autre gestionnaire possède réellement le champ.
Côté Argo CD
Essayer le Server-Side Diff avant d'exclure. Stable depuis la 3.1, il calcule l'état prévu par un server-side apply en dry-run, si bien que les contrôleurs d'admission participent au diff. Il s'active pour toute l'instance (controller.diff.server.side: "true" dans argocd-cmd-params-cm) ou par Application (annotation argocd.argoproj.io/compare-options: ServerSideDiff=true) ; les webhooks de mutation n'y entrent qu'avec IncludeMutationWebhook=true.
Exclure au champ près. ignoreDifferences se restreint par groupe, kind, nom et namespace, et vise un champ par pointeur JSON, expression jq ou gestionnaire de managedFields ; RespectIgnoreDifferences=true étend l'exclusion à la synchronisation, pour les ressources qui existent déjà. La clé resource.customizations.ignoreDifferences.all, qui vaut pour toutes les Applications, est la sourdine globale à éviter. Un HPA qui réordonne spec.metrics se corrige d'abord dans Git, en écrivant les métriques dans l'ordre retenu par le contrôleur ; à défaut, par une exclusion bornée à ce kind et à ce champ, jamais par une règle .all.
Connaître la sémantique de l'auto-sync. Une synchronisation automatique ne part que si l'Application est OutOfSync, une seule fois par couple commit et paramètres ; un échec sur le même commit n'est pas retenté, sauf politique retry configurée. Avec selfHeal: true, une modification faite dans le cluster déclenche une nouvelle synchronisation ; les tentatives successives sont espacées par un backoff exponentiel (par défaut 2 s, facteur 3, plafond 300 s : --self-heal-backoff-timeout-seconds, --self-heal-backoff-factor, --self-heal-backoff-cap-seconds). Pour une intervention manuelle urgente, spec.syncPolicy.automated.enabled: false suspend l'auto-sync sans perdre prune ni selfHeal ; sur une Application générée, l'ApplicationSet écrase ce changement, sauf ignoreApplicationDifferences sur /spec/syncPolicy.
Vérifier la méthode de suivi. Depuis la 3.0, Argo CD suit ses ressources par défaut avec l'annotation argocd.argoproj.io/tracking-id. Le mode label, historique, tronque les noms à 63 caractères et entre en conflit avec les charts qui écrivent app.kubernetes.io/instance. Une annotation qui ne désigne pas l'objet qui la porte (copie par un autre outil) le retire de la comparaison et du prune. Après un passage du mode label au mode annotation, la documentation recommande de synchroniser chaque Application avant toute suppression, sous peine de laisser des orphelins.
Côté Flux
Le kustomize-controller applique tout en server-side apply et corrige la dérive à chaque intervalle. Flux 2.9 a ajouté .spec.ignore : des pointeurs JSON, bornés par un sélecteur target, exclus de la détection et de la correction. Sans target, la règle vaut pour tous les objets de la Kustomization, et un champ ignoré n'est plus appliqué depuis Git, même quand Git change.
Par objet, l'annotation kustomize.toolkit.fluxcd.io/ssa choisit la politique : Override par défaut, Merge pour conserver les champs ajoutés par d'autres outils, IfNotPresent pour créer sans jamais mettre à jour, Ignore pour ne rien appliquer.
Pour Helm, spec.driftDetection.mode vaut disabled s'il n'est pas précisé. warn compare le manifeste de la release au cluster par dry-run et pose la condition Drifted ; enabled corrige en plus. Les règles ignore et l'annotation helm.toolkit.fluxcd.io/driftDetection: disabled bornent la comparaison.
La propriété des champs après un server-side apply, et le sort d'un champ retiré du manifeste, sont détaillés dans « Piloter la configuration Keycloak en GitOps : adoption, dérive et suppression de champs ».
Nettoyer les orphelins sans casser la production
Trois catégories à ne pas confondre
- Ressource suivie mais absente de Git. Argo CD la voit comme superflue et la propose au prune ; Flux la trouve dans son inventaire mais pas dans la nouvelle révision.
- Ressource non suivie dans un namespace géré. C'est l'orpheline au sens d'Argo CD : un objet de premier niveau, sans ownerReference, qui n'appartient à aucune Application existante.
- Objet de contrôle hors gouvernance. Une Application ou une Kustomization créée à la main continue de réconcilier ses propres ressources, hors de toute revue.
Supprimer ce qui est suivi : prune et options
Chez Argo CD, la synchronisation automatique ne supprime rien par défaut : il faut automated.prune: true, ou un argocd app sync --prune manuel. Même avec prune, une synchronisation automatique refuse de vider entièrement une Application, sauf allowEmpty: true. Par ressource, Prune=false conserve l'objet et laisse l'Application OutOfSync ; Prune=confirm maintient l'opération en état Syncing jusqu'à confirmation ; IgnoreExtraneous retire l'objet du calcul de synchronisation, sans effet sur la santé. PrunePropagationPolicy vaut foreground par défaut, et accepte background ou orphan. Replace=true et Force=true, que la documentation qualifie de potentiellement destructeurs, n'ont pas leur place dans un nettoyage.
Chez Flux, le prune porte sur .status.inventory, la liste des objets appliqués avec succès, qui portent les étiquettes kustomize.toolkit.fluxcd.io/name et kustomize.toolkit.fluxcd.io/namespace. L'étiquette ou l'annotation kustomize.toolkit.fluxcd.io/prune: disabled protège un Namespace, un PVC ou un PV. Avec prune: true, flux diff kustomization liste les objets qui seront supprimés, marqués deleted.
Détecter ce qui n'est pas suivi
Argo CD active la surveillance des orphelins par projet :
# Exemple synthétique : projet d'une équipe produit, Argo CD 3.5.3
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: produit-catalogue
namespace: argocd
spec:
description: Applications de l'équipe catalogue
sourceRepos:
- https://git.example.net/produit/catalogue-deploiement.git
destinations:
- server: https://kubernetes.default.svc
namespace: catalogue
clusterResourceWhitelist: []
orphanedResources:
warn: true
ignore:
# Secrets TLS écrits par cert-manager, sans ownerReference
- kind: Secret
name: "*-tls"Un bloc orphanedResources: {} suffit à activer la détection : filtre « Show Orphaned » de l'interface, argocd app resources <app> --orphaned et métrique argocd_app_orphaned_resources_count. warn: true ajoute la condition OrphanedResourceWarning. Ne sont jamais orphelins le ServiceAccount default, la ConfigMap kube-root-ca.crt, le Service kubernetes du namespace default et les kinds refusés par le projet ; ignore complète la liste, avec des motifs glob. La détection porte sur le namespace de destination de chaque Application, et la documentation prévient de son coût sur un namespace chargé comme kube-system.
Une limite se lit dans le code 3.5.3 : une ressource dont l'annotation de suivi nomme une Application existante n'est pas orpheline. Une Application créée à la main n'appartient pas aux manifestes de la racine et échappe donc à son diff comme à son prune ; ses ressources, qui nomment cette Application, n'apparaissent pas non plus comme orphelines. Seul un inventaire des Applications, comparé aux manifestes de la racine, la révèle.
La spécification Kustomization de Flux ne décrit pas d'équivalent. Les objets sans étiquette kustomize.toolkit.fluxcd.io/name se listent à la main : kubectl get deploy,svc,cm -n catalogue -l '!kustomize.toolkit.fluxcd.io/name'.
Supprimer l'objet de contrôle lui-même
Chez Argo CD, le finalizer resources-finalizer.argocd.argoproj.io porte la suppression en cascade ; sans lui, ou avec argocd app delete <app> --cascade=false, seul l'objet Application disparaît et ses ressources restent en place. D'après la FAQ, Argo CD ne peut pas supprimer une Application dont il ne sait plus produire les manifestes : il faut rétablir la source, ou supprimer sans cascade puis nettoyer à la main.
Chez Flux, le finalizer finalizers.fluxcd.io applique .spec.deletionPolicy : MirrorPrune par défaut, qui supprime les objets si prune est vrai et les abandonne sinon ; Delete ; WaitForTermination, qui attend leur disparition dans la limite de timeout ; Orphan. D'après le code du kustomize-controller 1.9.5, une Kustomization suspendue ne supprime rien à sa suppression ; si le compte de service à impersonner a disparu, Flux abandonne les objets, émet un événement d'erreur et retire son finalizer. Supprimer une HelmRelease désinstalle la release, sauf si elle est suspendue.
Retirer un composant de plateforme devenu inutile
Retirer un composant de plateforme (opérateur, contrôleur d'admission) cumule des risques que la documentation et le code décrivent séparément :
- Une Application hors des manifestes de la racine survit au retrait (voir plus haut).
- Une Application dont la source a disparu ne se supprime plus en cascade (FAQ Argo CD).
- Un APIService qui pointe vers un service supprimé reste Progressing.
- Les consommateurs du composant (métriques, webhooks, CRD) perdent leur dépendance.
La procédure qui en découle vaut pour tout composant de plateforme :
- Inventorier les consommateurs : sidecars injectés, métriques lues (autoscaling, alertes, tableaux de bord), webhooks, APIServices, CRD et leurs instances.
- Donner un propriétaire à chaque objet de contrôle : l'adopter dans la racine, ou le supprimer en cascade tant que sa source existe ; retirer la source ensuite.
- Lire le diff :
argocd app diffetflux diff kustomizationmontrent ce qui sera supprimé. - Supprimer par couches : workloads, webhooks, RBAC, APIServices, puis CRD sans instance restante, puisque supprimer une CRD supprime ses objets.
- Vérifier : santé, orphelins, APIServices indisponibles, finalizers restants, namespaces en Terminating. Sur un namespace bloqué, la condition
NamespaceDeletionDiscoveryFailuresignale une erreur de découverte des API, dont un APIService résiduel est une cause plausible.
nettoyer une ressource sans casser la production
Arbre de décision qui mène une ressource candidate au nettoyage vers le prune, l'adoption, l'observation ou la suppression par couches, puis vers une vérification commune.
Schéma défilable horizontalement ; sa version textuelle complète suit.
Lire le schéma sous forme textuelle
- Pour une ressource candidate au nettoyage, la première question est de savoir si une Application Argo CD ou une Kustomization Flux la suit.
- Si elle est suivie et retirée de Git, on lit d'abord le diff, puis on vérifie si elle porte des données ou des dépendants (PVC, CRD, Namespace).
- Si c'est le cas, on la protège par
Prune=confirm,Prune=falseoukustomize.toolkit.fluxcd.io/prune: disabled, avec une décision écrite ; sinon, le prune s'exécute dans la fenêtre prévue. - Si elle n'est pas suivie et porte une ownerReference, on la laisse au contrôleur qui la possède.
- Sans ownerReference, on identifie son auteur par l'annotation de suivi, les étiquettes et les
managedFields, puis on vérifie si elle est encore consommée. - Si elle l'est, on l'adopte en la déclarant dans Git puis en synchronisant.
- Si on ne sait pas, on exporte son manifeste, on l'isole et on observe, puis on revient à la question de la consommation.
- Si elle ne l'est plus, on supprime l'objet de contrôle tant que sa source existe, puis les ressources par couches.
- Toutes les branches se terminent par la même vérification : santé, orphelins, APIServices, finalizers et namespaces.
Les commandes de lecture, à exécuter avant et après :
# Argo CD 3.5.3
argocd app get catalogue --refresh
argocd app get catalogue --show-operation
argocd app diff catalogue --server-side-diff
argocd app resources catalogue --orphaned
argocd app sync catalogue --prune --dry-run
# Flux 2.9.5
flux get kustomizations -A --status-selector ready=false
flux diff kustomization catalogue --path ./clusters/production/catalogue
flux tree kustomization catalogue
flux events --for Kustomization/catalogue -n flux-system
# Kubernetes : résidus fréquents
kubectl get apiservices \
-o custom-columns='NAME:.metadata.name,SERVICE:.spec.service.name,AVAILABLE:.status.conditions[?(@.type=="Available")].status'
kubectl get namespace catalogue \
-o jsonpath='{range .status.conditions[*]}{.type}={.status} {.message}{"\n"}{end}'argocd app diff renvoie par défaut un code non nul dès qu'une différence existe, et flux diff kustomization renvoie 1 dans le même cas : les deux commandes s'intègrent à une revue de fusion. Sur une plateforme en service, un tel nettoyage se traite comme un changement de fiabilité mesuré, appliqué puis vérifié : c'est la démarche de l'optimisation d'une plateforme Kubernetes.
Sources officielles et limites de lecture
Les affirmations sur Argo CD renvoient à la documentation et au code du tag v3.5.3, le code servant quand la documentation se tait (calcul des orphelins, santé d'un APIService, contrôles KEDA et Gateway API). Celles sur Flux renvoient aux spécifications et au code des versions livrées par Flux 2.9.5, et aux pages du site du projet. Documentation et comportements changent à chaque version : une procédure d'exploitation doit citer la version installée.
Ce guide ne mesure ni la charge des contrôleurs ni le coût de la surveillance des orphelins, et ne traite ni la gestion des secrets, ni les fenêtres de synchronisation, ni le multi-cluster, ni les Applications hors du namespace d'Argo CD. Les manifestes et commandes sont synthétiques et ne décrivent aucun déploiement client ; le script Lua et les expressions CEL se testent sur vos propres objets avant usage. Healthy n'établit jamais qu'un service répond : la recette fonctionnelle reste un contrôle distinct.
Pour la propriété des champs et la suppression d'un champ retiré du manifeste, la suite logique est « Piloter la configuration Keycloak en GitOps : adoption, dérive et suppression de champs ».
Sources
- GitOps Principles v1.0.0, OpenGitOps, https://github.com/open-gitops/documents/blob/v1.0.0/PRINCIPLES.md, consulté le 28/09/2026.
- OpenGitOps project (projet Sandbox de la CNCF), open-gitops/project sur GitHub, https://github.com/open-gitops/project, consulté le 28/09/2026.
- Release v3.5.3, argoproj/argo-cd sur GitHub, https://github.com/argoproj/argo-cd/releases/tag/v3.5.3, consulté le 28/09/2026.
- Release v2.9.5 (versions des contrôleurs), fluxcd/flux2 sur GitHub, https://github.com/fluxcd/flux2/releases/tag/v2.9.5, consulté le 28/09/2026.
- Announcing Flux 2.9 GA, Flux, https://fluxcd.io/blog/2026/06/flux-v2.9.0/, consulté le 28/09/2026.
- Announcing Flux 2.8 GA, Flux, https://fluxcd.io/blog/2026/02/flux-v2.8.0/, consulté le 28/09/2026.
- Selective drift correction with ignore rules, Flux, https://fluxcd.io/blog/2026/08/ignore-rules-drift-detection/, consulté le 28/09/2026.
- Getting Started (installation core sans interface ni SSO), Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/getting_started.md, consulté le 28/09/2026.
- RBAC Configuration, Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/operator-manual/rbac.md, consulté le 28/09/2026.
- Application Sync using impersonation, Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/operator-manual/app-sync-using-impersonation.md, consulté le 28/09/2026.
- Helm (rendu par helm template, hooks Helm), Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/user-guide/helm.md, consulté le 28/09/2026.
- OCI, Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/user-guide/oci.md, consulté le 28/09/2026.
- Notifications Overview, Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/operator-manual/notifications/index.md, consulté le 28/09/2026.
- Argo CD Image Updater (README), argoproj-labs sur GitHub, https://github.com/argoproj-labs/argocd-image-updater, consulté le 28/09/2026.
- Resource Health, Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/operator-manual/health.md, consulté le 28/09/2026.
- v2.14 to 3.0 (suivi par annotation, santé hors du statut), Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/operator-manual/upgrading/2.14-3.0.md, consulté le 28/09/2026.
- v3.1 to 3.2 (CronJob Health), Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/operator-manual/upgrading/3.1-3.2.md, consulté le 28/09/2026.
- v3.3 to 3.4 (Applications with Missing health status), Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/operator-manual/upgrading/3.3-3.4.md, consulté le 28/09/2026.
- v3.4 to 3.5 (Helm 4.2.0), Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/operator-manual/upgrading/3.4-3.5.md, consulté le 28/09/2026.
- FAQ (Progressing, suppression d'une Application sans source), Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/faq.md, consulté le 28/09/2026.
- Diffing Customization, Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/user-guide/diffing.md, consulté le 28/09/2026.
- Diff Strategies (Server-Side Diff), Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/user-guide/diff-strategies.md, consulté le 28/09/2026.
- Compare Options (IgnoreExtraneous), Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/user-guide/compare-options.md, consulté le 28/09/2026.
- Automated Sync Policy, Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/user-guide/auto_sync.md, consulté le 28/09/2026.
- Controlling Resource Modification (Allow temporarily toggling auto-sync), Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/operator-manual/applicationset/Controlling-Resource-Modification.md, consulté le 28/09/2026.
- Resource Tracking, Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/user-guide/resource_tracking.md, consulté le 28/09/2026.
- Sync Options, Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/user-guide/sync-options.md, consulté le 28/09/2026.
- Orphaned Resources Monitoring, Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/user-guide/orphaned-resources.md, consulté le 28/09/2026.
- App Deletion, Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/user-guide/app_deletion.md, consulté le 28/09/2026.
- Metrics, Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/operator-manual/metrics.md, consulté le 28/09/2026.
- Références des commandes argocd app diff, get, resources et sync, Argo CD, https://github.com/argoproj/argo-cd/tree/v3.5.3/docs/user-guide/commands, consulté le 28/09/2026.
- argocd admin settings resource-overrides health Command Reference, Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/user-guide/commands/argocd_admin_settings_resource-overrides_health.md, consulté le 28/09/2026.
- controller/appcontroller.go au tag v3.5.3 (calcul des ressources orphelines), argoproj/argo-cd sur GitHub, https://github.com/argoproj/argo-cd/blob/v3.5.3/controller/appcontroller.go, consulté le 28/09/2026.
- resource_customizations/keda.sh/ScaledObject/health.lua au tag v3.5.3, argoproj/argo-cd sur GitHub, https://github.com/argoproj/argo-cd/blob/v3.5.3/resource_customizations/keda.sh/ScaledObject/health.lua, consulté le 28/09/2026.
- resource_customizations/gateway.networking.k8s.io/HTTPRoute/health.lua au tag v3.5.3, argoproj/argo-cd sur GitHub, https://github.com/argoproj/argo-cd/blob/v3.5.3/resource_customizations/gateway.networking.k8s.io/HTTPRoute/health.lua, consulté le 28/09/2026.
- gitops-engine/pkg/health/health_apiservice.go au tag v3.5.3, argoproj/argo-cd sur GitHub, https://github.com/argoproj/argo-cd/blob/v3.5.3/gitops-engine/pkg/health/health_apiservice.go, consulté le 28/09/2026.
- pkg/apis/application/v1alpha1/types.go au tag v3.5.3 (statuts de synchronisation, conditions), argoproj/argo-cd sur GitHub, https://github.com/argoproj/argo-cd/blob/v3.5.3/pkg/apis/application/v1alpha1/types.go, consulté le 28/09/2026.
- gitops-engine/pkg/sync/common/types.go au tag v3.5.3 (phases d'opération), argoproj/argo-cd sur GitHub, https://github.com/argoproj/argo-cd/blob/v3.5.3/gitops-engine/pkg/sync/common/types.go, consulté le 28/09/2026.
- Kustomization (API kustomize.toolkit.fluxcd.io/v1), fluxcd/kustomize-controller sur GitHub, https://github.com/fluxcd/kustomize-controller/blob/v1.9.5/docs/spec/v1/kustomizations.md, consulté le 28/09/2026.
- internal/controller/kustomization_controller.go au tag v1.9.5 (finalizer, politique de suppression, Kustomization suspendue, compte de service absent), fluxcd/kustomize-controller sur GitHub, https://github.com/fluxcd/kustomize-controller/blob/v1.9.5/internal/controller/kustomization_controller.go, consulté le 28/09/2026.
- Helm Releases (API helm.toolkit.fluxcd.io/v2), fluxcd/helm-controller sur GitHub, https://github.com/fluxcd/helm-controller/blob/v1.6.4/docs/spec/v2/helmreleases.md, consulté le 28/09/2026.
- api/v2/helmrelease_types.go et internal/controller/helmrelease_controller.go au tag v1.6.4 (mode de dérive par défaut, désinstallation à la suppression), fluxcd/helm-controller sur GitHub, https://github.com/fluxcd/helm-controller/blob/v1.6.4/api/v2/helmrelease_types.go et https://github.com/fluxcd/helm-controller/blob/v1.6.4/internal/controller/helmrelease_controller.go, consulté le 28/09/2026.
- Multi-tenancy lockdown, Flux, https://fluxcd.io/flux/installation/configuration/multitenancy/, consulté le 28/09/2026.
- Image Automation Controllers, Flux, https://fluxcd.io/flux/components/image/, consulté le 28/09/2026.
- Spécification de l'API notification (Provider, Alert, Receiver), fluxcd/notification-controller sur GitHub, https://github.com/fluxcd/notification-controller/tree/v1.9.4/docs/spec, consulté le 28/09/2026.
- Flux Ecosystem (Flux UIs), Flux, https://fluxcd.io/ecosystem/, consulté le 28/09/2026.
- cmd/flux (diff kustomization, get, tree, events, push artifact) et internal/build/diff.go au tag v2.9.5, fluxcd/flux2 sur GitHub, https://github.com/fluxcd/flux2/tree/v2.9.5/cmd/flux et https://github.com/fluxcd/flux2/blob/v2.9.5/internal/build/diff.go, consulté le 28/09/2026.
- ssa/manager.go au tag ssa/v0.76.2, version utilisée par kustomize-controller 1.9.5 (étiquettes de propriétaire), fluxcd/pkg sur GitHub, https://github.com/fluxcd/pkg/blob/ssa/v0.76.2/ssa/manager.go, consulté le 28/09/2026.
- Garbage Collection (propagation foreground, background, orphan), Kubernetes, https://kubernetes.io/docs/concepts/architecture/garbage-collection/, consulté le 28/09/2026.
- core/v1/types.go (NamespaceConditionType, NamespaceDeletionDiscoveryFailure), kubernetes/api sur GitHub, https://github.com/kubernetes/api/blob/master/core/v1/types.go, consulté le 28/09/2026.
- Extend the Kubernetes API with CustomResourceDefinitions (Delete a CustomResourceDefinition), Kubernetes, https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/, consulté le 28/09/2026.
- argocd-application-controller Command Reference (options de self-heal), Argo CD, https://github.com/argoproj/argo-cd/blob/v3.5.3/docs/operator-manual/server-commands/argocd-application-controller.md, consulté le 28/09/2026.