Argo CD
Declarative GitOps continuous delivery for Kubernetes. A controller compares the manifests rendered from a Git revision with the live state of each target cluster, reports drift, and applies the Git state on a manual or automated sync. Apache 2.0, a CNCF graduated project, and free to self-host. It fits teams that want Git as the record of what runs, a web UI per application, and one control plane for several clusters.
Argo CD keeps Kubernetes clusters in line with a Git repository. Each Application points at a repo, a revision and a path; Argo CD renders the manifests there, compares them with what is running, and shows every difference before anything changes. The official docs at argo-cd.readthedocs.io own the full reference.
What it is
A set of Kubernetes controllers and servers, normally installed in an argocd namespace: an API server with the web UI, a repository server, an application controller, an ApplicationSet controller, a notifications controller, a bundled Dex for SSO, and Redis as a cache. The argocd CLI talks to the API server. Configuration is Kubernetes-native: Applications, AppProjects and ApplicationSets are CRDs, and settings live in the argocd-cm, argocd-rbac-cm and argocd-cmd-params-cm ConfigMaps. Licence is Apache 2.0. Argo CD is part of the Argo family with Argo Workflows, Argo Rollouts and Argo Events.
The current line is v3.5 (v3.5.5 shipped 2026-10-12). Minor releases come four times a year, and only the three most recent minors get patches, so 3.5, 3.4 and 3.3 are supported today. v3.6 is in release candidates (rc3 on 2026-10-15) with GA planned for 2026-11-03. Argo CD 3.5 is tested against Kubernetes 1.33 to 1.36.
The breaking changes in v3.5:
- Helm v4. Argo CD now renders charts with Helm 4, and
spec.source.helm.version: v3is ignored. Helm 4 is strict about OCI registries without TLS: plain-HTTP OCI repos need--insecure-oci-force-http, and plain-HTTP OCI chart dependencies must be registered as repos too. - UI extensions built for the old React 16 UI must be rebuilt for React 19.
- gRPC event-listing methods return an Argo CD
EventListtype. REST paths and JSON bodies are unchanged; generated gRPC clients must be regenerated. - GnuPG verification is replaced by Source Integrity. Old
signatureKeysconfig still works with a warning.
The 3.0 release (May 2025) also changed defaults that still surprise upgrades: annotation-based resource tracking, logs as a separate RBAC resource, and, with Dex, RBAC subjects taken from federated_claims.user_id instead of sub.
How it works
Three components carry the work. The repository server clones Git, resolves the revision to a commit and renders manifests with Helm, Kustomize, plain YAML or a config-management plugin. The application controller watches the live resources in each target cluster, asks the repo server for the desired manifests, and diffs the two. The API server serves the UI, CLI and webhooks, handles SSO and RBAC, and records sync requests on the Application object. Redis caches rendered manifests and cluster state so that a refresh does not re-render every chart.
A refresh happens every 120 seconds by default (timeout.reconciliation) with up to 60 seconds of jitter, or at once when a Git webhook arrives. A refresh only updates status. Changes reach the cluster on a sync: automatically when the Application has syncPolicy.automated, or only when someone starts it when that block is absent.
Step 1 of 4. The UI or argocd login --sso goes to the API server, which redirects to Dex at /api/dex.
Manual sync with prune. With an automated sync policy the controller starts the sync itself after a refresh.
Ownership is recorded on every object Argo CD applies. Since 3.0 the default is the argocd.argoproj.io/tracking-id annotation, which lets prune find objects that left Git without touching objects created by other tools. An AppProject limits which repos, clusters, namespaces and resource kinds its Applications may use, and is the main multi-tenant boundary.
When to use it
Reach for it when:
- Git should be the record of what runs, and every change should show as a diff before it applies.
- Several clusters (beta, prod, edge) are deployed from one control plane, each from its own branch, path or overlay.
- People who deploy need a web UI that shows each app's resource tree, health, events and logs.
- Releases need ordering: database migrations as PreSync hooks, sync waves for CRDs before operators.
Skip it when:
- The cluster is a single dev box and
helm upgradefrom a terminal is enough. - Helm release semantics (
helm list,helm rollback, chart hooks run by Helm) must be kept. Argo CD renders withhelm templateand applies plain manifests; Helm does not own the release. - Fleet in a Rancher install, or Flux, is already doing the job. Two GitOps controllers on one object will fight.
At a glance
Core concepts
- Application — one source (repo, revision, path, and Helm or Kustomize options) and one destination (cluster and namespace). Multi-source Applications are supported.
- AppProject — allowed sources, destinations and resource kinds, plus project-scoped roles and sync windows.
- ApplicationSet — a template plus generators (list, cluster, Git, matrix) that create Applications at scale.
- Sync policy — manual by default;
automatedwith optionalpruneandselfHeal; sync options such asServerSideApply=trueorCreateNamespace=true. - Sync status and health — two separate fields. Synced means it matches Git; Healthy means it is working.
- Sync waves and hooks — the
argocd.argoproj.io/sync-waveannotation orders resources; hook annotations run Jobs before, during or after a sync.
Key facts (v3.5)
| Item | Value |
|---|---|
| Licence | Apache 2.0, CNCF graduated |
| Latest release | v3.5.5 (2026-10-12) |
| Supported minors | 3.5, 3.4, 3.3 |
| Tested Kubernetes | 1.33 to 1.36 |
| Helm chart | argo/argo-cd 10.10.5 (app v3.5.5) |
| Bundled Helm | v4 |
| Default refresh | 120 s plus up to 60 s jitter |
| Default tracking | annotation (argocd.argoproj.io/tracking-id) |
Argo CD, Flux and Fleet compared
| Aspect | Argo CD | Flux | Fleet |
|---|---|---|---|
| Model | Hub pushes to many clusters, or one per cluster | Agent in each cluster pulls | Rancher manager plus agent per cluster |
| Web UI | Built in | None in the core project | Rancher's UI |
| Helm | Rendered with helm template, applied as manifests |
Real Helm releases | Real Helm releases (bundles) |
| Ordering | Sync waves and hooks | dependsOn between Kustomizations |
dependsOn between bundles |
| SSO and RBAC | Own, through Dex or OIDC | Kubernetes RBAC | Rancher's |
How to integrate
Install with Helm
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd -n argocd --create-namespace -f values.yaml
SSO through Dex to an OIDC provider
configs:
cm:
url: https://argocd.example.com
admin.enabled: "true" # local admin kept as break-glass
dex.config: |
connectors:
- type: oidc
id: keycloak
name: Keycloak
config:
issuer: https://sso.example.com/realms/platform
clientID: argocd
clientSecret: $dex.keycloak.clientSecret # key in argocd-secret
insecureEnableGroups: true # pass the groups claim through
scopes: [openid, profile, email, groups]
rbac:
policy.default: "" # no access unless a rule grants it
scopes: "[groups]"
policy.csv: |
g, platform-admins, role:admin
secret:
extra:
dex.keycloak.clientSecret: "<client secret>"
The redirect URI to register in the identity provider is https://argocd.example.com/api/dex/callback. The provider must put group names in a groups claim.
A repo over SSH with a read-only deploy key
apiVersion: v1
kind: Secret
metadata:
name: platform-repo
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
type: git
url: [email protected]:example/platform.git
sshPrivateKey: |
-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----
Add the Git host's key to argocd-ssh-known-hosts-cm. Since 3.5 that ConfigMap is used for every SSH repo, including repos with no credentials.
A manually synced Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: prod
namespace: argocd
spec:
project: default
source:
repoURL: [email protected]:example/platform.git
targetRevision: main
path: overlays/prod
destination:
name: prod # a cluster registered with argocd cluster add
namespace: default
syncPolicy:
syncOptions:
- ServerSideApply=true
# no "automated" block: syncs run only when started by hand
Review and sync
argocd login argocd.example.com --sso
argocd app diff prod
argocd app sync prod --prune
argocd app history prod
In the GL stack
Argo CD v3.5.5 runs as a hub on the management cluster and deploys to the two workload clusters. There are two Applications. The beta one tracks the beta branch and targets the beta cluster; the prod one tracks main and targets the prod cluster. The branch rule is feature to beta to main, so a change reaches prod only after it has been merged to beta and then promoted.
Neither Application has an automated sync policy. Beta is synced by hand, and prod syncs only when someone starts it, with prune on so that objects removed from Git are removed from the cluster too. A merge to main therefore marks prod OutOfSync and stops there; the diff is read before the sync runs.
Sign-in goes through Keycloak by way of the bundled Dex. The local admin account stays enabled as break-glass for when SSO is down. Argo CD reads the repository with a read-only deploy key, so a compromise of Argo CD cannot push to Git.
Argo CD is the only GitOps tool for applications. Fleet, which every Rancher install includes, delivers only Rancher's own agent bundles, so no workload has two controllers that could disagree about its state. Product images are built by Argo Workflows and tagged by git SHA, and the manifests in Git name those tags.
Gotchas
- Synced is not Healthy. An app can match Git and still have a crash-looping Deployment. Alert on health as well as sync status.
- Helm 4 and plain-HTTP OCI. After an upgrade to 3.5, charts pulled from an OCI registry without TLS fail until the repo has
insecureOCIForceHttp: "true". Setting--insecure-skip-server-verificationon the same chain silently cancels it, and there is no workaround. - Dex RBAC subjects changed in 3.0. Policies written against the Dex
subclaim stop matching. Bind to groups, or to thefederated_claims.user_idvalue. - Dex sessions do not refresh.
refreshTokenThresholddoes not apply to Dex's web login; when the Dex token expires, the user signs in again. Groups are also read only at sign-in. - The initial admin password. It is generated into the
argocd-initial-admin-secretsecret. Change it, then delete that secret; it has no other purpose, and Argo CD re-creates it only when a new admin password must be generated. - Prune follows tracking. Objects with a copied
tracking-idannotation, or apps that share resources, can be pruned by the wrong Application. Keep each object under one Application. - Large CRDs and server-side apply. Client-side apply stores the full object in an annotation and fails above 262,144 bytes.
ServerSideApply=trueavoids that. - Settings changes need restarts. A change to
timeout.reconciliationtakes effect only after the repo server and application controller are restarted.
Risks
- Licence and project health. Apache 2.0 under the CNCF, with a public release calendar, named release champions and many vendors contributing. The risk of the project stopping is low.
- Hub blast radius. A hub holds credentials for every cluster it manages, usually cluster-admin. A compromise of the hub's namespace is a compromise of every cluster. Restrict who can reach it and keep AppProjects tight.
- Security record. The API server and repo server parse untrusted input (Git content, Helm charts, plugins) and have had CVEs. Stay on a supported minor and take patch releases.
- Lock-in. Low for content: the repo holds plain YAML, Kustomize and Helm. Moderate for the control layer: Applications, sync waves, hooks and ApplicationSets need rewriting for Flux or Fleet.
Alternatives
- Flux — pick it for a pull model with an agent in each cluster, real Helm releases and image update automation, with no central UI.
- Fleet — pick it inside Rancher when many clusters are targeted by label and Rancher's UI is enough.
- Helm or Kustomize from CI — pick it for a single cluster where a pipeline that runs
helm upgradeis simpler than another controller. - A hosted Argo CD service — pick it to keep Argo CD's model without running the hub.
Related
- Fleet — the GitOps engine in Rancher, used here only for Rancher's own bundles.
- Rancher and K3s — the cluster manager and the distro under the clusters Argo CD deploys to.
- Keycloak — the identity provider behind Dex.
- Argo Workflows and Distribution registry — where the deployed images are built and stored.
- Redis — the cache Argo CD bundles.
- Official: Argo CD docs, Upgrading 3.4 to 3.5, Releases, Helm chart.
