Home
DevOps & Cloud Engineering / Lesson 34 — GitOps with ArgoCD & Flux

GitOps with ArgoCD & Flux

Git as the source of truth for infrastructure. Continuous reconciliation, audit trails, declarative everything.


What GitOps Means

GitOps is a discipline: the desired state of every system lives in Git. Software running in clusters reconciles toward that state continuously.

Old model — push:

Text
Engineer → CI runs kubectl apply → cluster

GitOps — pull:

Text
Engineer → commits to Git → ArgoCD/Flux notices → applies to cluster

The differences are subtle but important:

1. Git is the source of truth. Whatever is in main is what should be running. Period.

2. Drift detection. If someone manually changes a deployment in the cluster, ArgoCD notices and flags (or reverts) the drift.

3. No CI access to production. CI doesn't need cluster credentials. The cluster pulls — it has its own identity.

4. Audit trail by default. Every change is a Git commit. Want to know what's running and why? git log.

5. Declarative everywhere. You describe what should exist, the system makes it so.

The two main tools: ArgoCD and Flux. Both CNCF-graduated. Both are excellent. The choice is mostly preference.


ArgoCD — UI-First GitOps

ArgoCD has a great web UI showing what's deployed, sync status, recent commits.

Setup:

Bash
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Define what to sync — an Application:

YAML
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/myapp-config
    path: k8s/production
    targetRevision: main
  destination:
    server: https://kubernetes.default.svc
    namespace: myapp
  syncPolicy:
    automated:
      prune: true       # delete resources no longer in Git
      selfHeal: true    # revert drift back to Git state
    syncOptions:
      - CreateNamespace=true

Once applied, ArgoCD watches the Git repo. New commits → sync to cluster. Manual changes in cluster → reverted to match Git.

The UI shows:
• Every Application's sync status (in sync, out of sync, syncing)
• Diff between Git and cluster
• Resource tree (Deployment → ReplicaSet → Pods)
• Recent events and logs

Good for: teams that value visibility, multi-cluster setups, large numbers of applications.


Flux — Lighter, More Modular

Flux is the other major GitOps tool. Smaller footprint, no UI by default (you can use Weave GitOps or other UIs).

Setup with the Flux CLI:

Bash
flux bootstrap github \
  --owner=myorg \
  --repository=fleet-config \
  --branch=main \
  --path=clusters/production

This creates a Git repo, installs Flux in the cluster, and configures Flux to watch that repo.

Then you commit Kubernetes manifests, Helm charts, or Kustomize overlays. Flux applies them.

Helm release via Flux:

YAML
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: myapp
  namespace: production
spec:
  interval: 5m
  chart:
    spec:
      chart: myapp
      version: '1.x'
      sourceRef:
        kind: HelmRepository
        name: my-helm-repo
  values:
    replicas: 5
    image:
      tag: v1.2.3

Image automation — Flux can also automatically update Helm values when new images are pushed. You commit the new tag back to Git, completing the GitOps loop.

ArgoCD vs Flux:
• Want a UI: ArgoCD
• Want lightweight, CLI-driven: Flux
• Both work well. Try both, pick what fits your workflow.


Repo Structure for GitOps

Two patterns dominate:

Mono-repo — all environment configs in one repo

Text
fleet-config/
  base/                  # base manifests
    deployment.yaml
    service.yaml
  overlays/
    dev/
      kustomization.yaml
    staging/
      kustomization.yaml
    production/
      kustomization.yaml

ArgoCD/Flux applies the right overlay to the right cluster.

App-of-apps — one Application that points to many Applications

YAML
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: production-apps
spec:
  source:
    repoURL: https://github.com/myorg/fleet-config
    path: production-apps    # this dir contains many Application YAMLs

Adding a new app = committing a new Application to that directory. ArgoCD picks it up automatically.

Per-app repos vs central repo
• Central — easier governance, single source of truth
• Per-app — teams move independently, more autonomy

Most teams: central config repo, separate from app code repos. App code repo CI builds image and pushes a tag. A bot opens a PR to the central config repo bumping the tag. Reviewer merges → ArgoCD deploys.


Image Updates — Closing the Loop

Without image automation, GitOps requires a manual step: code repo merges → image built → human edits config repo to bump tag → ArgoCD deploys.

Better: automate the bump.

Approaches:

1. ArgoCD Image Updater — watches a registry, updates Git automatically when new images appear.

2. Flux Image Automation — same idea. Flux's built-in feature.

3. CI commits to config repo — your app's CI does it after pushing the image:

YAML
- name: Update config repo
  run: |
    git clone https://github.com/myorg/fleet-config
    cd fleet-config/production
    yq e -i '.image.tag = "${{ github.sha }}"' values.yaml
    git commit -am "bump production to ${{ github.sha }}"
    git push

This last approach is simple and explicit. The CI bumps the tag; the GitOps tool deploys.

For mature setups, automation policies define WHICH images get auto-bumped:
• Production: only after manual approval (human merges PR)
• Staging: auto-merge if image scan passes
• Dev: auto-merge always


Multi-Cluster GitOps

As you scale, you may have multiple clusters: per-region, per-team, per-environment. GitOps scales naturally.

ArgoCD: one ArgoCD instance can manage many clusters. Add clusters as resources, then target Applications at specific clusters.

Flux: each cluster runs its own Flux. Each cluster's repo is shaped to its needs.

Patterns:
• Hub-and-spoke — one central ArgoCD manages everything
• Federated — each cluster has its own ArgoCD/Flux
• Hybrid — central for shared services, local for app-specific

For very large fleets (hundreds of clusters), specialized tools:
• Rancher Fleet
• ArgoCD ApplicationSets
• KubeVela

The big win of GitOps + multi-cluster: every cluster's state is in Git. Reproducing a cluster (after a disaster, or for testing) is git clone + bootstrap. Cattle, not pets, applied to entire clusters.


⁂ Back to all modules