Optimiser le déploiement continu avec ArgoCD et Kubernetes

Introduction
ArgoCD est devenu mon outil de déploiement continu de référence sur Kubernetes. Après l'avoir implémenté chez Bloomflow (30+ microservices, 5 ans), KNDS (Défense), Padam Mobility (transport), F2R2 (AWS multi-compte) et Earny SA (migration GCP vers AWS), j'ai accumulé des optimisations et des patterns qui font la différence entre un ArgoCD installé par défaut et un ArgoCD qui tourne en production sans friction à grande échelle.
Le GitOps comme philosophie : Git = vérité, cluster = miroir
ArgoCD implémente le GitOps de manière stricte : Git est la source de vérité unique, le cluster Kubernetes est un miroir fidèle de l'état déclaré dans Git. Concrètement, chez Bloomflow, les Helm values de chaque microservice vivaient dans un repo Git dédié (infra-k8s). Le workflow était fluide : un développeur mergeait sa PR sur le repo applicatif, GitHub Actions buildait l'image Docker et poussait vers GHCR, puis un second workflow mettait à jour le tag de l'image dans le fichier values.yaml du repo infra-k8s. ArgoCD détectait le changement en moins de 3 minutes et synchronisait le cluster.
Le rollback était un git revert sur le commit de mise à jour du tag. ArgoCD détectait le revert et redéployait l'ancienne version automatiquement. Le temps total du rollback : 4 minutes (30 secondes pour le git revert + push, 3 minutes pour la détection ArgoCD, 30 secondes pour la synchronisation). L'audit trail était le git log du repo GitOps : chaque ligne montrait qui avait déployé quoi, quand, et le diff exact des changements. Chez KNDS, cette traçabilité native était un prérequis réglementaire pour la défense : chaque déploiement en production devait être auditable avec l'identité du commit author et les changements appliqués.
ApplicationSets : scaler de 3 à 90 applications sans effort
L'organisation des Applications ArgoCD impacte directement la maintenabilité à l'échelle. Mon pattern éprouvé : une Application ArgoCD par microservice par environnement. Chez Bloomflow avec 30+ services et 3 environnements (dev, staging, production), cela faisait plus de 90 Applications ArgoCD. Les gérer manuellement aurait été un cauchemar de YAML dupliqué.
Les ApplicationSets résolvent ce problème élégamment. J'ai configuré un ApplicationSet avec un générateur git qui scannait la structure du repo GitOps : chaque dossier dans services/ correspondait à un microservice, chaque sous-dossier dans environments/ à un environnement. Le template ApplicationSet générait automatiquement les Applications ArgoCD pour chaque combinaison service x environnement. Quand un nouveau microservice apparaissait dans le repo (un nouveau dossier avec un values.yaml), ArgoCD créait automatiquement ses 3 Applications (dev, staging, prod) sans intervention humaine. Chez F2R2, les ApplicationSets étaient organisés par environnement avec des labels (env: dev, env: prod) qui permettaient de filtrer dans l'UI ArgoCD.
Synchronisation avancée : waves, hooks et self-heal
ArgoCD offre des options de synchronisation avancées que j'exploite systématiquement mais que peu de mes clients utilisaient avant mon intervention. Le sync wave permet d'ordonner les déploiements par priorité. Chez Bloomflow, les migrations de base de données (annotées avec argocd.argoproj.io/sync-wave: "-1") s'exécutaient toujours avant le déploiement de l'application (wave 0). Ainsi, la nouvelle version de l'application trouvait toujours un schéma de base de données compatible. Sans les waves, un déploiement pouvait échouer parce que l'application démarrait avant que la migration ne soit terminée.
Le sync hook permettait d'exécuter des Jobs à des moments précis du cycle de synchronisation. Chez Padam Mobility, un hook PostSync exécutait automatiquement des smoke tests contre l'application fraîchement déployée : vérification que l'API répondait, que l'endpoint de calcul de routes fonctionnait avec un trajet test, et que les métriques Prometheus étaient collectées. Si le hook échouait, l'Application passait en statut Degraded et l'équipe était alertée immédiatement. Le self-heal, activé chez KNDS, corrigeait automatiquement toute modification manuelle du cluster (un kubectl edit intempestif, un kubectl delete accidentel) en resynchronisant avec l'état Git. C'est la garantie que le cluster est toujours conforme à Git.
Notifications et observabilité : ne rien rater
ArgoCD sans notifications, c'est comme un monitoring sans alertes -- inutile en production. Chez Bloomflow, ArgoCD Notifications (le module officiel) envoyait un message Slack pour chaque événement significatif : synchronisation réussie (message vert avec le lien vers le diff Git et le temps de sync), synchronisation échouée (message rouge avec le log d'erreur et le lien vers l'Application dans l'UI ArgoCD), et Application en état Degraded (message orange avec les détails du health check défaillant).
Chez KNDS, les notifications allaient sur un channel Discord dédié à l'équipe ops, avec un second channel pour les déploiements production uniquement (pour les auditeurs). Pour l'observabilité fine, ArgoCD expose nativement des métriques Prometheus : nombre de synchronisations par statut (Success, Failed, Unknown), durée de chaque sync, nombre d'Applications par état (Healthy, Degraded, OutOfSync), et temps de réconciliation. Chez Bloomflow, un dashboard Grafana dédié affichait ces métriques et alertait si une Application restait en état OutOfSync pendant plus de 10 minutes (signe d'un problème de sync) ou si le taux d'échec de sync dépassait 5% sur une heure.
Performance à l'échelle : sharding, webhooks et resource optimization
A l'échelle de 90+ Applications, ArgoCD peut devenir un goulot d'étranglement si on ne l'optimise pas. Chez Bloomflow, deux optimisations étaient essentielles pour maintenir la réactivité.
La première : le sharding du controller ArgoCD. Par défaut, un seul controller gère toutes les Applications. Avec 90+ Applications et des syncs fréquentes, le controller était saturé : les réconciliations prenaient 5 minutes au lieu de 30 secondes. J'ai configuré 3 shards (3 instances du controller), chacun gérant un tiers des Applications basé sur un hash du nom. La réconciliation est revenue à 30 secondes. Les ressources du controller ont aussi été augmentées : 2 CPU et 4 Go de RAM par shard, avec des requests/limits ajustées finement.
La seconde : les webhooks GitHub. Par défaut, ArgoCD poll le repo Git toutes les 3 minutes pour détecter les changements. Pour les déploiements critiques, 3 minutes d'attente est trop long. J'ai configuré un webhook GitHub qui notifie ArgoCD immédiatement à chaque push sur le repo GitOps. Le temps entre le merge de la PR et le début de la synchronisation est passé de 3 minutes (polling) à 5 secondes (webhook). Pour les Applications moins critiques (outils internes, dashboards), un polling interval de 5 minutes réduisait la charge sur l'API Git sans impact perceptible.
Conclusion
Optimiser ArgoCD sur Kubernetes, c'est aller bien au-delà de l'installation par défaut. Le GitOps strict comme philosophie (Git = vérité unique), les ApplicationSets pour scaler de 3 à 90 Applications sans duplication, la synchronisation fine avec les waves et les hooks post-sync, les notifications proactives et l'observabilité Prometheus/Grafana, et les optimisations de performance (sharding + webhooks) : ces pratiques, affinées sur 5 ans chez Bloomflow et validées chez KNDS, Padam Mobility, F2R2 et Earny SA, font d'ArgoCD un outil de déploiement continu fiable, maintenable et performant à toute échelle.