Git, CI/CD & GitOpsLXXVII · Argo CDArchitecture
Argo CD architecture — the three components and the data flow
What you'll learn
- Name the three core components of the Argo CD control plane and the role each plays
- Trace the data flow from a Git commit to a Kubernetes reconcile
- Distinguish the stateless controller components from the stateful cluster connection
- Identify where the cache, the manifest rendering, and the API surface live in the architecture
Prerequisites
Practice
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
Argo CD is not a single binary. It is a control plane of three stateless services backed by Redis and a per-cluster credential store, talking to one or more Kubernetes API servers. Treating Argo CD as a single process hides where the work happens and where failure modes live. This lesson decomposes the control plane and traces the path from a Git commit to a Kubernetes reconcile so the next five lessons land on a model that already knows where each piece runs.
The three components
The Argo CD control plane has three stateless components, each backed by a shared Redis cache, and a per-cluster credential store. The names match the verbs the component owns:
- API server. The gRPC/REST surface that the CLI and UI talk to. Owns authentication, project and RBAC enforcement, Application CRUD, and the read paths the UI consumes. Does not apply manifests; validates requests and writes them to etcd.
- Repo server. Owns manifest rendering. Clones the Git source, resolves Helm values, runs Kustomize, evaluates plugins, and returns rendered manifests. The only component that talks to Git directly.
- Application controller. Owns the reconcile loop. Reads Applications from the Kubernetes API, asks the repo server for desired manifests, reads live state from the target cluster, computes the diff, and either auto-syncs or surfaces the diff.
flowchart LR
U["Operator: CLI or UI"] --> API["API server"]
API --> K8s[("etcd / kube-apiservers")]
K8s --> AC["Application controller"]
AC --> RS["Repo server"]
RS --> G["Git / Helm / OCI source"]
AC --> C["Target Kubernetes cluster"]
RS --> Cache[("Redis cache")]
API --> Cache
AC --> Cache
The shared Redis cache is what makes the components stateless. The repo server caches rendered manifests so a controller reconcile loop does not re-render every three seconds; the controller caches live cluster state so the diff does not require a fresh API call on every loop. Redis is the hot path; etcd is durable.
The data flow
A Git commit becomes a Kubernetes reconcile through this path:
- The Application is registered against a source (Git, Helm,
OCI) and a destination (a cluster server URL and a namespace).
The registration lives in the Argo CD namespace as an
ApplicationCRD. - The application controller observes the Application and schedules a reconcile. The default interval is three minutes for polling; webhooks can short-circuit when Git pushes happen.
- The controller calls the repo server with the source reference and asks for rendered manifests. The repo server clones the source (or reads its cache), runs the appropriate renderer (Helm, Kustomize, directory, plugin), and returns the manifest set.
- The controller reads the live state from the target cluster using its stored credentials (ServiceAccount token, kubeconfig, or cloud IAM identity).
- The controller diffs desired against live. Match:
Synced. Mismatch:OutOfSync, and the sync policy decides what happens next. - Automated sync: the controller applies the diff itself.
Manual sync: the controller waits for an operator to run
argocd app sync.
sequenceDiagram
participant Git
participant Repo as Repo server
participant Ctrl as Application controller
participant K8s as Target cluster
Git->>Repo: clone source at revision
Repo->>Repo: render (Helm / Kustomize / plugin)
Repo->>Ctrl: rendered manifests
Ctrl->>K8s: list live resources
K8s->>Ctrl: live state
Ctrl->>Ctrl: diff desired vs live
alt Synced
Ctrl->>Ctrl: status = Synced
else OutOfSync
Ctrl->>K8s: apply diff (if policy = automated)
end
The same flow runs on a timer. That is the central operational property of Argo CD: it is a reconciler, not an event-driven deployer. Every interval, it re-reads desired state, re-reads live state, and re-diffs. A successful deploy is not an event the system records; it is the absence of a diff at the end of a reconcile.
Where each piece of state lives
The separation matters when something breaks:
- The Application CRD lives in the Argo CD namespace’s etcd. Deleting the CRD unregisters the deployment but does not delete deployed resources; they remain until pruned.
- The rendered manifest cache lives in Redis and on the repo server’s filesystem. A repo server restart re-renders; a Redis flush forces a re-render across the fleet.
- The cluster credentials live in Secrets in the Argo CD namespace. Losing the Secret without a backup is a production outage.
- The live state cache lives in Redis. The controller refreshes it on every reconcile.
Under the hood
The three-component split answers a scaling problem. A single-process reconciler that reads Git, renders manifests, reads the cluster, and applies diffs has one bottleneck: the slowest step. Argo CD splits the work so the slowest step in one environment does not block others. A team with slow Helm charts needs repo server replicas and Redis memory; a team with a slow target cluster API needs application controller replicas and healthy kubeconfig credentials. The two scaling problems are independent.
Production discipline
The operational rules for the Argo CD control plane:
- The repo server has at least two replicas. A single repo server is a single point of failure for every Application that renders manifests. Helm and Kustomize renders are not free.
- Redis is sized for the cache, not for ephemeral state. The repo server’s rendered-manifest cache, the controller’s cluster-state cache, and the API server’s RBAC cache all live in Redis. Underestimating Redis is the most common Argo CD production failure.
- Cluster credentials are backed up. Losing the Secret that holds the target cluster’s ServiceAccount token without a backup is a cluster re-onboarding event.
Cross-course references
- Kubernetes for Production Sysadmins - Parts IX-XII (RBAC and Cluster API) cover the cluster credentials the application controller uses and the ServiceAccount model Argo CD inherits.
- Git, CI/CD & GitOps for Infrastructure Engineers - Part LXXIV (GitOps Controllers) is the architectural context; Part LXXV (Pull-based Deployment) is the operational pattern.
- Linux for Production Sysadmins - Parts XXVII-XXIX (Caching and Redis Operations) cover the operational side of the Redis cache.
Quiz
Knowledge check · 4 questions
Q1. Which Argo CD component is responsible for rendering Helm and Kustomize templates into the manifest set the controller diffs against the cluster?
Q2. Argo CD applies a successful deploy as a one-shot event recorded in the system log; subsequent reconciles do not re-check the deployment.
Q3. Name the three Argo CD components and identify which one owns the reconcile loop and which one owns manifest rendering.
Q4. Diagnose the failure and identify which component is the bottleneck.
A team operates Argo CD with one repo server replica and a single Redis instance. After upgrading to a chart with 800 Applications, half of which use Helm charts that take 20 seconds to render, the team observes that Applications take ten minutes to reflect Git changes. The controller logs are clean; the API server response times are normal; the repo server CPU is pinned at 100%.
Passing score: 75%. Answers are checked in this browser.