Aller au contenu principal
GitOpsKubernetesDevOpsCI/CDArgoCDFlux

GitOps en 2026 : ArgoCD vs Flux, le guide complet

30 min de lecture

Comprends les principes GitOps et compare ArgoCD et Flux en profondeur. Installation, concepts, démos pratiques et guide pour choisir le bon outil.

C’est quoi GitOps ?

GitOps, c’est une méthode de gestion d’infrastructure et de déploiement où Git est la source de vérité unique. Tout l’état désiré de ton cluster Kubernetes est décrit dans un repo Git. Un opérateur dans le cluster surveille ce repo et réconcilie automatiquement l’état réel avec l’état désiré.

Les 4 principes GitOps (selon OpenGitOps)

  1. Déclaratif — L’état désiré est décrit, pas les étapes pour y arriver
  2. Versionné et immuable — Git stocke l’historique complet des changements
  3. Tiré automatiquement — Les agents dans le cluster pull les changements
  4. Réconciliation continue — L’état réel est constamment rapproché de l’état désiré

Push vs Pull : la différence fondamentale

Push-based (CI/CD classique) :

Dev → Git Push → CI Pipeline → kubectl apply → Cluster

Le pipeline pousse les changements vers le cluster. Il a besoin de credentials pour accéder au cluster.

Pull-based (GitOps) :

Dev → Git Push → Git Repo ← Agent dans le cluster → Réconciliation

L’agent dans le cluster tire les changements depuis Git. Pas besoin d’exposer les credentials du cluster à l’extérieur.

AspectPush (CI/CD)Pull (GitOps)
Qui déploiePipeline externeAgent dans le cluster
Credentials clusterNécessaires dans la CIRestent dans le cluster
Drift detection❌ Pas natif✅ Réconciliation continue
RollbackRe-run du pipelinegit revert
Audit trailLogs CIHistorique Git
SécuritéCredentials exposésPrincipe du moindre privilège

Pourquoi GitOps en 2026 ?

  • Sécurité : plus besoin de kubeconfig dans les pipelines CI/CD
  • Auditabilité : chaque changement = un commit Git avec auteur et timestamp
  • Récupération : cluster crashé ? Recrée-le et pointe vers le même repo. Tout revient.
  • Developer experience : les devs font des PR, pas du kubectl
  • Compliance : les régulateurs adorent l’audit trail Git

ArgoCD

ArgoCD est l’outil GitOps le plus populaire. Développé par Intuit (les mêmes que TurboTax), maintenant projet CNCF graduated.

Installation

# Créer le namespace
kubectl create namespace argocd

# Installer ArgoCD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Attendre que tout soit prêt
kubectl wait --for=condition=available deployment/argocd-server -n argocd --timeout=300s

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

# Exposer l'UI (port-forward pour tester)
kubectl port-forward svc/argocd-server -n argocd 8443:443

# Ou avec un Ingress (production)
cat <<EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server
  namespace: argocd
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - argocd.devopslab.ch
      secretName: argocd-tls
  rules:
    - host: argocd.devopslab.ch
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: argocd-server
                port:
                  number: 443
EOF

Installer la CLI

# macOS
brew install argocd

# Linux
curl -sSL -o argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
chmod +x argocd && sudo mv argocd /usr/local/bin/

# Se connecter
argocd login argocd.devopslab.ch --username admin --password <password>

Concepts clés

Application — La ressource centrale. Elle lie un repo Git à un namespace Kubernetes :

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  
  source:
    repoURL: https://github.com/devopslab/k8s-manifests.git
    targetRevision: main
    path: apps/my-app          # Répertoire dans le repo
  
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  
  syncPolicy:
    automated:                  # Sync automatique
      prune: true               # Supprimer les ressources orphelines
      selfHeal: true            # Re-sync si drift détecté
    syncOptions:
      - CreateNamespace=true
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

AppProject — Isole les applications par équipe/environnement :

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: team-backend
  namespace: argocd
