GitOps is now the standard deployment model for Kubernetes in 2026. Instead of running kubectl apply from a CI runner, you declare desired state in Git and let a controller inside the cluster reconcile actual state toward it. The two dominant tools are ArgoCD and Flux — both are mature CNCF projects, but they make different tradeoffs that matter for real teams.
For a detailed side-by-side feature matrix, see the ArgoCD vs Flux comparison. This post covers the conceptual differences, when each tool fits, and how to migrate from a push-based CI/CD setup.
GitOps Principles in 30 Seconds
GitOps rests on four ideas:
- ›Declarative — everything about the system is expressed as config (YAML, Helm values, Kustomize overlays)
- ›Versioned and immutable — Git is the single source of truth; every change is a commit
- ›Pulled automatically — the cluster pulls state from Git, rather than CI pushing to the cluster
- ›Continuously reconciled — a controller watches for drift and corrects it
The pull model is the key security win: your CI runner never needs cluster credentials. The cluster credentials stay inside the cluster.
Architecture Comparison
ArgoCD runs as a central server with a controller, API server, and repo server. Applications are CRDs (Application, AppProject) stored in the cluster. The UI is a first-class citizen with visual diff views, sync status, and resource graphs.
Flux is a collection of small controllers (source-controller, kustomize-controller, helm-controller, notification-controller) that each do one thing. There is no built-in UI — you use the flux CLI and GitRepository/Kustomization/HelmRelease CRDs directly. The GitOps Toolkit architecture means you can use only the components you need.
Feature Comparison
| Feature | ArgoCD | Flux |
|---|---|---|
| Web UI | Full-featured, visual resource graph | None (use Weave GitOps or third-party) |
| CLI | argocd CLI (connects to API server) | flux CLI (talks directly to cluster) |
| Helm support | Native (ApplicationSource Helm) | Dedicated HelmRelease CRD |
| Kustomize support | Native | Native (dedicated controller) |
| Multi-tenancy | AppProject for namespace/cluster isolation | Tenant namespacing via ServiceAccount per Kustomization |
| Multi-cluster | Built-in (cluster registration in ArgoCD) | Bootstrap each cluster separately; Flux Hub pattern |
| Notifications | argocd-notifications (Slack, Teams, PD, etc.) | notification-controller (similar integrations) |
| SSO / RBAC | OIDC, SAML, LDAP; internal RBAC model | Delegates to Kubernetes RBAC entirely |
| Resource usage | ~300–500 MB RAM (full stack) | ~80–150 MB RAM (base controllers) |
| Drift detection | Visual diff, sync status per app | flux diff kustomization CLI |
| Image automation | Separate argocd-image-updater | Built-in image-reflector-controller |
| OCI artifacts | Supported | Supported (source-controller) |
| CNCF status | Graduated | Graduated |
When to Choose ArgoCD
ArgoCD is the better fit when:
- ›Your team wants a UI. The ArgoCD dashboard is genuinely useful — you can see sync status, diff desired vs actual state, and trigger manual syncs without touching the CLI. For teams with mixed Kubernetes experience, this matters.
- ›You manage many applications on multiple clusters. ArgoCD's
ApplicationSetcontroller can generate hundreds ofApplicationCRDs from templates, making it practical for platform teams managing dozens of clusters. - ›You need multi-tenant isolation.
AppProjectenforces which Git repos, clusters, and namespaces a team can deploy to — all from one ArgoCD instance.
Use the ArgoCD Application Generator to scaffold the Application and AppProject CRDs for your setup.
When to Choose Flux
Flux is the better fit when:
- ›You want GitOps-native everything. Flux's own config is managed via GitOps (the bootstrap process commits Flux CRDs to your repo). ArgoCD's config can live in the cluster without a Git backing.
- ›You need minimal footprint. At ~80–150 MB RAM, Flux fits comfortably on small clusters. ArgoCD's API server, controller, and repo server together consume more, especially at scale.
- ›You prefer CLI-driven workflows. Flux's operator model and
fluxCLI fit naturally into infrastructure-as-code teams that are already comfortable withkubectland don't want a separate UI. - ›Image automation matters. Flux's built-in
image-reflector-controllerandimage-automation-controllercan automatically update manifests when a new image tag is pushed — without a separate tool.
Migrating from CI/CD Push to GitOps Pull
If you're currently deploying via kubectl apply or helm upgrade from a CI runner, here's the migration path:
1. Move your manifests to a Git repo
Structure matters. A common layout:
infra/
clusters/
production/
flux-system/ # Flux bootstrap or ArgoCD config
apps/
my-app.yaml # Application or HelmRelease CRD
apps/
my-app/
base/
deployment.yaml
service.yaml
overlays/
production/
kustomization.yaml
2. Install the GitOps controller
Flux bootstrap (writes to Git automatically):
flux bootstrap github \
--owner=my-org \
--repository=k8s-config \
--branch=main \
--path=infra/clusters/production \
--personal
ArgoCD install:
kubectl create namespace argocd
kubectl apply -n argocd -f \
https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
3. Create your first Application or Kustomization
ArgoCD Application:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/my-org/k8s-config
targetRevision: HEAD
path: infra/apps/my-app/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
Flux Kustomization:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: my-app
namespace: flux-system
spec:
interval: 5m
path: ./infra/apps/my-app/overlays/production
prune: true
sourceRef:
kind: GitRepository
name: k8s-config
targetNamespace: production
4. Remove cluster credentials from CI
Once the controller is reconciling from Git, your CI pipeline only needs to push to the Git repo — not to the cluster. Remove the KUBECONFIG secret from your CI environment and update the pipeline to commit manifests (or update Helm values files) instead of running kubectl.
Summary
Neither tool is universally better. ArgoCD wins on UI and multi-cluster management. Flux wins on lightweight footprint and pure GitOps purist design. Both are production-proven at scale.
If your team is small and CLI-comfortable: start with Flux. If you're managing multiple clusters or need a UI for non-platform engineers: ArgoCD. You can always migrate later — both tools read standard Kubernetes manifests and Helm charts.