Skip to content
SumGuy's Ramblings
Go back

ArgoCD vs Flux: GitOps — When Your Git Repo Is the Source of Truth

The Problem GitOps Solves (And Why Your Colleague Is the Problem)

Picture a Kubernetes cluster that’s been running for two years. Services are deployed. Things mostly work. Then something breaks. You open the deployment to investigate and discover that the YAML in the cluster doesn’t match the YAML in Git. At all. There’s an environment variable that doesn’t exist in any repository. There’s a replica count that got bumped from 2 to 5 at some point. No PR. No commit. No audit trail.

Your colleague meant well. There was an incident, things were moving fast, they ran kubectl apply -f on a local file and never committed the change. Classic. No malice, just the entirely human tendency to fix the immediate problem and defer the paperwork.

GitOps is the systematic answer to this. The principle: Git is the single source of truth. The cluster should always match what’s in the repository. Any change to the cluster must happen through Git. An automated reconciliation loop continuously checks for drift and corrects it.

Two tools implement this on Kubernetes: ArgoCD and Flux. They have similar goals and different philosophies about how to get there.


What GitOps Actually Means (Practically)

Before comparing the tools, it’s worth being precise about what GitOps requires:

  1. Declarative configuration: everything about your application’s deployment lives in YAML files in a Git repository
  2. Versioned, auditable history: every change has a commit, an author, and a timestamp
  3. Automated reconciliation: a controller running in the cluster watches the repo and applies changes when they differ from cluster state
  4. Correctness by default: if someone manually edits a resource in the cluster, the controller reverts it to match Git

The last point is the controversial one for teams used to hotfixing in production. GitOps makes that harder by design. The correct fix is always: update Git, let the reconciliation loop apply it. The discipline is the point.


ArgoCD: The UI-Focused One

ArgoCD is a Kubernetes-native GitOps tool that puts a beautiful web UI front and center. You can see every application, its sync status, whether it’s healthy, and a live graph of what’s running in the cluster versus what Git says should be running. For teams new to GitOps, the visual feedback is enormously helpful.

Key ArgoCD Concepts

Application: an ArgoCD custom resource that defines what to sync — a source (Git repo + path) and a destination (cluster + namespace).

App-of-Apps pattern: a parent Application that manages other Applications, allowing you to bootstrap an entire cluster’s worth of deployments from a single ArgoCD application definition.

Sync policies: manual sync (you click a button or run a CLI command) or automated sync (ArgoCD watches for changes and applies them automatically, optionally with pruning of removed resources).

Installing ArgoCD

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

Get the initial admin password:

kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d && echo

Access the UI (port-forward for initial setup):

kubectl port-forward svc/argocd-server -n argocd 8080:443

Navigate to https://localhost:8080, log in with admin and the retrieved password.

Defining an Application

# my-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/yourorg/your-gitops-repo
    targetRevision: main
    path: apps/my-app
  destination:
    server: https://kubernetes.default.svc
    namespace: my-app
  syncPolicy:
    automated:
      prune: true       # Remove resources deleted from Git
      selfHeal: true    # Revert manual changes to cluster
    syncOptions:
      - CreateNamespace=true

Apply this and ArgoCD takes over. Any commit to apps/my-app in your repo triggers an automatic sync. Any manual kubectl edit to a managed resource gets reverted.

ArgoCD RBAC

ArgoCD has a built-in RBAC system that maps to SSO providers (GitHub, GitLab, LDAP, OIDC). This matters for teams: you can give developers read-only access to see app status without giving them sync permissions, and restrict sync to CI pipeline service accounts.


Flux: The Automation-First One

Flux takes the opposite philosophy from ArgoCD: there’s no UI. Flux is a set of Kubernetes controllers that you configure entirely through custom resources and the flux CLI. It’s designed for automation-heavy environments where you want things to happen without human checkpoints.

Flux is more composable than ArgoCD — it breaks GitOps functionality into discrete controllers (source controller, kustomize controller, helm controller, image automation controller) that can be used independently. This makes it more flexible and more complex.

Key Flux Concepts

GitRepository: a source custom resource that Flux polls for changes.

Kustomization: a Flux reconciliation unit — it takes a GitRepository source and applies it to the cluster using Kustomize.

HelmRelease: like a Kustomization but for Helm charts. Flux’s helm controller manages chart deployment and upgrades.

Image Automation: Flux can scan container registries for new image tags and automatically update your Git repository with the new tag, then sync the change to the cluster. This is Flux’s killer feature for CI/CD pipelines — new image → Flux updates Git → Flux deploys it.

Installing Flux

The flux CLI bootstraps everything:

# Install the flux CLI
curl -s https://fluxcd.io/install.sh | sudo bash

# Bootstrap Flux on your cluster (GitHub example)
flux bootstrap github \
  --owner=yourorg \
  --repository=your-gitops-repo \
  --branch=main \
  --path=./clusters/my-cluster \
  --personal

Bootstrap creates the Flux controllers in the cluster AND commits the Flux system manifests to your repo, so the Flux installation itself is version-controlled. This is a nice design choice.

Defining a Flux Source and Kustomization

# /clusters/my-cluster/apps/source.yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/yourorg/your-gitops-repo
  ref:
    branch: main
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 10m
  path: ./apps/my-app
  prune: true
  sourceRef:
    kind: GitRepository
    name: my-app

Flux polls the GitRepository every minute and applies the Kustomization every 10 minutes (or immediately on detected change).

Image Automation: Flux’s Superpower

Flux can watch a container registry, detect new image tags, update your Git repo, and deploy — all automatically:

apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
  name: my-app
  namespace: flux-system
spec:
  image: registry.example.com/my-app
  interval: 5m
---
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"

When a new image matching the policy appears, Flux updates the deployment YAML in Git and applies it. Your CI pipeline just needs to push an image — Flux handles the rest.


ArgoCD vs Flux: Side by Side

FeatureArgoCDFlux
Web UIYes (excellent)No (CLI only, plus Weave GitOps)
Multi-clusterYesYes
Helm supportYesYes (HelmRelease CRD)
Kustomize supportYesYes (first-class)
RBACBuilt-in, SSO supportKubernetes RBAC
Image automationVia Argo Image Updater (addon)Built-in, mature
App-of-Apps patternNativeVia Kustomization composition
Drift detectionYes, visualYes, automated
Self-healingYes (selfHeal policy)Yes (reconciliation loop)
Installation complexityMediumLow (flux bootstrap CLI)
Learning curveLower (UI helps)Higher (all CRDs and CLI)
CommunityLarge, CNCF graduatedLarge, CNCF graduated
Best forTeams new to GitOpsAutomation-heavy pipelines

When to Use Each

Choose ArgoCD when:

Choose Flux when:

Both tools are CNCF graduated projects with strong communities. You’re not making a bet on vaporware. Pick based on your team’s workflow, not on hype. And both of them will prevent the scenario where your colleague applies YAML directly to production at 2am and forgets to commit it. That alone is worth the adoption cost.


Share this post on:

Previous Post
Tmpfs vs Ramfs: When Your Disk Is Too Slow and Your RAM Is Just Sitting There
Next Post
Docker Health Checks: Because "It's Running" Doesn't Mean "It's Working"