spec:
  description: Projet pour l'équipe backend
  
  sourceRepos:
    - 'https://github.com/devopslab/*'
  
  destinations:
    - namespace: 'backend-*'
      server: https://kubernetes.default.svc
  
  clusterResourceWhitelist:
    - group: ''
      kind: Namespace
  
  namespaceResourceBlacklist:
    - group: ''
      kind: ResourceQuota
  
  roles:
    - name: developer
      policies:
        - p, proj:team-backend:developer, applications, get, team-backend/*, allow
        - p, proj:team-backend:developer, applications, sync, team-backend/*, allow
      groups:
        - team-backend-devs

ApplicationSet — Générer des Applications dynamiquement :

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: microservices
  namespace: argocd
spec:
  generators:
    # Générer une Application par répertoire dans le repo
    - git:
        repoURL: https://github.com/devopslab/k8s-manifests.git
        revision: main
        directories:
          - path: apps/*

  template:
    metadata:
      name: '{{path.basename}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/devopslab/k8s-manifests.git
        targetRevision: main
        path: '{{path}}'
      destination:
        server: https://kubernetes.default.svc
        namespace: '{{path.basename}}'
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
          - CreateNamespace=true

Démo : déployer une app avec ArgoCD

Structure du repo Git :

k8s-manifests/
├── apps/
│   └── demo-app/
│       ├── deployment.yaml
│       ├── service.yaml
│       ├── ingress.yaml
│       └── kustomization.yaml
└── argocd/
    └── demo-app.yaml

apps/demo-app/deployment.yaml :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
  labels:
    app: demo-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo-app
  template:
    metadata:
      labels:
        app: demo-app
    spec:
      containers:
        - name: demo-app
          image: ghcr.io/devopslab/demo-app:v1.2.0
          ports:
            - containerPort: 8080
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 10
            periodSeconds: 5
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 256Mi

apps/demo-app/service.yaml :

apiVersion: v1
kind: Service
metadata:
  name: demo-app
spec:
  selector:
    app: demo-app
  ports:
    - port: 80
      targetPort: 8080
  type: ClusterIP

argocd/demo-app.yaml :

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: demo-app
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    repoURL: https://github.com/devopslab/k8s-manifests.git
    targetRevision: main
    path: apps/demo-app
  destination:
    server: https://kubernetes.default.svc
    namespace: demo
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
# Appliquer l'Application
kubectl apply -f argocd/demo-app.yaml

# Vérifier via CLI
argocd app get demo-app
argocd app sync demo-app

# Voir l'historique
argocd app history demo-app

# Rollback
argocd app rollback demo-app 1

Workflow quotidien avec ArgoCD

# 1. Modifier le manifest (ex: nouvelle image)
sed -i 's/v1.2.0/v1.3.0/' apps/demo-app/deployment.yaml

# 2. Commit + push
git add . && git commit -m "Bump demo-app to v1.3.0" && git push

# 3. ArgoCD détecte le changement et sync automatiquement
# (si syncPolicy.automated est activé)

# 4. Vérifier
argocd app get demo-app
# Status: Synced, Health: Healthy

# 5. Problème ? Revert Git
git revert HEAD && git push
# ArgoCD re-sync vers la version précédente

Flux

Flux est l’autre gros joueur GitOps. Développé par Weaveworks (RIP), maintenant projet CNCF graduated. Philosophie : léger, composable, Kubernetes-native.

Installation

# Installer la CLI
brew install fluxcd/tap/flux
# Ou
curl -s https://fluxcd.io/install.sh | sudo bash

# Vérifier les prérequis
flux check --pre

# Bootstrapper Flux avec GitHub
flux bootstrap github \
  --owner=devopslab \
  --repository=fleet-infra \
  --branch=main \
  --path=clusters/production \
  --personal

# Ou GitLab
flux bootstrap gitlab \
  --owner=devopslab \
  --repository=fleet-infra \
  --branch=main \
  --path=clusters/production

Le bootstrap :

  1. Crée le repo fleet-infra s’il n’existe pas
  2. Installe les composants Flux dans le cluster
  3. Configure Flux pour se gérer lui-même via Git (inception!)

Concepts clés

Flux est composable. Chaque fonctionnalité est un controller séparé :

ControllerRôle
source-controllerRécupère les sources (Git, Helm, OCI, S3)
kustomize-controllerApplique les manifests Kustomize
helm-controllerGère les HelmReleases
notification-controllerAlertes et webhooks
image-reflector-controllerDétecte les nouvelles images
image-automation-controllerMet à jour les manifests avec les nouvelles images

GitRepository — Source Git :

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/devopslab/k8s-manifests.git
  ref:
    branch: main
  secretRef:
    name: github-token  # Si repo privé

Kustomization — Ce qui doit être appliqué depuis la source :

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 5m
  path: ./apps/my-app
  prune: true            # Supprime les orphelins
  sourceRef:
    kind: GitRepository
    name: my-app
  targetNamespace: production
  healthChecks:
    - apiVersion: apps/v1
      kind: Deployment
      name: my-app
      namespace: production
  timeout: 3m

HelmRelease — Déployer un chart Helm :

apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: nginx-ingress
  namespace: flux-system
spec:
  interval: 10m
  chart:
    spec:
      chart: ingress-nginx
      version: "4.x"
      sourceRef:
        kind: HelmRepository
        name: ingress-nginx
  values:
    controller:
      replicaCount: 2
      service:
        type: LoadBalancer

Démo : déployer avec Flux

Structure du repo :

fleet-infra/
├── clusters/
│   └── production/
│       ├── flux-system/        # Généré par bootstrap
│       │   ├── gotk-components.yaml
│       │   ├── gotk-sync.yaml
│       │   └── kustomization.yaml
│       ├── sources/
│       │   └── my-app.yaml
│       └── apps/
│           └── my-app.yaml
└── apps/
    └── my-app/
        ├── deployment.yaml
        ├── service.yaml
        └── kustomization.yaml

clusters/production/sources/my-app.yaml :

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/devopslab/k8s-manifests.git
  ref:
    branch: main

clusters/production/apps/my-app.yaml :

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 5m
  path: ./apps/my-app
  prune: true
  sourceRef:
    kind: GitRepository
    name: my-app
  targetNamespace: demo
  healthChecks:
    - apiVersion: apps/v1
      kind: Deployment
      name: demo-app
      namespace: demo
# Appliquer
git add . && git commit -m "Add my-app" && git push

# Flux détecte et applique automatiquement

# Vérifier
flux get kustomizations
flux get sources git

# Forcer une réconciliation
flux reconcile kustomization my-app --with-source

# Voir les événements
flux events

# Suspendre (maintenance)
flux suspend kustomization my-app

# Reprendre
flux resume kustomization my-app

Image Automation

Flux peut détecter les nouvelles images Docker et mettre à jour les manifests automatiquement :

# Scanner le registry
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
  name: my-app
  namespace: flux-system
spec:
  image: ghcr.io/devopslab/my-app
  interval: 5m

---
# Politique de tag
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
  name: my-app
  namespace: flux-system
spec:
  imageRepositoryRef:
    name: my-app
  policy:
    semver:
      range: ">=1.0.0"

---
# Automation : update le manifest
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageUpdateAutomation
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 5m
  sourceRef:
    kind: GitRepository
    name: fleet-infra
  git:
    checkout:
      ref:
        branch: main
    commit:
      author:
        name: fluxcdbot
        email: flux@devopslab.ch
      messageTemplate: 'chore: update {{.AutomationObject.Name}} to {{range .Changed.Changes}}{{.NewValue}}{{end}}'
    push:
      branch: main
  update:
    path: ./apps
    strategy: Setters

Dans le manifest, marque l’image avec un commentaire :

spec:
  containers:
    - name: my-app
      image: ghcr.io/devopslab/my-app:v1.2.0 # {"$imagepolicy": "flux-system:my-app"}

Flux va automatiquement committer le changement de tag quand une nouvelle version est publiée.


Comparatif ArgoCD vs Flux

Tableau comparatif détaillé

CritèreArgoCDFlux
ArchitectureMonolithique (serveur + UI)Composable (controllers séparés)
UI✅ Interface web riche❌ Pas d’UI native (Weave GitOps UI en option)
CLI✅ Puissante✅ Puissante
Multi-cluster✅ Natif (hub-spoke)✅ Via Kustomization
Multi-tenancy✅ AppProjects + RBAC✅ Namespace-scoped
Helm✅ Via Application✅ HelmRelease natif
Kustomize✅ Natif✅ Natif
RBAC✅ Intégré (OIDC, LDAP)⚠️ Via Kubernetes RBAC
SSO✅ OIDC, SAML, LDAP❌ (via UI tierce)
Image automation⚠️ Argo Image Updater (séparé)✅ Natif
Notifications✅ Argo Notifications✅ notification-controller
Webhooks✅ GitHub, GitLab✅ GitHub, GitLab, et plus
Diff/Preview✅ Dans l’UI⚠️ CLI uniquement
Rollback✅ Un clic dans l’UI⚠️ git revert
OCI support
Footprint~200-500 Mi RAM~100-200 Mi RAM
Courbe d’apprentissageMoyennePlus raide
CNCF StatusGraduatedGraduated
CommunautéTrès active (~16k ⭐)Active (~6k ⭐)

Benchmark de performance

Sur un cluster avec 200 applications :

MétriqueArgoCDFlux
Temps de sync moyen15-30s10-20s
RAM utilisée~450 Mi~180 Mi
CPU utilisé~200m~100m
Détection de drift3 min (default)1 min (configurable)

Points forts de chacun

ArgoCD brille quand :

  • Tu veux une UI pour visualiser l’état des apps
  • Tu as besoin de SSO/RBAC intégré
  • Plusieurs équipes doivent voir l’état des déploiements
  • Tu veux du rollback en un clic
  • Tu viens du monde CI/CD et tu veux une transition douce

Flux brille quand :

  • Tu préfères une approche Kubernetes-native (tout est CRD)
  • Tu veux un footprint minimal
  • Tu as besoin d’image automation native
  • Tu gères de l’infrastructure (pas seulement des apps)
  • Tu veux de la composabilité (n’installe que ce dont tu as besoin)

Quand utiliser quoi ?

Arbre de décision

Tu as besoin d'une UI ?
├── Oui → ArgoCD
└── Non
    ├── Tu gères beaucoup d'infra (cert-manager, ingress, monitoring...) ?
    │   ├── Oui → Flux (plus léger, HelmRelease natif)
    │   └── Non
    │       ├── Plusieurs équipes non-techniques doivent voir les déploiements ?
    │       │   ├── Oui → ArgoCD (UI = adoption facile)
    │       │   └── Non → Flux ou ArgoCD, les deux marchent
    │       └── Tu as besoin d'image automation ?
    │           ├── Oui → Flux (natif et mature)
    │           └── Non → ArgoCD ou Flux

Recommandations par contexte

ContexteRecommandation
Startup / petite équipeFlux (léger, rapide à setup)
Enterprise / plusieurs équipesArgoCD (UI, RBAC, SSO)
Platform engineeringFlux (composable, Kubernetes-native)
Migration depuis Jenkins/GitLab CIArgoCD (transition plus douce)
Multi-cluster massifArgoCD (ApplicationSet) ou Flux (Kustomization multi-cluster)
Edge / IoT / ressources limitéesFlux (footprint minimal)

Le setup hybride

Rien n’empêche d’utiliser les deux :

  • Flux pour l’infrastructure (cert-manager, ingress, monitoring, operators)
  • ArgoCD pour les applications (ce que les devs voient et gèrent)

C’est un pattern de plus en plus courant en 2026.


Bonnes pratiques GitOps

Structure de repo

Mono-repo (recommandé pour commencer) :

fleet/
├── infrastructure/        # Composants infra
│   ├── cert-manager/
│   ├── ingress-nginx/
│   └── monitoring/
├── apps/                  # Applications
│   ├── frontend/
│   ├── backend/
│   └── worker/
├── clusters/              # Config par cluster
│   ├── production/
│   └── staging/
└── README.md

Multi-repo (grandes organisations) :

# Repo 1: fleet-infra (platform team)
# Repo 2: app-frontend (frontend team)
# Repo 3: app-backend (backend team)

Sécurité

# Sealed Secrets (chiffrement côté client, déchiffrement dans le cluster)
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: my-secret
  namespace: production
spec:
  encryptedData:
    password: AgBy3i... # Chiffré avec la clé publique du cluster

# Ou External Secrets Operator (secrets depuis Vault, AWS SM, etc.)
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: my-secret
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: my-secret
  data:
    - secretKey: password
      remoteRef:
        key: secret/data/my-app
        property: password

Le workflow PR

  1. Dev crée une branche et modifie les manifests
  2. PR review (le code ET les manifests)
  3. CI valide les manifests (kubectl dry-run, kustomize build, helm template)
  4. Merge → ArgoCD/Flux sync automatiquement
  5. Monitoring vérifie que tout est healthy
# GitHub Actions : valider les manifests avant merge
name: Validate K8s Manifests
on: [pull_request]
jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Validate manifests
        run: |
          # Installer les outils
          curl -sL https://github.com/yannh/kubeconform/releases/latest/download/kubeconform-linux-amd64.tar.gz | tar xz
          
          # Valider tous les YAML
          find apps/ -name '*.yaml' -exec ./kubeconform -strict -summary {} +
          
      - name: Kustomize build check
        run: |
          for dir in apps/*/; do
            echo "Building $dir..."
            kustomize build "$dir" > /dev/null
          done

Conclusion

GitOps n’est plus une tendance — c’est le standard en 2026 pour le déploiement Kubernetes. ArgoCD et Flux sont tous deux matures, graduées CNCF, et production-ready.

TL;DR :

  • Tu veux une UI et du RBAC → ArgoCD
  • Tu veux du léger et du Kubernetes-native → Flux
  • Tu débutes en GitOps → ArgoCD (l’UI aide beaucoup à comprendre)
  • Tu es platform engineer → Flux (plus de contrôle)

Le plus important, c’est de commencer. Prends celui qui te parle, déploie-le, et itère. Le switch de l’un à l’autre est toujours possible — tes manifests Kubernetes restent les mêmes.

🖥️ Pratique sur ton propre serveur

Pour suivre GitOps en 2026 : ArgoCD vs Flux, le guide complet en conditions réelles, tu as besoin d'un VPS. DigitalOcean offre 200$ de crédit gratuit pour démarrer.

Obtenir 200$

Articles liés