Exploiter Argo CD
Pourquoi
Installer Argo CD prend une heure. L'exploiter, c'est pour des années : il faut y faire entrer les applications qui existaient avant lui, savoir qu'une synchronisation a échoué la nuit sans regarder l'interface, le mettre à jour quatre fois par an, survivre à la perte de son cluster, et décider comment les nouvelles images arrivent dans Git. Cette dernière leçon rassemble ce qui sépare une démonstration d'une plateforme, avec deux incidents réels vécus chez Lyneko lors de la mise en place d'Argo CD, et ce qu'ils ont appris.
Les concepts
Exploiter Argo CD, c'est surveiller deux choses distinctes :
- Les applications vues par Argo CD : sont-elles synchronisées, saines, et les synchronisations réussissent-elles ? C'est le rôle des notifications et des métriques
argocd_app_*. - Argo CD lui-même : ses composants répondent-ils, joignent-ils Git et les clusters, ont-ils assez de mémoire ? C'est le rôle des métriques des composants et de la supervision Kubernetes habituelle.
Une panne d'Argo CD n'arrête pas les applications : elles continuent de tourner telles qu'elles sont. Mais plus rien ne se déploie, plus rien ne se répare, et une dérive passe inaperçue. C'est une panne silencieuse, d'où l'importance de la surveiller explicitement.
En pratique
Adopter une release Helm existante
Avant Argo CD, les applications de Lyneko étaient déployées par helm upgrade --install depuis la CI. Les faire passer sous Argo CD, c'est retirer à Helm la propriété de ressources qui tournent, sans les supprimer.
L'incident. La première adoption a suivi une idée qui semblait sûre : poser l'annotation helm.sh/resource-policy: keep sur toutes les ressources vivantes avec kubectl annotate, puis lancer helm uninstall, qui est censé conserver les ressources ainsi annotées. Helm n'a conservé qu'une ressource, un volume persistant dont l'annotation figurait dans le chart. Tout le reste (Deployments, StatefulSet, Services, Ingress, certificat, ExternalSecrets) a été supprimé, et l'application, utilisée par un client, est tombée jusqu'à ce qu'une synchronisation d'Argo CD la recrée, une à deux minutes plus tard. Aucune donnée perdue : les volumes avaient l'annotation dans le chart, une classe de stockage en Retain, et le StatefulSet une politique de rétention de ses PVC à Retain.
L'explication. helm uninstall évalue helm.sh/resource-policy sur le manifeste enregistré dans le secret de release de Helm, pas sur les objets du cluster. Une annotation posée à la main sur un objet vivant n'existe pas pour lui. Pour qu'elle compte, il faut l'ajouter dans le chart et faire un helm upgrade, afin qu'elle entre dans le manifeste enregistré.
La méthode sûre, validée ensuite sur plusieurs applications, sans aucun redémarrage :
- Épingler dans Git la version réellement déployée. Si la CI passait
--set image.tag=<sha>, levalues.yamlde Git dit autre chose (souventlatest), et Argo CD rendrait la mauvaise version. - Créer l'Application sans
syncPolicy: Argo CD compare, mais n'agit pas. - Vérifier que la différence est vide (
argocd app diff, ouhelm templatecomparé à l'existant parkubectl diff). La seule différence acceptable est l'annotation de suivi d'Argo CD. - Synchroniser. Argo CD ajoute son annotation
argocd.argoproj.io/tracking-id; le gabarit des pods ne change pas, donc aucun pod ne redémarre. - Retirer Helm en supprimant seulement sa comptabilité, les secrets de release :
kubectl delete secret -n <namespace> -l owner=helm,name=<release>. Les ressources ne sont pas touchées. - Retirer le déploiement de la CI. Sinon, CI et Argo CD se battent ; chez Lyneko, le premier
helm upgradede la CI après l'adoption a d'ailleurs échoué, faute de secret de release (secrets "sh.helm.release.v1.<release>.v11" not found). La CI se contente désormais d'écrire la nouvelle version dans Git, et n'a plus besoin d'identifiant du cluster.
Les annotations meta.helm.sh/release-name et meta.helm.sh/release-namespace, et l'étiquette app.kubernetes.io/managed-by: Helm, restent sur les objets après l'adoption : elles sont inoffensives, mais un helm install du même nom pourrait de nouveau revendiquer ces ressources.
L'ordre est voulu : Argo CD synchronise avant que Helm ne lâche, et Helm reste une solution de repli tant qu'Argo CD n'a pas prouvé qu'il gère les ressources.
Caution
Pendant une adoption, laissez prune désactivé. Une ressource du chart oubliée dans Git (un volume persistant, par exemple) serait sinon supprimée à la première synchronisation automatique. Chez Lyneko, prune reste désactivé sur les applications qui ont des PVC ; pour l'activer, posez d'abord argocd.argoproj.io/sync-options: Prune=false sur les PVC.
Être prévenu
Le contrôleur de notifications fait partie d'Argo CD depuis la version 2.3. Il réagit à des déclencheurs (conditions sur l'état d'une Application), met en forme un modèle, et l'envoie à un service (courriel, Slack, Teams, Google Chat, Mattermost, webhook générique...). Le catalogue officiel fournit les déclencheurs courants, à installer une fois :
kubectl apply -n argocd --server-side --force-conflicts \
-f https://raw.githubusercontent.com/argoproj/argo-cd/v3.5.3/notifications_catalog/install.yaml| Déclencheur | Quand |
|---|---|
on-sync-failed | une synchronisation a échoué |
on-health-degraded | l'application est devenue Degraded |
on-sync-status-unknown | l'état de synchronisation est Unknown (erreur de rendu, cluster injoignable) |
on-deployed | synchronisée et saine, une fois par commit |
on-sync-succeeded, on-sync-running, on-created, on-deleted | les autres étapes |
Pour un espace Google Chat, l'URL du webhook entrant est un secret : elle va dans argocd-notifications-secret (produit par External Secrets, leçon 8), et la configuration la référence :
# argocd-notifications-cm (extrait)
data:
service.googlechat: |
webhooks:
plateforme: $googlechat-plateformeL'abonnement se pose par annotation, sur une Application ou, mieux, sur un AppProject pour couvrir toutes ses applications :
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: signalements
annotations:
notifications.argoproj.io/subscribe.on-sync-failed.googlechat: plateforme
notifications.argoproj.io/subscribe.on-health-degraded.googlechat: plateforme
notifications.argoproj.io/subscribe.on-sync-status-unknown.googlechat: plateformeNe vous abonnez pas à on-sync-succeeded sur toutes les applications : avec l'auto-réparation, le canal se remplit de messages que plus personne ne lit, et l'échec important s'y noie. Notifiez les échecs ; on-deployed peut servir, dans un canal séparé, à tracer les mises en production.
Surveiller
Chaque composant expose des métriques Prometheus. Les plus utiles :
| Métrique | Ce qu'elle dit |
|---|---|
argocd_app_info | une série par application, avec sync_status et health_status en étiquettes |
argocd_app_sync_total | les synchronisations, par résultat (phase) |
argocd_app_reconcile | la durée des réconciliations : un contrôleur qui s'essouffle |
argocd_cluster_connection_status | la connexion à chaque cluster cible |
argocd_git_request_total, argocd_git_request_duration_seconds | les accès à Git du repo-server |
argocd_repo_pending_request_total | des rendus en attente : un repo-server saturé |
Quelques alertes, en PromQL :
# Extrait des règles d'un PrometheusRule (sous spec.groups[].rules).
# Une application désynchronisée depuis plus de 30 minutes : l'auto-synchronisation n'y arrive pas,
# ou quelqu'un a désactivé l'automatisme et oublié.
- alert: ArgoCDApplicationDesynchronisee
expr: argocd_app_info{sync_status="OutOfSync"} == 1
for: 30m
# Une application dégradée.
- alert: ArgoCDApplicationDegradee
expr: argocd_app_info{health_status="Degraded"} == 1
for: 10m
# Un cluster cible injoignable.
- alert: ArgoCDClusterInjoignable
expr: argocd_cluster_connection_status == 0
for: 5mEt une alerte sur l'absence de métriques (absent(argocd_app_info)) : si le contrôleur ne tourne plus, les autres alertes se taisent, faute de données.
Dimensionner : le second incident
L'incident. Le cluster Kapsule de Lyneko n'avait qu'un nœud, avec un disque racine de 20 Go (environ 17 Gio utilisables). Le cache d'images y avait atteint près de 10 Gio, dont 2 Gio pour une seule image d'analyse de documents, et le disque était plein à 90 %. L'installation d'Argo CD, avec ses images, a fait passer l'espace libre sous le seuil d'éviction du kubelet (10 % disponibles) : le nœud est passé en DiskPressure, et le kubelet a évincé des pods, dont le contrôleur d'entrée qui servait plusieurs applications. Elles sont devenues injoignables jusqu'à ce que le ramasse-miettes d'images libère de la place ; aucune intervention manuelle n'a été nécessaire. Le délai de 300 secondes de l'installation Helm d'Argo CD a d'ailleurs expiré pendant que le nœud se débattait.
Les leçons :
- Sur un cluster à un seul nœud, chaque image jamais tirée s'accumule sur ce nœud. Dimensionner en processeur et mémoire ne suffit pas : déclarez aussi
ephemeral-storagedans les ressources, et surveillez le disque des nœuds. - La correction a été un disque racine de 50 Go. Sur Kapsule, changer la taille du disque racine remplace le pool : le nœud est détruit et recréé, tout redémarre. À planifier, pas à improviser.
- Argo CD n'est pas petit : contrôleur, repo-server, serveur, Redis, contrôleur d'ApplicationSet, notifications. Donnez-leur des
requestsréalistes et des limites de mémoire, en particulier au repo-server, qui rend les charts et peut consommer beaucoup pendant les pics.
Mettre à jour
Le projet publie une version mineure tous les trois mois, et seules les trois dernières mineures reçoivent des correctifs, y compris de sécurité. Une installation qui ne bouge pas pendant neuf mois n'est plus corrigée. La routine :
- lire les notes de mise à jour de chaque mineure traversée ; par exemple, la 3.5 embarque Helm 4.2 (avec des effets sur les dépôts OCI en HTTP) et remplace la vérification des signatures GnuPG par Source Integrity ;
- mettre à jour par Git (la version du chart Helm ou des manifestes dans le dépôt de la plateforme), d'abord sur une instance de recette si vous en avez une ;
- appliquer l'ensemble des manifestes, côté serveur (
--server-side --force-conflicts), pas seulement l'image ; - vérifier que les applications restent
Syncedet qu'aucune ne passe en erreur de comparaison après la mise à jour (un changement de version de Helm ou de Kustomize peut modifier un rendu).
Les correctifs (troisième chiffre) ne cassent rien par principe : appliquez-les vite, surtout quand ils corrigent une vulnérabilité.
Qui installe Argo CD ? Chez Lyneko, Argo CD est installé par Terraform (une ressource Helm dans le dépôt d'infrastructure), à côté du cluster. Une autre école fait gérer Argo CD par lui-même, à travers une Application qui pointe vers son propre chart : élégant, mais une mauvaise configuration peut l'empêcher de se réparer. Dans les deux cas, la version d'Argo CD est dans Git.
Sauvegarder
Avec GitOps, l'essentiel de l'état est dans Git : reconstruire un cluster, c'est réinstaller Argo CD et appliquer l'application racine. Ce qui n'est pas dans Git doit être sauvegardé ou reproductible :
- les secrets (identifiants de dépôts et de clusters, secret OIDC) : dans le gestionnaire de secrets, ce qui est une raison de plus pour ESO ;
- tout ce qui a été créé par l'interface ou la CLI au lieu de Git (Applications, projets, dépôts) :
argocd admin export -n argocd > sauvegarde.yamlen fait un export complet, à réimporter avecargocd admin import; - les clés de Sealed Secrets, si vous l'utilisez (leçon 8).
Le vrai test d'une reprise après sinistre est de la jouer : recréer Argo CD dans un cluster vide, et mesurer le temps jusqu'à ce que tout soit Synced.
Faire arriver les nouvelles images dans Git
Argo CD déploie ce que dit Git. Reste à mettre la nouvelle version de l'image dans Git, à chaque construction. Deux approches :
- La CI écrit dans Git. Après avoir construit et poussé l'image, la CI modifie la version dans le dépôt de déploiement et commite (ou ouvre une demande de fusion pour la production, comme à la leçon 4). C'est l'approche de Lyneko : simple, tracée, sans composant de plus. Son piège : le remplacement par
sedd'une lignetag:peut toucher la mauvaise clé si le fichier en contient plusieurs ; préférez un outil qui comprend le YAML (yq). - Argo CD Image Updater surveille le registre et met à jour lui-même les applications, en écrivant dans Git ou en surchargeant les paramètres par l'API d'Argo CD. Il fonctionne avec les applications Helm, Kustomize et à greffon de rendu (Config Management Plugin), et se configure, depuis sa version 1, par une ressource
ImageUpdater. Il est encore hébergé dansargoproj-labs, et son README indique ne pas le recommander « pour les charges de travail critiques en production ». La surcharge par l'API, qui ne passe pas par Git, contredit d'ailleurs le principe d'un état voulu versionné : si vous l'utilisez, choisissez l'écriture dans Git.
Et Flux ?
Flux est l'autre grand outil GitOps de la CNCF. Les principes sont les mêmes, la conception diffère :
| Argo CD | Flux | |
|---|---|---|
| Unité | Application, ApplicationSet | Kustomization, HelmRelease, sources séparées |
| Helm | rendu par Argo CD (helm template), pas de release Helm | vraie release Helm, gérée par le contrôleur Helm |
| Interface | interface web riche, RBAC et SSO intégrés | pas d'interface intégrée ; RBAC de Kubernetes |
| Multi-clusters | un hub qui pilote les clusters cibles | en général, une instance par cluster |
| Mise à jour d'images | Image Updater (projet labs) | contrôleurs d'automatisation d'images intégrés |
Flux plaît aux équipes qui veulent un outil réduit à ses contrôleurs, sans interface, gouverné uniquement par le RBAC de Kubernetes. Argo CD plaît à celles qui veulent une interface partagée avec les équipes de développement et un modèle multi-clusters centralisé. Les concepts de ce cours (réconciliation, état voulu dans Git, promotion par demande de fusion, secrets résolus dans le cluster) s'appliquent aux deux.
Sous le capot
Le contrôleur ne surveille pas Git en continu : il compare chaque application à Git toutes les 120 secondes par défaut (timeout.reconciliation), plus un délai aléatoire d'au plus 60 secondes (timeout.reconciliation.jitter) qui étale la charge sur le repo-server. D'où les « environ trois minutes » observés tout au long de ce cours. Un webhook de la forge vers argocd-server (/api/webhook) déclenche un rafraîchissement immédiat des applications concernées : c'est le réglage qui rend les déploiements quasi instantanés. Protégez-le par un secret partagé : plusieurs vulnérabilités de 2024 et 2025 permettaient de faire tomber argocd-server par une requête de webhook malformée, sans authentification.
Pièges courants
helm.sh/resource-policy: keep posé à la main, puis helm uninstall. Les ressources sont supprimées. Supprimez les secrets de release de Helm à la place.
latest dans Git pendant une adoption. Argo CD déploierait une autre version que celle qui tourne. Épinglez d'abord.
La CI déploie encore après l'adoption. Deux maîtres pour les mêmes ressources. Retirez le déploiement de la CI.
Un canal de notifications que personne ne lit. Trop de messages. Ne notifiez que ce qui demande une action.
Une mise à jour qui saute plusieurs mineures sans lire les notes. Lisez les notes de chaque version traversée.
DiskPressure après l'installation d'un composant. Le disque du nœud était déjà presque plein. Surveillez le disque, déclarez ephemeral-storage.
Sécurité
Mettez à jour. C'est la mesure de sécurité la plus efficace : la leçon 9 a montré des vulnérabilités critiques corrigées uniquement dans les mineures supportées.
Les sauvegardes contiennent des secrets. Un argocd admin export contient les Secrets d'Argo CD : identifiants de dépôts et de clusters. Chiffrez-le et stockez-le comme un secret.
Les notifications sortent du cluster. Elles envoient des noms d'applications, des messages d'erreur, parfois des extraits de manifestes, vers un service externe. Choisissez des modèles sobres, et des services de confiance.
Le webhook d'Argo CD est un point d'entrée sans authentification utilisateur : secret partagé obligatoire, et si possible accessible uniquement depuis votre forge. Les avis de sécurité de 2025 sur les webhooks (CVE-2025-59531, CVE-2025-59537, CVE-2025-59538) recommandent de définir un secret aléatoire pour chaque fournisseur, y compris ceux que vous n'utilisez pas (Gogs, Bitbucket Server, Azure DevOps) : sans secret, le point d'entrée d'un fournisseur accepte n'importe quelle requête.
En production
Chez Lyneko, le bilan de la mise en place tient en quelques règles, toutes issues des incidents de cette leçon :
- adoption des applications Helm par la méthode sûre (épingler, comparer, synchroniser, supprimer les secrets de release, retirer le déploiement de la CI), sans aucun redémarrage sur les applications suivantes ;
prunedésactivé tant que les PVC ne sont pas protégés parPrune=false;- un disque de nœud dimensionné pour le cache d'images, et le disque surveillé ;
- la CI qui écrit la version dans Git et n'a plus d'identifiant du cluster : un secret de moins dans la CI, ce qui est peut-être le plus grand gain de sécurité de tout le passage à GitOps.
Exercices
1. Un collègue propose d'adopter une release Helm en lançant helm uninstall --keep-history. Qu'en pensez-vous ?
Solution
--keep-history conserve l'historique des releases, pas les ressources : helm uninstall supprime toujours les ressources, sauf celles dont le manifeste enregistré porte helm.sh/resource-policy: keep. Pour retirer la propriété de Helm sans toucher aux ressources, on supprime les secrets de release (owner=helm,name=<release>), après qu'Argo CD a synchronisé l'application.
2. Écrivez l'abonnement qui envoie les échecs de synchronisation de toutes les applications de production dans l'espace Google Chat astreinte, et rien d'autre.
Solution
Sur l'AppProject de production (ou dans subscriptions d'argocd-notifications-cm avec un sélecteur d'étiquettes) :
metadata:
annotations:
notifications.argoproj.io/subscribe.on-sync-failed.googlechat: astreinteavec astreinte déclaré dans service.googlechat.webhooks, l'URL venant de argocd-notifications-secret.
3. Votre installation est en 3.2 en octobre 2026. Est-elle encore supportée ? Que faites-vous ?
Solution
Avec une mineure tous les trois mois et la 3.5 publiée, les versions supportées sont les trois dernières mineures : 3.5, 3.4 et 3.3. La 3.2 ne reçoit plus de correctifs, même de sécurité. Il faut monter en lisant les notes de 3.2 vers 3.3, 3.3 vers 3.4 et 3.4 vers 3.5, idéalement une mineure à la fois en vérifiant les applications entre chaque étape.
4. Pourquoi absent(argocd_app_info) est-elle une alerte indispensable ?
Solution
Les autres alertes reposent sur les séries de argocd_app_info. Si le contrôleur ne tourne plus, ou n'est plus collecté, ces séries disparaissent, et les alertes « désynchronisée » ou « dégradée » ne peuvent plus se déclencher : le silence ressemblerait à un état sain. L'alerte sur l'absence détecte justement cette panne silencieuse.
5. Faut-il préférer Image Updater ou l'écriture par la CI pour Signalements ?
Solution
L'écriture par la CI : la CI sait déjà quelle image elle vient de construire et de tester, le commit relie la version à la construction, la promotion en production reste une demande de fusion relue, et il n'y a pas de composant supplémentaire. Image Updater a du sens quand les images viennent de l'extérieur (une image tierce à suivre) ; il reste un projet labs que ses mainteneurs ne recommandent pas pour les charges critiques.
Récapitulatif
- Adopter une release Helm : épingler la version, Application sans automatisme, différence vide, synchroniser, supprimer les secrets de release, retirer le déploiement de la CI. Jamais
helm.sh/resource-policyposé à la main sur l'existant. - Notifier les échecs (
on-sync-failed,on-health-degraded,on-sync-status-unknown), de préférence par projet, pas les succès. - Surveiller
argocd_app_info, la connexion aux clusters, le repo-server, et l'absence même des métriques. - Dimensionner aussi le disque : un nœud plein évince des pods qui n'ont rien à voir avec Argo CD.
- Mettre à jour au rythme du projet : une mineure par trimestre, trois mineures supportées.
- Sauvegarder ce que Git ne contient pas, et jouer la reprise.
- Les nouvelles images arrivent dans Git par la CI ; Image Updater reste un projet labs.
Pour aller plus loin
- Argo CD, Operator Manual : haute disponibilité, sharding, réglages fins du contrôleur et du repo-server.
- Flux : l'autre approche GitOps, pour comparer en connaissance de cause.
- Retour à la présentation du cours.
Sources
- Argo CD, Notifications (catalogue, abonnements, Google Chat)
- Argo CD, Metrics
- Argo CD, Upgrading (vue d'ensemble, v3.4 vers v3.5)
- Argo CD, Release Process and Cadence
- Argo CD, Disaster Recovery
- Helm, Annotation helm.sh/resource-policy
- argoproj-labs/argocd-image-updater
- Kubernetes, Node-pressure Eviction
- Flux, documentation