Argo CD vs Flux, deployed side by side on kind
Argo CD and Flux both pull Kubernetes manifests from Git and keep a cluster
in step with them. Both are CNCF graduated projects: Flux since
November 30, 2022, Argo since
December 6, 2022. This comparison
deploys the same app from the same Git commit once through each, on its own
kind cluster, and a CI job fails unless both reach their ready state and
behave as described below. The code is
argocd-vs-flux
in kadet-hub/examples; the numbers below are from one local run of its
check on kind in Docker.
Render, then deliver
Helm, Kustomize and Kapitan render manifests. Argo CD and Flux deliver them: they fetch a revision from Git, apply it and report whether the cluster matches. So “Helm vs Argo CD” is not a choice between two tools for the same job: Argo CD or Flux deploys what Helm, Kustomize or Kapitan produced.
Both delivery tools render Helm charts and Kustomize directories themselves,
but they treat Helm differently. Argo CD runs helm template and applies
the result as its own objects, so helm ls does not show the app
(Argo CD FAQ).
Flux’s helm-controller performs Helm actions such as install, upgrade and
rollback, and keeps the release in Helm’s storage
(HelmRelease).
Kapitan writes plain YAML files, which both read without extra tooling:
Argo CD as a directory source with recurse: true
(directory apps),
Flux by generating a kustomization.yaml for a path that has none
(Kustomization).
The example
One Kapitan inventory has three
targets. web renders the app with the
kubernetes generator: a
Namespace, a Deployment of nginx-unprivileged with two replicas under the
restricted Pod Security profile, and a Service. argocd renders the
Application with the argocd generator, flux the
GitRepository and Kustomization with the flux
generator:
# inventory/targets/argocd.yml
parameters:
generators:
argocd:
applications:
web:
project: default
destination: web
source:
repoURL: http://gitea.git.svc.cluster.local:3000/kadet/app.git
targetRevision: main
path: web
directory:
recurse: true
sync_policy:
automated:
prune: true
selfHeal: true# inventory/targets/flux.yml
parameters:
generators:
flux:
git_repositories:
app:
url: http://gitea.git.svc.cluster.local:3000/kadet/app.git
ref: main
kustomizations:
web:
source: app
path: ./web
prune: trueThe argocd generator fills in server: https://kubernetes.default.svc for
the destination; the flux generator writes the sourceRef, a 1 minute
interval on the GitRepository and the recommended Kustomization settings,
including a 60 minute interval.
The check pushes the compiled app as one commit to a Gitea inside the
cluster, because the commit has to exist before either tool can deploy it.
It then installs Argo CD 3.5.5 or Flux 2.9.6 from the release’s
install.yaml, pinned by sha256, on Kubernetes 1.37.0, applies the tool’s
target and asserts with Chainsaw that the Application is Synced and
Healthy, or the Kustomization Ready, at exactly the pushed commit, and
that both replicas are available. argocd-vs-flux/check argocd and
argocd-vs-flux/check flux run the same locally, given Docker, kind,
kubectl, Chainsaw and a logged-in gh for verifying the generators.
What each installs
| Argo CD 3.5.5 | Flux 2.9.6 | |
|---|---|---|
CRDs in install.yaml |
3 | 15 |
| Pods | 7 | 7 |
| Images | 3: argocd, dex, redis |
7, one per controller |
install.yaml applied until all workloads available |
68 s | 72 s |
| Memory working set of those pods after the check | 277 MiB | 162 MiB |
The install time is mostly image pulls: over three runs Flux took between 72 and 102 seconds. Memory comes from the kubelet’s summary API, with the tool idle and one app deployed.
Argo CD’s seven pods are the application controller, the repo server, the API server that serves the web UI and CLI, the ApplicationSet controller, the notifications controller, Redis and Dex for SSO. A headless core install drops the API, notifications and SSO and relies on Kubernetes RBAC.
Flux’s install.yaml holds all seven controllers, including image
automation and source-watcher. flux install and flux bootstrap install
four by default: source, kustomize, helm and notification controller
(defaults).
None of them serves a UI.
Time to sync
From creating the Application to the Deployment reporting available took 10 seconds, and as long from creating the Kustomization. Both include pulling the nginx image, so at this size the tools do not differ in a way that matters.
After the first sync, Argo CD checks Git for new commits every 120 seconds
plus up to 60 seconds of jitter
(timeout.reconciliation),
Flux at the GitRepository’s interval, 1 minute here. Both accept a webhook
from the Git server to skip the wait: Argo CD on its API server
(webhooks),
Flux through a Receiver
(receivers).
Drift
The check scales the Deployment to one replica with kubectl scale.
Argo CD’s application controller continuously compares the live objects
with Git
(architecture).
With selfHeal on, it scaled the Deployment back to two replicas 2 seconds
later. Without selfHeal it would mark the Application OutOfSync and
leave the change in place
(automated sync).
Flux did not react. After 30 seconds the Deployment still had one replica
and the Kustomization still reported Ready. kustomize-controller
corrects drift when it reconciles: at the Kustomization’s interval, 60
minutes here, or on request. Setting the reconcile.fluxcd.io/requestedAt
annotation, which flux reconcile kustomization does, restored two replicas
1 second later
(triggering a reconcile).
A shorter interval narrows the window at the cost of more applies.
Choosing
Choose Argo CD when people need a UI to see and sync applications, when one installation should deploy to many clusters registered as Secrets (clusters), or when drift should be undone within seconds.
Choose Flux when a cluster should run controllers only, with Kubernetes RBAC as the access model and no API server or UI of its own, when Helm releases should stay Helm releases, or when image updates should be written back to Git by the image automation controllers (image updates). A Kustomization can also apply to a remote cluster through a kubeconfig Secret (remote clusters).
With either tool, the argocd and flux generators render the delivery objects from the same Kapitan inventory as the app, so a new target and its Application or Kustomization are one change. The Helm alternatives guide compares the tools that render the app itself.