Skip to main content
RunBook Academy

KubernetesCIII · GitOps IntroductionGitOps

Reconciliation controllers — Argo CD and Flux in depth

Advanced⏱ ~17 minkubectlargocdflux

What you'll learn

  • Use Argo CD for GitOps reconciliation
  • Use Flux for GitOps reconciliation
  • Choose between Argo CD and Flux
  • Apply the operational discipline of treating the controller as production infrastructure

Prerequisites

Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16

Not yet marked complete on this device.

Argo CD and Flux are the two main GitOps controllers for Kubernetes. This lesson walks Argo CD’s architecture, Flux’s architecture, the comparison, and the operational discipline.

Argo CD architecture

flowchart LR
    A[Git repository] --> B[Argo CD controller]
    B --> C[Application CR]
    C --> D[cluster]
    B --> E[Application controller]
    E -->|sync| D
    B --> F[Repo server]
    F -->|fetch manifests| A
    B --> G[Web UI]
    G --> H[User]

Argo CD components:

  • Application CR — declarative definition of an app to sync (source repo + path + destination cluster + namespace).
  • Application controller — reconciles actual state toward desired; syncs the cluster.
  • Repo server — fetches manifests from Git; renders Helm/Kustomize.
  • Web UI — the Argo CD dashboard.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: billing
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/example/manifests
    targetRevision: main
    path: apps/billing/overlays/prod
  destination:
    server: https://kubernetes.default.svc
    namespace: prod-app
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

The Application CR declares what to sync, from where, to where. syncPolicy.automated enables auto-sync; prune deletes resources not in Git; selfHeal corrects drift.

Flux architecture

flowchart LR
    A[Git repository] --> B[Source Controller]
    B --> C[GitRepository CR]
    C --> D[Kustomization CR]
    D -->|apply| E[cluster]
    D --> F[HelmRelease CR]
    F -->|install| G[Helm chart]
    B --> H[Helm Controller]

Flux components:

  • Source Controller — watches GitRepository CRs and fetches the source.
  • Kustomize Controller — applies Kustomize overlays.
  • Helm Controller — manages Helm releases.
  • GitRepository, Kustomization, HelmRelease — the Flux CRDs.
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: manifests
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/example/manifests
  ref:
    branch: main
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: billing
  namespace: flux-system
spec:
  interval: 5m
  sourceRef:
    kind: GitRepository
    name: manifests
  path: ./apps/billing/overlays/prod
  prune: true
  wait: true

Flux uses CRDs per concept (source, kustomization, helm release). The pattern is more Kubernetes-native than Argo CD’s single Application CR.

The comparison

flowchart LR
    A[Argo CD] --> A1[Single Application CR]
    A --> A2[Web UI built in]
    A --> A3["Sync waves, App of Apps"]
    A --> A4["Supports Helm, Kustomize, raw YAML"]
    B[Flux] --> B1["Multiple CRDs (GitRepository, Kustomization, HelmRelease)"]
    B --> B2["No web UI by default (use Weave GitOps or other)"]
    B --> B3[More Kubernetes-native]
    B --> B4["Supports Helm, Kustomize, raw YAML"]

The trade-offs:

FeatureArgo CDFlux
Web UIbuilt inrequires add-on
CRDsone (Application)many (GitRepository, Kustomization, HelmRelease)
Sync wavesyes (annotation)yes (dependsOn)
Multi-clusteryes (Application per cluster)yes (Kustomization per cluster)
MaturityCNCF GraduatedCNCF Graduated
Communitylargersmaller but growing

The choice depends on team preference. Both are production-ready.

App of Apps (Argo CD)

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: prod-apps
  namespace: argocd
spec:
  source:
    repoURL: https://github.com/example/manifests
    path: clusters/prod
  destination:
    server: https://kubernetes.default.svc
  project: default

The App of Apps pattern: a parent Application that points to a directory containing child Applications. The parent syncs the children; each child syncs its app. The pattern allows grouping apps into logical sets.

Quiz

Knowledge check · 4 questions

  1. Q1. Where does the `argocd.argoproj.io/sync-wave` annotation belong?

  2. Q2. Argo CD waits for every resource in a sync wave to become healthy before starting the next wave.

  3. Q3. Work out why merged commits have stopped reaching a Flux-managed cluster and restore reconciliation.

    Three commits merged to `main` three hours ago are absent from the `prod-app` namespace. `flux get kustomizations` shows `billing` Ready True with `Last Applied Revision: main@sha1:9c1f2ab`, which is yesterday's commit. `flux get sources git` shows `manifests` Ready False with `failed to checkout and determine revision: unable to clone: authentication required`.

  4. Q4. In Flux, which controller fetches repository contents, which one applies them, and what does a Kustomization's `sourceRef` name?

Passing score: 75%. Answers are checked in this browser.

The operational discipline

The reconciliation controller in production rests on five non-negotiable elements:

  • HA controller. The GitOps controller is critical; deploy with HA (Argo CD’s ha: true install option; Flux’s HA topology).
  • Monitor sync status. Alert on sync failures, drift, and stale syncs.
  • Test controller upgrades. Controller upgrades can break Applications; test in staging.
  • Backup controller state. The controller’s state (Application CRs, Kustomization CRs) must be backed up.
  • Document the topology. The Application / Kustomization hierarchy must be in the runbook.

The controller is production infrastructure. Treat it as such.