What is ArgoCD? GitOps CD for Kubernetes Explained
Every team using Kubernetes eventually faces the same question: how does code actually get from a merged pull request into the running cluster? A common starting point is a CI pipeline that runs kubectl apply or helm upgrade at the end of a build. This works, but it means your pipeline needs cluster credentials, there is no clear view of what is currently deployed, and manual cluster changes are invisible.
ArgoCD solves the deployment problem by running inside the cluster itself, watching a Git repository, and continuously reconciling the cluster toward the desired state in that repo. It is the most popular implementation of GitOps for Kubernetes, co-created by Intuit engineers and open-sourced in 2018. It is now a CNCF graduated project.
How ArgoCD Works
ArgoCD installs as a set of controllers and a UI in your cluster. You define an Application resource that tells ArgoCD:
- Where to find the configuration (a Git repo URL and path)
- What Kubernetes cluster and namespace to deploy into
- What tool renders the manifests (raw YAML, Helm, Kustomize, Jsonnet)
ArgoCD's reconciliation loop then runs continuously:
- Fetch the latest commit from the Git repository
- Render the manifests (run
helm templateif it is a Helm chart, apply Kustomize overlays, etc.) - Compare the rendered manifests to the live cluster state
- If they differ: report the diff, and optionally apply it automatically
Installing ArgoCD
# Create the argocd namespace and install
kubectl create namespace argocd
kubectl apply -n argocd -f \
https://raw.githubusercontent.com/argoproj/argo-cd/v2.11.0/manifests/install.yaml
# Wait for pods to be ready
kubectl wait --for=condition=available deployment \
-l app.kubernetes.io/name=argocd-server \
-n argocd --timeout=120s
# Get the initial admin password
argocd admin initial-password -n argocd
# Port-forward to access the UI locally
kubectl port-forward svc/argocd-server -n argocd 8080:443
Defining an Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: api-server
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io # Cascade-delete on app removal
spec:
project: default
source:
repoURL: https://github.com/mycompany/k8s-config
targetRevision: main
path: apps/production/api-server
helm:
valueFiles:
- values-production.yaml
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true # Remove resources deleted from Git
selfHeal: true # Revert manual changes
syncOptions:
- CreateNamespace=true
selfHeal: true is the key setting for a genuine GitOps workflow. It means if an operator manually edits a Deployment in the cluster -- say, bumping the replica count directly with kubectl scale -- ArgoCD will revert it on the next sync cycle to match Git. The cluster state becomes Git state.
The ArgoCD UI
ArgoCD's web interface is genuinely useful, not just decorative. The application graph visualizes every Kubernetes resource that belongs to an application -- Deployments, ReplicaSets, Pods, Services, Ingresses -- and shows their health status (Healthy, Degraded, Progressing, Missing). The diff view shows exactly what would change before you click sync.
For live incidents, being able to see at a glance that production is out of sync with main, and what the diff is, is faster than running kubectl get across a dozen resources.
Application Health and Sync Status
ArgoCD distinguishes between two orthogonal states:
Sync status: does the cluster match Git? (Synced, OutOfSync, Unknown) Health status: are the running resources actually healthy? (Healthy, Progressing, Degraded, Suspended, Missing)
A deployment can be Synced (cluster matches Git) but Degraded (pods are crash-looping). A deployment can be OutOfSync (new commit in Git) but Healthy (old version is running fine). This distinction is essential for operating deployments confidently.
ArgoCD in a Real Pipeline
The typical integration with CI looks like this:
- Developer merges a PR to the application code repository
- CI builds, tests, and pushes a new Docker image tagged
v1.5.0 - CI opens a PR against the GitOps config repo, updating
values-production.yamltoimage.tag: v1.5.0 - The config PR is reviewed and merged (or auto-merged for staging)
- ArgoCD detects the new commit, renders the Helm chart with the new image tag, and applies the diff to the cluster
No pipeline ever touches the cluster. The cluster credentials never leave the cluster. Every deployment is traceable to a specific Git commit. Rolling back is git revert on the config repo.
For a deeper look at the pull-model and GitOps principles, see what is GitOps. For chart packaging, see what is Helm. For the full Kubernetes picture, see the Kubernetes guide for beginners.
