Argo CD is a declarative GitOps continuous delivery tool for Kubernetes. It watches Git repositories and automatically synchronizes the desired application state defined in manifests (Helm, Kustomize, plain YAML) to target clusters. Key features: Application CRD for declarative app definitions, sync waves and hooks for ordered deployments, health checks, multi-cluster support, SSO/RBAC, ApplicationSets for managing apps at scale, and built-in notifications. It replaces imperative kubectl apply pipelines with a pull-based reconciliation model where Git is the single source of truth.
- Argo CD implements GitOps: Git is the single source of truth for your Kubernetes desired state.
- The pull-based reconciliation model automatically detects and corrects drift between Git and live cluster state.
- Application CRD declaratively defines source (Git repo), destination (cluster/namespace), and sync policy.
- Sync waves and hooks enable ordered deployments — run DB migrations before app rollout, verify after.
- ApplicationSets generate hundreds of Applications from templates using cluster, Git, or list generators.
- Sealed Secrets, External Secrets Operator, or SOPS keep secrets encrypted in Git while Argo CD syncs them safely.
- Multi-cluster management, SSO/RBAC, and a rich web UI make Argo CD suitable for enterprise-scale GitOps.
What Is Argo CD and GitOps?
Argo CD is a declarative, GitOps-based continuous delivery tool for Kubernetes, maintained as a CNCF graduated project. It continuously monitors Git repositories containing Kubernetes manifests and automatically synchronizes the desired application state to target clusters. When someone pushes a change to Git, Argo CD detects the difference between the live state and the desired state and reconciles them — either automatically or with manual approval.
GitOps is an operational framework that takes DevOps best practices — version control, collaboration, compliance, CI/CD — and applies them to infrastructure automation. The core principle is simple: the entire system state is described declaratively in Git, and an automated agent (Argo CD) ensures the live system matches that description at all times. Every change is a Git commit, every rollback is a Git revert, and every audit trail is a Git log.
Traditional CI/CD pipelines push changes to clusters using kubectl apply or helm upgrade from a CI runner. This push model has problems: CI credentials with cluster admin access are a security risk, pipeline failures can leave the cluster in a partially-applied state, and there is no continuous reconciliation — if someone manually changes a resource, nobody knows. Argo CD solves all of these by running inside the cluster, pulling desired state from Git, and continuously reconciling.
Installation: kubectl and Helm
Install with kubectl (Quick Start)
# Create namespace and install Argo CD
kubectl create namespace argocd
kubectl apply -n argocd -f \
https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# Wait for all pods to be ready
kubectl wait --for=condition=Ready pod --all -n argocd --timeout=300s
# Get the initial admin password
argocd admin initial-password -n argocd
# Port-forward the API server
kubectl port-forward svc/argocd-server -n argocd 8080:443
# Login via CLI
argocd login localhost:8080 --username admin --password <initial-password>
# Change the admin password immediately
argocd account update-passwordInstall with Helm (Production)
# Add the Argo Helm repository
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
# Install with custom values
helm install argocd argo/argo-cd \
--namespace argocd \
--create-namespace \
--set server.service.type=LoadBalancer \
--set server.extraArgs[0]=--insecure \
--set configs.params."server\.insecure"=true \
--set ha.enabled=true \
--set controller.replicas=2 \
--set redis-ha.enabled=true \
-f values-production.yaml
# values-production.yaml example:
# server:
# replicas: 2
# ingress:
# enabled: true
# hosts:
# - argocd.example.com
# tls:
# - secretName: argocd-tls
# hosts:
# - argocd.example.comArchitecture: Core Components
Argo CD consists of three main components that work together to implement the GitOps reconciliation loop. Understanding this architecture is essential for troubleshooting, scaling, and securing your Argo CD installation.
Argo CD Architecture
Git Repository Argo CD (in-cluster) Target Cluster(s)
┌──────────┐ ┌─────────────────────────────┐ ┌──────────────────┐
│ manifests│ │ ┌────────────────────────┐ │ │ │
│ helm/ │◄────┤ │ Repo Server │ │ │ Namespaces │
│ kustomize│ │ │ (clone, render, cache) │ │ │ ┌────────────┐ │
│ plain/ │ │ └───────────┬────────────┘ │ │ │ Deployments│ │
└──────────┘ │ │ │ │ │ Services │ │
│ ┌───────────▼────────────┐ │ │ │ ConfigMaps │ │
│ │ Application Controller │ │────►│ │ Secrets │ │
│ │ (diff, sync, health) │ │ │ │ Ingress │ │
│ └───────────┬────────────┘ │ │ └────────────┘ │
│ │ │ └──────────────────┘
Web UI / CLI │ ┌───────────▼────────────┐ │
┌──────────┐ │ │ API Server │ │
│ Browser │◄────┤ │ (gRPC/REST, auth, │ │
│ argocd │ │ │ RBAC, web UI) │ │
│ CLI │ │ └────────────────────────┘ │
└──────────┘ └─────────────────────────────┘API Server
The API Server is the central component that exposes the gRPC and REST API consumed by the web UI, CLI, and CI/CD systems. It handles authentication (local accounts, SSO via OIDC/SAML/LDAP), authorization (RBAC policies), and serves the built-in web dashboard. It manages Application and AppProject resources and triggers sync operations.
Repo Server
The Repo Server clones Git repositories, caches them locally, and renders Kubernetes manifests. It supports plain YAML, Helm charts (helm template), Kustomize overlays (kustomize build), Jsonnet, and custom config management plugins. The Repo Server is stateless and horizontally scalable — for large installations with hundreds of applications, run multiple replicas.
Application Controller
The Application Controller is the brain of Argo CD. It continuously monitors running applications, compares the live state against the desired state from the Repo Server, detects drift (OutOfSync), and optionally auto-syncs. It also evaluates resource health using built-in and custom health checks. The controller runs the reconciliation loop on a configurable interval (default: 3 minutes for full reconciliation, with webhook-triggered instant checks).
The Application CRD
The Application custom resource is the fundamental building block in Argo CD. It defines what to deploy (source), where to deploy (destination), and how to sync (sync policy). Applications can be created via the UI, CLI, or declaratively as YAML — the latter is the GitOps-recommended approach, often called the "app of apps" pattern.
# application.yaml - Argo CD Application CRD
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-web-app
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/org/k8s-manifests.git
targetRevision: main
path: apps/web-app/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
allowEmpty: false
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground
- PruneLast=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3mAppProjects: Multi-Tenancy and Access Control
AppProjects provide logical grouping and access control for Applications. They restrict which Git repositories an Application can use as source, which clusters and namespaces it can deploy to, and which Kubernetes resource kinds are allowed or denied. Projects are essential for multi-tenancy — different teams get different projects with scoped permissions.
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: team-backend
namespace: argocd
spec:
description: Backend team project
sourceRepos:
- https://github.com/org/backend-manifests.git
- https://github.com/org/shared-charts.git
destinations:
- server: https://kubernetes.default.svc
namespace: backend-*
- server: https://staging-cluster.example.com
namespace: backend-*
clusterResourceWhitelist:
- group: ""
kind: Namespace
namespaceResourceBlacklist:
- group: ""
kind: ResourceQuota
- group: ""
kind: LimitRange
roles:
- name: backend-dev
description: Backend developer role
policies:
- p, proj:team-backend:backend-dev, applications, get, team-backend/*, allow
- p, proj:team-backend:backend-dev, applications, sync, team-backend/*, allow
groups:
- backend-developersSync Policies: Automated vs Manual
Sync policies determine how Argo CD reconciles the live state with the desired state. Manual sync requires explicit user action (via UI or CLI) to apply changes. Automated sync triggers synchronization whenever the desired state in Git diverges from the live state. Each mode has distinct use cases depending on your deployment risk tolerance.
| Feature | Manual Sync | Automated Sync |
|---|---|---|
| Trigger | User clicks Sync or runs argocd app sync | Automatic on Git change detection |
| Prune | Optional per sync | Configurable: prune=true removes orphans |
| Self-heal | Not available | selfHeal=true reverts manual cluster changes |
| Best for | Production with approval gates | Dev/staging, trusted production repos |
| Rollback | Git revert + manual sync | Git revert triggers auto-sync |
# Manual sync via CLI
argocd app sync my-web-app --prune --force
# Automated sync in Application spec
# syncPolicy:
# automated:
# prune: true # Delete resources removed from Git
# selfHeal: true # Revert manual cluster changes
# allowEmpty: false # Prevent sync if Git returns empty manifestsSync Waves and Hooks
Sync waves control the order in which Argo CD applies resources during a sync. Resources are assigned wave numbers via annotations: lower waves are applied first, and Argo CD waits for all resources in a wave to be healthy before proceeding to the next. Hooks are special resources (usually Jobs) that run at specific lifecycle phases.
# Wave -1: Namespace and RBAC (created first)
apiVersion: v1
kind: Namespace
metadata:
name: my-app
annotations:
argocd.argoproj.io/sync-wave: "-1"
---
# Wave 0: ConfigMaps and Secrets
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
annotations:
argocd.argoproj.io/sync-wave: "0"
data:
DATABASE_HOST: postgres.db.svc
---
# Wave 1: Database migration (PreSync hook)
apiVersion: batch/v1
kind: Job
metadata:
name: db-migrate
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: migrate
image: my-app:latest
command: ["./migrate", "--up"]
restartPolicy: Never
---
# Wave 2: Application Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
annotations:
argocd.argoproj.io/sync-wave: "2"
---
# PostSync hook: Smoke test
apiVersion: batch/v1
kind: Job
metadata:
name: smoke-test
annotations:
argocd.argoproj.io/hook: PostSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: test
image: curlimages/curl:latest
command: ["curl", "-f", "http://my-app.my-app.svc/healthz"]
restartPolicy: NeverHook Types Reference
| Hook | When It Runs | Common Use Case |
|---|---|---|
| PreSync | Before sync starts | Database migrations, schema changes |
| Sync | During sync (with wave ordering) | Complex resource creation order |
| PostSync | After all resources are healthy | Smoke tests, notifications, cache warming |
| SyncFail | When sync operation fails | Cleanup, alerting, rollback triggers |
| Skip | Never synced by Argo CD | Resources managed externally |
Health Checks
Argo CD evaluates the health of every resource it manages. Built-in health checks cover Deployments (are all replicas available?), StatefulSets, DaemonSets, Ingress, PersistentVolumeClaims, and more. For custom resources (CRDs), you can define custom health check scripts in Lua that Argo CD evaluates to determine Healthy, Progressing, Degraded, Suspended, or Missing status.
# Custom health check for a CronJob (in argocd-cm ConfigMap)
# data:
# resource.customizations.health.batch_CronJob: |
# hs = {}
# if obj.status ~= nil then
# if obj.status.lastScheduleTime ~= nil then
# hs.status = "Healthy"
# hs.message = "CronJob is scheduled"
# else
# hs.status = "Progressing"
# hs.message = "Waiting for first schedule"
# end
# else
# hs.status = "Progressing"
# hs.message = "No status yet"
# end
# return hsMulti-Cluster Management
Argo CD can manage applications across multiple Kubernetes clusters from a single control plane. This is critical for organizations with separate clusters for development, staging, production, or regional deployments. External clusters are registered and their credentials are stored securely as Kubernetes Secrets in the Argo CD namespace.
# Register an external cluster
argocd cluster add staging-context --name staging-cluster
argocd cluster add prod-us-east --name prod-us-east
argocd cluster add prod-eu-west --name prod-eu-west
# List registered clusters
argocd cluster list
# Deploy to a specific cluster
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-app-prod-us
namespace: argocd
spec:
project: production
source:
repoURL: https://github.com/org/manifests.git
path: overlays/prod-us-east
targetRevision: main
destination:
server: https://prod-us-east.example.com
namespace: web-appSSO and RBAC
Argo CD supports Single Sign-On via OIDC (Okta, Auth0, Keycloak, Google), SAML 2.0, LDAP, and GitHub/GitLab OAuth. RBAC policies use a Casbin model to control who can view, sync, delete, or override applications at the project or global level. This enables fine-grained access control for multi-team environments.
# argocd-cm ConfigMap - OIDC SSO configuration
data:
url: https://argocd.example.com
oidc.config: |
name: Okta
issuer: https://org.okta.com/oauth2/default
clientID: argocd-client-id
clientSecret: $oidc.okta.clientSecret
requestedScopes:
- openid
- profile
- email
- groups
# argocd-rbac-cm ConfigMap - RBAC policies
data:
policy.default: role:readonly
policy.csv: |
# Admins can do everything
p, role:admin, applications, *, */*, allow
p, role:admin, clusters, *, *, allow
p, role:admin, repositories, *, *, allow
p, role:admin, projects, *, *, allow
# Developers can view and sync their project apps
p, role:developer, applications, get, team-backend/*, allow
p, role:developer, applications, sync, team-backend/*, allow
p, role:developer, applications, action/*, team-backend/*, allow
# Map SSO groups to roles
g, platform-team, role:admin
g, backend-devs, role:developerSecrets Management
Storing plain-text Kubernetes Secrets in Git violates security best practices. Argo CD integrates with multiple secret management solutions that keep encrypted or referenced secrets in Git while the actual values are resolved at sync time or by in-cluster controllers.
Sealed Secrets (Bitnami)
# Install Sealed Secrets controller
helm repo add sealed-secrets https://bitnami-labs.github.io/sealed-secrets
helm install sealed-secrets sealed-secrets/sealed-secrets -n kube-system
# Encrypt a secret (safe to commit to Git)
kubectl create secret generic db-creds \
--from-literal=password=supersecret \
--dry-run=client -o yaml | \
kubeseal --controller-name=sealed-secrets \
--controller-namespace=kube-system \
--format yaml > sealed-db-creds.yaml
# The SealedSecret can be safely stored in Git
# Argo CD syncs it; the controller decrypts it in-clusterExternal Secrets Operator
# ExternalSecret syncs from AWS Secrets Manager
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: db-credentials
creationPolicy: Owner
data:
- secretKey: username
remoteRef:
key: prod/db-credentials
property: username
- secretKey: password
remoteRef:
key: prod/db-credentials
property: passwordApplicationSets: Managing Apps at Scale
The ApplicationSet controller generates Argo CD Application resources from templates using generators. Instead of manually creating hundreds of Application CRDs, you define a template and a generator that produces the parameter sets. This is essential for managing monorepos, multi-cluster deployments, and dynamic environments.
Cluster Generator (Multi-Cluster)
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: web-app-all-clusters
namespace: argocd
spec:
generators:
- clusters:
selector:
matchLabels:
env: production
template:
metadata:
name: web-app-{{name}}
spec:
project: production
source:
repoURL: https://github.com/org/manifests.git
targetRevision: main
path: overlays/{{metadata.labels.region}}
destination:
server: "{{server}}"
namespace: web-app
syncPolicy:
automated:
prune: true
selfHeal: trueGit Directory Generator (Monorepo)
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: monorepo-services
namespace: argocd
spec:
generators:
- git:
repoURL: https://github.com/org/monorepo.git
revision: main
directories:
- path: services/*
template:
metadata:
name: "{{path.basename}}"
spec:
project: default
source:
repoURL: https://github.com/org/monorepo.git
targetRevision: main
path: "{{path}}"
destination:
server: https://kubernetes.default.svc
namespace: "{{path.basename}}"Pull Request Generator (Preview Environments)
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: pr-previews
namespace: argocd
spec:
generators:
- pullRequest:
github:
owner: org
repo: web-app
tokenRef:
secretName: github-token
key: token
requeueAfterSeconds: 60
template:
metadata:
name: preview-{{branch_slug}}
spec:
project: previews
source:
repoURL: https://github.com/org/web-app.git
targetRevision: "{{head_sha}}"
path: k8s/preview
destination:
server: https://kubernetes.default.svc
namespace: preview-{{number}}Argo CD Notifications
Argo CD Notifications (built-in since v2.6) sends alerts to Slack, Teams, email, webhooks, GitHub, and more when application events occur (sync succeeded, sync failed, health degraded). Notifications are configured via the argocd-notifications-cm ConfigMap with triggers and templates.
# argocd-notifications-cm ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
service.slack: |
token: $slack-token
trigger.on-sync-succeeded: |
- when: app.status.operationState.phase in ["Succeeded"]
send: [app-sync-succeeded]
trigger.on-sync-failed: |
- when: app.status.operationState.phase in ["Error", "Failed"]
send: [app-sync-failed]
trigger.on-health-degraded: |
- when: app.status.health.status == "Degraded"
send: [app-health-degraded]
template.app-sync-succeeded: |
message: |
Application {{.app.metadata.name}} sync succeeded.
Revision: {{.app.status.sync.revision}}
template.app-sync-failed: |
message: |
Application {{.app.metadata.name}} sync FAILED.
Error: {{.app.status.operationState.message}}
# Subscribe an app to notifications (annotation)
# metadata:
# annotations:
# notifications.argoproj.io/subscribe.on-sync-succeeded.slack: deploysArgo CD with Helm and Kustomize
Helm Integration
Argo CD renders Helm charts using helm template (not helm install), which means it treats Helm as a manifest generator rather than a release manager. You can specify Helm values inline, from files in the repo, or from external value files. This approach gives Argo CD full control over resource lifecycle while leveraging the Helm chart ecosystem.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: nginx-ingress
namespace: argocd
spec:
project: infrastructure
source:
repoURL: https://kubernetes.github.io/ingress-nginx
chart: ingress-nginx
targetRevision: 4.9.1
helm:
releaseName: nginx-ingress
valuesObject:
controller:
replicaCount: 3
service:
type: LoadBalancer
metrics:
enabled: true
destination:
server: https://kubernetes.default.svc
namespace: ingress-nginxKustomize Integration
# Application using Kustomize overlays
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: api-prod
namespace: argocd
spec:
source:
repoURL: https://github.com/org/manifests.git
path: api/overlays/production
targetRevision: main
kustomize:
namePrefix: prod-
commonLabels:
env: production
images:
- name=api-image
newName=registry.example.com/api
newTag=v2.5.0
destination:
server: https://kubernetes.default.svc
namespace: api-production
# Corresponding kustomization.yaml in the repo
# apiVersion: kustomize.config.k8s.io/v1beta1
# kind: Kustomization
# resources:
# - ../../base
# patches:
# - path: replica-patch.yaml
# - path: resource-limits-patch.yamlCI/CD Pipeline Integration
In a GitOps workflow, CI and CD are cleanly separated. CI (GitHub Actions, GitLab CI, Jenkins) builds, tests, and pushes container images. CD is handled entirely by Argo CD watching the Git repo. The CI pipeline updates the image tag in the Git manifest repository, and Argo CD detects the change and syncs. This separation means CI never needs cluster credentials.
# GitHub Actions CI pipeline that triggers Argo CD
name: Build and Update Manifests
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build and push image
run: |
docker build -t registry.example.com/app:$GITHUB_SHA .
docker push registry.example.com/app:$GITHUB_SHA
- name: Update manifest repo
run: |
git clone https://github.com/org/k8s-manifests.git
cd k8s-manifests
# Update image tag in kustomization.yaml
cd apps/web-app/overlays/production
kustomize edit set image \
app=registry.example.com/app:$GITHUB_SHA
git add .
git commit -m "Update web-app to $GITHUB_SHA"
git push
# Argo CD detects change and syncs automaticallyImage Updater (Automatic Image Tag Updates)
Argo CD Image Updater is a companion tool that watches container registries for new image tags and automatically updates the Application source. This eliminates the need for the CI pipeline to commit image tag changes to Git — the Image Updater handles it.
# Application annotation for Image Updater
metadata:
annotations:
argocd-image-updater.argoproj.io/image-list: |
app=registry.example.com/app
argocd-image-updater.argoproj.io/app.update-strategy: semver
argocd-image-updater.argoproj.io/app.allow-tags: regexp:^v[0-9]+\.[0-9]+\.[0-9]+$
argocd-image-updater.argoproj.io/write-back-method: gitDisaster Recovery
Since Argo CD follows the GitOps principle, disaster recovery is straightforward: your Git repositories contain the desired state of all applications. If the Argo CD installation is lost, reinstall it, reconnect the repositories, and all applications will be re-synced automatically. However, you should also back up Argo CD-specific configuration.
# Export all Argo CD resources for backup
argocd admin export -n argocd > argocd-backup.yaml
# Back up specific resource types
kubectl get applications -n argocd -o yaml > apps-backup.yaml
kubectl get appprojects -n argocd -o yaml > projects-backup.yaml
kubectl get secrets -n argocd -l argocd.argoproj.io/secret-type=repository -o yaml > repos-backup.yaml
kubectl get secrets -n argocd -l argocd.argoproj.io/secret-type=cluster -o yaml > clusters-backup.yaml
# Restore from backup
argocd admin import -n argocd < argocd-backup.yaml
# Best practice: Store Argo CD config as code
# Keep Application, AppProject, and config YAMLs
# in a dedicated Git repo managed by a bootstrap appBest Practices
- Separate app repo from config repo — Keep application source code and Kubernetes manifests in separate Git repositories. CI builds images from the app repo; CD reads manifests from the config repo. This decouples application releases from infrastructure changes.
- Use the App of Apps pattern — Define a root Application that points to a directory of Application manifests. When you add a new app, commit its Application YAML to this directory, and the root app auto-syncs it.
- Enable automated sync with selfHeal for dev/staging — In non-production environments, automated sync with self-heal ensures the cluster always matches Git, catching manual changes immediately.
- Use manual sync with approval gates for production — In production, require explicit sync approval. Combine with CI checks (passing tests, security scans) before the manifest repo is updated.
- Pin targetRevision to tags or SHA in production — Avoid tracking HEAD of main in production. Pin to a specific Git tag or commit SHA for predictable, auditable deployments.
- Leverage sync waves for dependency ordering — Ensure CRDs are created before custom resources, databases before apps, and config before deployments.
- Set resource limits on Argo CD components — The Application Controller and Repo Server can be memory-intensive with hundreds of apps. Set appropriate resource requests and limits, and scale replicas horizontally.
- Use Projects to enforce least-privilege — Restrict each teams project to specific repos, clusters, namespaces, and resource kinds. Deny cluster-scoped resources unless explicitly needed.
- Integrate with Prometheus and Grafana — Argo CD exports Prometheus metrics. Monitor sync duration, sync failures, app health status, and API server request latency.
- Adopt Progressive Delivery — Combine Argo CD with Argo Rollouts for canary deployments, blue-green releases, and traffic shifting experiments before full promotion.
Argo CD vs Flux: Choosing a GitOps Tool
Argo CD and Flux are both CNCF graduated GitOps projects for Kubernetes. They share the same core principle (Git as source of truth, pull-based reconciliation) but differ significantly in architecture, user experience, and ecosystem integration.
| Dimension | Argo CD | Flux |
|---|---|---|
| Architecture | Monolithic: API Server + Controller + Repo Server | Microservices: source-controller, kustomize-controller, helm-controller, notification-controller |
| Web UI | Built-in, feature-rich dashboard | No built-in UI (Weave GitOps is a third-party option) |
| CRD Model | Application, AppProject, ApplicationSet | GitRepository, Kustomization, HelmRelease, HelmRepository |
| Multi-Tenancy | Projects + RBAC + SSO | Namespace-scoped controllers + service account impersonation |
| Helm Support | helm template (manifest generation) | Native helm install/upgrade via HelmRelease |
| Progressive Delivery | Argo Rollouts (canary, blue-green) | Flagger (canary, A/B, blue-green) |
| Image Automation | Argo CD Image Updater (add-on) | Built-in image-reflector + image-automation controllers |
| Best For | Teams wanting UI, SSO/RBAC, multi-cluster visibility | Teams preferring minimal footprint, CLI-only, Kubernetes-native design |
Frequently Asked Questions
What is Argo CD and how does it differ from traditional CI/CD?
Argo CD is a declarative GitOps continuous delivery tool for Kubernetes. Unlike traditional push-based CI/CD where a pipeline runs kubectl apply or helm upgrade, Argo CD uses a pull-based model. It runs inside the cluster, continuously watches Git repositories, compares the desired state in Git against the live cluster state, and reconciles any differences. This means Git becomes the single source of truth, all changes are auditable through Git history, drift is automatically detected, and CI pipelines never need direct cluster access.
How do I install Argo CD?
Install Argo CD by creating the argocd namespace and applying the official install manifest with kubectl. For production, use the Argo Helm chart with HA (high availability) configuration — multiple API Server replicas, Redis HA, and the Application Controller sharding feature for large-scale deployments. After installation, retrieve the initial admin password from the argocd-initial-admin-secret, port-forward or expose the server via Ingress, and log in.
What are sync waves and hooks?
Sync waves control resource application order during a sync. Annotate resources with argocd.argoproj.io/sync-wave and an integer value — lower values are applied first. Hooks (PreSync, Sync, PostSync, SyncFail) are Jobs that run at specific lifecycle phases. For example, use a PreSync hook for database migrations before the app deployment, and a PostSync hook for smoke tests after deployment completes.
How does Argo CD handle secrets?
Never commit plain-text secrets to Git. Use Sealed Secrets (encrypts secrets client-side; the controller decrypts in-cluster), External Secrets Operator (syncs secrets from AWS Secrets Manager, Vault, Azure Key Vault), or SOPS with age/GPG encryption. Argo CD syncs these encrypted or reference resources like any other manifest, and the respective controller resolves the actual secret values within the cluster.
What is the App of Apps pattern?
The App of Apps pattern is a bootstrapping approach where a single root Application points to a Git directory containing other Application manifests. When Argo CD syncs the root app, it creates all child applications, which in turn sync their own resources. This enables managing your entire platform — infrastructure components, shared services, application deployments — from a single entry point. Adding a new application is as simple as committing a new Application YAML file.
How does multi-cluster deployment work?
Register external clusters using argocd cluster add, which creates a ServiceAccount on the target cluster and stores credentials in the Argo CD namespace. Applications can then target any registered cluster by specifying its server URL in the destination field. Combined with ApplicationSets and the cluster generator, you can deploy the same application to all clusters matching a label selector from a single Argo CD instance.
When should I use ApplicationSets?
Use ApplicationSets when you need to manage applications at scale: deploying across multiple clusters (cluster generator), managing microservices in a monorepo (Git directory generator), creating preview environments from pull requests (PR generator), or generating applications from a dynamic list of environments (list or matrix generator). ApplicationSets eliminate the need to manually create and maintain hundreds of Application CRDs.
How does Argo CD compare to Flux?
Both are CNCF graduated GitOps tools. Argo CD offers a rich web UI, built-in SSO/RBAC, multi-cluster management, and ApplicationSets — ideal for teams needing visibility and multi-tenancy. Flux uses a microservices architecture with separate controllers for sources, Kustomize, and Helm, and has built-in image automation. Flux suits teams preferring a minimal, CLI-driven, Kubernetes-native approach. For most teams starting with GitOps, Argo CD provides a smoother onboarding experience due to its UI and comprehensive feature set.
Conclusion
Argo CD brings the principles of GitOps to Kubernetes continuous delivery, replacing fragile push-based scripts with a robust, auditable, self-healing reconciliation loop. By making Git the single source of truth, every deployment is versioned, every change is reviewable, and every rollback is a git revert. The combination of Application CRDs, sync policies, waves, hooks, ApplicationSets, and multi-cluster support makes Argo CD suitable for everything from a single-app startup to an enterprise platform managing thousands of microservices across global clusters. Start simple — one Application, one cluster, manual sync — and progressively adopt automation, ApplicationSets, and progressive delivery with Argo Rollouts as your needs grow.