Aller au contenu
  1. Articles/

ArgoCD en pratique : GitOps simplifie

GitLab CI, Jenkins, GitHub Actions — les pipelines CI/CD, tout le monde connaît. Mais quand tu gères plusieurs clusters Kubernetes en production, les scripts de déploiement dans une pipeline ça pose vite des questions : qui a modifié quoi ? Comment rollbacker proprement ? Comment avoir un état desired vs actual visible ?

GitOps répond à ces questions. ArgoCD en est l’implémentation la plus répandue. Voici comment ça fonctionne concrètement.

GitOps, kezako ? #

Le principe est simple : le dépôt Git est la seule source de vérité. Ton code Kubernetes (manifests, Helm charts, Kustomize) vit dans Git. ArgoCD surveille ce dépôt et syncronise automatiquement l’état desiré (dans Git) avec l’état réel (dans le cluster).

Git (desired state)  →  ArgoCD  →  Kubernetes (actual state)

La différence fondamentale avec un pipeline CI/CD classique :

Pipeline CI/CDGitOps (ArgoCD)
Déclencheurpush sur la branche, MR…commit Git
Qui déploieRunner / Agent CIArgoCD (pull)
Rollbackgit revert + pipelinegit revert (ArgoCD sync)
VisibilitéLogs de pipelineDashboard temps réel
Drift detectionManuelleAutomatique

Dans un pipeline classique, tu pousses vers le cluster. Avec GitOps, ArgoCD tire les changements depuis le cluster.

Installation #

ArgoCD se déploie sur un cluster Kubernetes — souvent le même que celui qu’il gère, mais il peut gérer plusieurs clusters (y compris des clusters externes).

# Installation via Helm
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd \
  --namespace argocd \
  --create-namespace \
  --values - <<EOF
redis:
  enabled: true
server:
  ingress:
    enabled: true
    ingressClassName: traefik
    hosts:
      - argocd.example.com
EOF

Accès au dashboard (après création de l’Ingress) :

# Récupérer le mot de passe admin
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d

Le concept d’Application #

L’objet central dans ArgoCD, c’est l’Application. C’est la relation entre un dépôt Git et un cluster/namespace destination.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: mon-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/mon-org/k8s-manifests
    targetRevision: main
    path: apps/mon-app
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      selfHeal: true
      prune: true

Cette Application dit : “Syncronise le contenu de apps/mon-app dans le dépôt Git avec le namespace production du cluster courant.”

Les sources supportées #

ArgoCD ne déploie pas que des manifests YAML bruts :

  • Git repository — manifests bruts, Kustomize, Helm (values inline ou fichiers)
  • Helm repository — charts depuis un registry Helm
  • OCI registry — charts Docker/OCI (depuis GitHub Container Registry, Docker Hub…)
  • Bitbucket, GitLab, Azure DevOps — en plus de GitHub

Sync et Drift #

Drift detection #

ArgoCD compare en permanence l’état desired (Git) avec l’état réel (cluster). Si quelqu’un modifie un Deployment manuellement avec kubectl, ArgoCD le détecte et affiche l’application comme OutOfSync.

# Voir le statut
argocd app get mon-app
Name:               mon-app
Project:            default
Server:             kubernetes.default.svc
Namespace:          production
URL:                https://argocd.example.com/applications/mon-app
Repo:               https://github.com/mon-org/k8s-manifests
Target:             a1b2c3d (main)
Sync Status:        OutOfSync (1 pod replica count differs)
Health Status:      Healthy

Sync manuelle #

# Sync manuelle
argocd app sync mon-app

# Spécifier une révision
argocd app sync mon-app --revision v2.1.0

Sync automatique #

Avec syncPolicy.automated, ArgoCD syncronise automatiquement quand il détecte un changement dans Git :

syncPolicy:
  automated:
    selfHeal: true    # Corrige le drift automatiquement
    prune: true       # Supprime les ressources supprimées dans Git

Attention : selfHeal peut être dangereux en production si tu ne testes pas tes changements. Beaucoup d’équipes préfèrent une sync manuelle avec un argocd app sync explicite dans leur pipeline CI.

Kustomize ou Helm ? #

C’est LA question. Les deux fonctionnent, les deux ont des adeptes.

Kustomize #

Kustomize est intégré à kubectl et parfait pour les overlays simples :

base/
  deployment.yaml
  service.yaml
  kustomization.yaml
overlays/
  staging/
    kustomization.yaml
    replica-count.yaml
  production/
    kustomization.yaml
    replica-count.yaml
# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base
patches:
  - path: replica-count.yaml
    target:
      kind: Deployment
# overlays/production/replica-count.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mon-app
spec:
  replicas: 5

ArgoCD génère le manifest final avant de l’appliquer. Tu obtiens un diff propre :

argocd app diff mon-app

Helm #

Helm reste indispensable quand tu utilises des charts tiers (Bitnami, Prometheus, cert-manager…). ArgoCD intègre nativement Helm :

spec:
  source:
    repoURL: https://prometheus-community.github.io/helm-charts
    chart: prometheus
    targetRevision: 25.0.0
    helm:
      valueFiles:
        - values.production.yaml
      values: |
        replicaCount: 3
        service:
          type: ClusterIP
# Voir les valeurs
argocd app get mon-app --show-yaml

Mon avis #

KustomizeHelm
PourSimple, pas de syntaxe nouvelleTemplates puissants, registry de charts
ContrePas de fonctions conditionnellesComplexité des templates pour les overlays
Use case idealTes propres appsCharts tiers, apps avec beaucoup de config

Projects — organiser les Applications #

