ArgoCD — GitOps Continuous Delivery for Kubernetes
Advertisement
Introduction
Why This Matters
ArgoCD is the de-facto GitOps tool for Kubernetes. Rather than pushing deployments from CI pipelines, ArgoCD continuously reconciles your cluster state against Git — making Git the single source of truth for what runs in production. Any drift is detected and corrected automatically, audit logs are implicit (it is just Git history), and rollback is a git revert away.
Installation
# Create namespace and install
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 pods --all -n argocd --timeout=120s
# Get initial admin password
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d && echo
# Port-forward the UI
kubectl port-forward -n argocd svc/argocd-server 8080:443
# Install CLI (macOS)
brew install argocd
# Login via CLI
argocd login localhost:8080 --username admin --insecureDeploying an Application
# application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/my-org/my-app
path: k8s/overlays/production
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true # delete removed resources
selfHeal: true # fix manual cluster changes
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=foreground# Apply the application manifest
kubectl apply -f application.yaml
# Or create via CLI
argocd app create my-app \
--repo https://github.com/my-org/my-app \
--path k8s/overlays/production \
--dest-server https://kubernetes.default.svc \
--dest-namespace production \
--sync-policy automated \
--auto-prune \
--self-healSync Strategies and Policies
syncPolicy:
# Automated sync — ArgoCD reconciles on every Git push
automated:
prune: true # remove K8s resources not in Git
selfHeal: true # revert manual kubectl changes
allowEmpty: false # do not sync if source produces zero resources
# Retry failed syncs with backoff
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
- RespectIgnoreDifferences=trueProjects and RBAC
# AppProject scopes which repos and clusters an app can use
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: team-backend
namespace: argocd
spec:
description: Backend team project
sourceRepos:
- 'https://github.com/my-org/*'
destinations:
- namespace: 'backend-*'
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ''
kind: Namespace
namespaceResourceBlacklist:
- group: ''
kind: ResourceQuota
roles:
- name: developer
description: Read-only access
policies:
- p, proj:team-backend:developer, applications, get, team-backend/*, allow
- p, proj:team-backend:developer, applications, sync, team-backend/*, allowMulti-Cluster Management
# Register external cluster
argocd cluster add my-eks-cluster --name production-eks
# List registered clusters
argocd cluster list
# Deploy to external cluster
argocd app create remote-app \
--dest-server https://eks-cluster-api-server.amazonaws.com \
--dest-namespace productionRollback
# View app history
argocd app history my-app
# Rollback to previous revision
argocd app rollback my-app --revision 42
# Or revert in Git (preferred GitOps approach)
git revert HEAD
git push origin main
# ArgoCD picks up the change automaticallyCommon Mistakes
- Enabling
prune: truewithout testing — it will delete resources not tracked in Git - Not setting finalizers on Application resources, causing orphaned cluster resources on deletion
- Using automated sync for stateful applications without carefully managing data migrations
- Storing sensitive values (passwords, API keys) directly in Git manifests — use Sealed Secrets or External Secrets Operator
- Not configuring AppProjects — leaving all teams deploying to all namespaces
Best Practices
- Separate your application code repo from your GitOps config repo (app-of-apps pattern)
- Enable
selfHealin production to ensure cluster state never drifts from Git - Use Kustomize overlays or Helm chart values per environment within the same repo
- Configure webhook notifications so ArgoCD syncs immediately on Git push rather than polling
- Use ArgoCD Image Updater to automate image tag updates without manual Git commits
- Protect the
argocdnamespace with NetworkPolicies and strict RBAC
Key Takeaways
- ArgoCD implements GitOps by continuously syncing Kubernetes cluster state to match a Git repository
prune: trueremoves cluster resources that have been deleted from Git — powerful but requires careselfHeal: trueautomatically reverts any manualkubectlchanges that differ from Git state- AppProjects provide RBAC boundaries controlling which teams can deploy to which namespaces and clusters
- Rollbacks in GitOps are Git reverts — ArgoCD detects the change and reconciles the cluster
- The App-of-Apps pattern uses one ArgoCD Application to manage many child Applications declaratively
- ArgoCD supports Helm, Kustomize, Jsonnet, and plain YAML manifests as source formats
- Multi-cluster management is native — register external clusters and deploy across environments from one control plane
Advertisement
Related reading
DevOps Engineer Roadmap 2026 — From Zero to $150K+ in 18 Months9 min readArgoCD in Production — GitOps Deployment Pipelines That Actually Work8 min readGitOps With ArgoCD — Git as the Single Source of Truth for Kubernetes Deployments10 min readAI Tools for DevOps — Generate Dockerfiles, CI/CD Pipelines, and Kubernetes Manifests5 min readGitHub Actions Complete Guide 2026 — CI/CD Pipelines, Workflows, and Automation5 min readKubernetes Guide 2026 — Deploy, Scale, and Manage Containers in Production5 min read