Les AppProjects permettent de regrouper les Applications et imposer des contraintes :

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: production
  namespace: argocd
spec:
  sourceRepos:
    - https://github.com/mon-org/*
    - https://github.com/mon-org/k8s-manifests
  destinations:
    - server: https://kubernetes.default.svc
      namespace: production
  clusterResourceWhitelist:
    - group: ""
      kind: Namespace
  namespaceResourceBlacklist:
    - group: ""
      kind: ResourceQuota

Les contraintes possibles :

  • sourceRepos — quels dépôts sont autorisés
  • destinations — quels clusters/namespaces sont autorisés
  • namespaceResourceBlacklist — resources que ArgoCD ne gère pas
  • clusterResourceWhitelist — resources cluster-wide autorisées

Ça permet d’isoler les équipes : le projet “production” ne peut déployer que dans le namespace production, pas dans staging ou kube-system.

Rollback en un clin d’oeil #

C’est là que GitOps brille. Rollbacker, c’est juste revenir à un commit précédent :

# Lister les révisions déployées
argocd app history mon-app

ID  DATE                           COMMIT    MESSAGE
1   2026-03-01 10:00:00 +0100 CET  a1b2c3d   feat: ajout monitoring
2   2026-03-15 14:30:00 +0100 CET  d4e5f6g   fix: hotfix replicas
3   2026-03-20 09:15:00 +0100 CET  h7i8j9k   chore: dep updates

# Rollback vers la révision 2
argocd app rollback mon-app 2

ArgoCD redéploie le manifest à l’état du commit d4e5f6g. Pas besoin de helm rollback, pas de manipulation de state — Git fait tout.

Intégration avec GitLab CI #

Mon setup typique : la CI build et push l’image Docker, puis déclenche une sync ArgoCD :

# .gitlab-ci.yml
build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t registry.example.com/mon-app:$CI_COMMIT_SHA .
    - docker push registry.example.com/mon-app:$CI_COMMIT_SHA
    - echo $CI_COMMIT_SHA > commit_sha.txt
  artifacts:
    paths:
      - commit_sha.txt

deploy:
  stage: deploy
  image: bitnami/argocd:latest
  script:
    - argocd login argocd.example.com --username $ARGOCD_USER --password $ARGOCD_PASSWORD
    - argocd app set mon-app --kustomize-images registry.example.com/mon-app=$CI_COMMIT_SHA
    - argocd app sync mon-app --force
  dependencies:
    - build
  when: manual

Le when: manual permet de valider avant de syncroniser. L’image tag est mise à jour via Kustomize (ou Helm values), et ArgoCD détecte le changement.

Multi-cluster #

Un ArgoCD installé sur un cluster “management” peut gérer d’autres clusters :

# Enregistrer un cluster externe dans ArgoCD
argocd cluster add mon-prod-cluster --name production
# Liste des clusters connus
argocd cluster list
SERVER                          NAME          VERSION  STATUS   MESSAGE
https://kubernetes.default.svc   in-cluster    1.30     True     Successful
https://prod.example.com:6443    production    1.29     True     Successful

L’Application peut alors cibler n’importe quel cluster enregistré :

spec:
  destination:
    server: https://prod.example.com:6443
    namespace: production

Un seul ArgoCD, plusieurs clusters — c’est le setup que j’utilise en production.

Webhooks — éviter le polling #

Par défaut, ArgoCD poll le dépôt toutes les 3 minutes. Pour une réactivité immédiate, configure un webhook :

# Dans ArgoCD configmap
data:
  resource.customizations: |
    argoproj.io/Application:
      health.lua: |
        ...

Le webhook se configure côté GitLab :

Settings → Webhooks → Add webhook
URL: https://argocd.example.com/api/webhook
Secret token: (generer un token)
Events: Push events

À chaque push, ArgoCD est notifié et syncronise immédiatement.

Bonnes pratiques #

1. Un dépôt par application (ou par domaine) #

Évite le mega-repo avec 50 apps. Chaque dépôt = une Application ArgoCD = un cycle de vie indépendant. Plus facile à maintenir, plus simple à sécuriser.

2. Toujours un diff avant sync #

argocd app diff mon-app --local ./manifests

Compare ton état local (non commité) avec ce qu’ArgoCD connaît. Évite les surprises.

3. Utiliser les PreSync Hooks pour les migrations #

Si tu as besoin de migrer une BDD avant de déployer :

apiVersion: batch/v1
kind: Job
metadata:
  name: db-migration
  annotations:
    argocp.argoproj.io/hook: PreSync
    argocp.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
        - name: migrate
          image: mon-app:latest
          command: ["migrate.sh"]
      restartPolicy: Never
  backoffLimit: 3

PreSync s’exécute avant le déploiement, Sync pendant, PostSync après. HookSucceeded supprime le Job une fois terminé.

4. Rester sur une image tag stable #

Évite les tags latest ou main. Utilise le SHA de l’image :

image: registry.example.com/mon-app@sha256:a1b2c3d4...

Plus de doute sur “quelle version est déployée”. Le SHA est déterministe.

Conclusion #

ArgoCD transforme la gestion Kubernetes en quelque chose de visible et reproductible. Le dépôt Git devient l’audit trail de tes déploiements, le dashboard montre l’état réel vs desired, et le rollback est une question de git revert.

Le coût : un cluster dédié à ArgoCD (ou le même si t’as les ressources) + la discipline de passer par Git pour tout changement. En retour, tu gagnes en traçabilité, en confiance dans les déploiements, et en temps passé à debugger “qui a cassé quoi”.

C’est devenu le standard de facto pour le GitOps Kubernetes. Si tu gères plus de deux clusters, c’est presque indispensable.