Definition
- ArgoCD – A Kubernetes-native, declarative GitOps continuous-delivery tool that runs inside the cluster and watches a Git repository.
- Application resource – Each deployable unit is an
ApplicationCR pointing at a Git repo, path, revision, and destination cluster/namespace. - Reconciliation – ArgoCD periodically renders manifests (YAML, Helm, Kustomize), compares to live state, and reports Synced/OutOfSync, Healthy/Degraded.
- Pull-based – The controller inside the cluster reaches outward to read Git; credentials stay inside the cluster.
- Push-based – An external CI server (Jenkins) holds kubeconfig credentials and runs
kubectl applyfrom outside; credentials live outside the cluster. - CI/CD separation – CI builds and tests; ArgoCD owns deployment, cleanly separating concerns.
Think of ArgoCD as an inspector who lives inside the National Bank of India's data center. He keeps a copy of the official rulebook (the Git repo) and constantly walks the floor making the setup match the rulebook, reporting a green light when everything matches and red when it does not. The traditional push model is the opposite: an outside contractor (Jenkins) keeps the keys to the data center and drives over to make changes whenever told. The inside inspector is safer because no outsider needs the keys.
Understanding the Concepts
What is ArgoCD?
ArgoCD is a Kubernetes-native, declarative GitOps continuous-delivery tool. It models each deployable unit as an Application custom resource that points at a Git repository, a path and revision within it, and a destination cluster and namespace. The ArgoCD controller polls or receives webhooks from the repo, renders the manifests, and compares the rendered desired state to the live cluster state.
# ArgoCD Application for the banking-api
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: banking-api
namespace: argocd
spec:
project: default
source:
repoURL: https://git.nationalbank.in/gitops-repo.git
path: banking-api # directory in the repo
targetRevision: main # branch or tag
destination:
server: https://kubernetes.default.svc
namespace: banking
syncPolicy:
automated:
prune: true # delete resources removed from Git
selfHeal: true # revert manual drift
syncOptions:
- CreateNamespace=true
How does ArgoCD report status?
ArgoCD reports each Application as Synced or OutOfSync (does the cluster match Git?) and as Healthy or Degraded (are the resources actually working?). Its web UI and CLI show a live diff of exactly what differs.
# Check sync and health status
argocd app get banking-api
# Output:
# Name: banking-api
# Project: default
# Server: https://kubernetes.default.svc
# Namespace: banking
# Sync Status: Synced
# Health Status: Healthy
# Last Sync: 2024-01-15T10:30:00Z (commit abc1234)
# Message: successfully synced
# Show the diff when out of sync
argocd app diff banking-api
# Diff output:
# === Deployment banking-api ===
# - replicas: 3
# + replicas: 1 <- someone manually scaled down
# ArgoCD will self-heal this back to 3.
What is the difference between pull-based and push-based? (comparison table)
| Aspect | Push-Based (Jenkins) | Pull-Based (ArgoCD) |
|---|---|---|
| Where it runs | Outside the cluster | Inside the cluster |
| Credentials | External system holds kubeconfig | Credentials stay inside the cluster |
| Cluster exposure | API must be reachable from CI network | Cluster reaches out to Git (no inbound) |
| Deployment model | One-shot imperative (kubectl apply) | Continuous reconciliation loop |
| Drift detection | None after the push | Continuous, with self-heal |
| Compromised CI impact | Attacker has cluster credentials | Attacker cannot reach the cluster |
| Multi-cluster | CI needs credentials for each cluster | One ArgoCD can pull for many clusters |
# Push-based: Jenkins pushes to cluster
# Jenkinsfile:
stage('Deploy') {
steps {
sh 'kubectl apply -f deployment.yaml' # Jenkins has kubeconfig
sh 'kubectl rollout status deployment/banking-api'
}
}
# Problems: Jenkins holds cluster credentials, no ongoing enforcement.
# Pull-based: ArgoCD pulls from Git
# ArgoCD Application (shown above)
# CI only builds and updates Git:
# 1. Build image
# 2. Push to registry
# 3. Update image tag in gitops-repo
# ArgoCD handles the actual deployment.
# No external system holds cluster credentials.
How does ArgoCD handle sync policies?
With automated sync, ArgoCD applies changes automatically when it detects a new commit. With prune: true, it deletes resources that were removed from Git. With selfHeal: true, it reverts manual changes.
syncPolicy:
automated:
prune: true # Resources deleted from Git are deleted from cluster
selfHeal: true # Manual edits on cluster are reverted to Git state
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
# Manual sync (when automated is not enabled)
argocd app sync banking-api
# Force sync (override all differences)
argocd app sync banking-api --force
# Rollback to a previous sync
argocd app rollback banking-api 3 # revision number
How does ArgoCD fit with CI?
CI (Jenkins, GitHub Actions, GitLab CI) still builds the image, runs tests, and updates the image tag in the Git repo. ArgoCD then handles deployment by syncing that commit. Jenkins is not eliminated; it is repositioned to do build and test.
CI/CD Pipeline with ArgoCD
===========================
Developer pushes code
│
▼
┌──────────────────┐
│ CI (GitHub │ 1. Build image
│ Actions) │ 2. Run tests
│ │ 3. Push image to registry
│ │ 4. Update image tag in gitops-repo
└────────┬─────────┘
│ (commit to gitops-repo)
▼
┌──────────────────┐
│ ArgoCD │ 5. Detect new commit
│ (in-cluster) │ 6. Render manifests
│ │ 7. Compare to live state
│ │ 8. Apply changes (deploy)
└──────────────────┘
# GitHub Actions CI workflow (builds and updates Git)
name: CI
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.nationalbank.in/banking-api:${{ github.sha }} .
docker push registry.nationalbank.in/banking-api:${{ github.sha }}
- name: Update gitops repo
run: |
git clone https://git.nationalbank.in/gitops-repo.git
cd gitops-repo/banking-api
sed -i "s|image:.*|image: registry.nationalbank.in/banking-api:${{ github.sha }}|" deployment.yaml
git commit -am "Bump banking-api to ${{ github.sha }}"
git push
What are common mistakes with ArgoCD?
# WRONG: Running kubectl apply alongside ArgoCD
kubectl apply -f deployment.yaml -n banking
# ArgoCD will detect this as drift and revert it (with selfHeal).
# Or worse, without selfHeal, the cluster diverges from Git.
# CORRECT: All changes go through the Git repo.
# ArgoCD is the only entity that applies manifests.
What about multi-cluster management?
A single ArgoCD instance can manage many clusters by registering each as a destination. Because ArgoCD pulls, you do not need to expose each cluster's API to an external CI system.
# Register a second cluster with ArgoCD
argocd cluster add banking-dr-cluster --name dr-cluster
# Deploy the same Application to both clusters
# Application 1: banking-api -> production cluster
# Application 2: banking-api-dr -> dr-cluster
# Both point at the same Git repo path for identical state.
What should a senior engineer know?
ArgoCD supports the app-of-apps pattern for managing many applications declaratively, sync waves and hooks for ordering deployments, and progressive delivery through Argo Rollouts for canary and blue-green strategies. It integrates with external secret management tools like Sealed Secrets and External Secrets Operator.
# App-of-apps: one Application that manages all others
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: banking-platform
spec:
source:
repoURL: https://git.nationalbank.in/gitops-repo.git
path: apps # contains Application YAML for each service
destination:
server: https://kubernetes.default.svc
namespace: argocd
Visual Overview
Pull-Based (ArgoCD) vs Push-Based (Jenkins)
============================================
Push-Based (Jenkins)
─────────────────────
┌──────────┐ kubectl apply ┌──────────────┐
│ Jenkins │ ────────────────────> │ Kubernetes │
│ (outside)│ (kubeconfig held │ Cluster │
│ │ by external CI) │ │
└──────────┘ └──────────────┘
Risk: credentials outside cluster, no drift detection
Pull-Based (ArgoCD)
─────────────────────
┌──────────┐ ┌──────────────┐
│ Git Repo │ <──── read ──────── │ Kubernetes │
│ (source │ │ Cluster │
│ of truth│ │ ┌────────┐ │
└──────────┘ │ │ ArgoCD │ │
│ │(inside)│ │
│ └────────┘ │
└──────────────┘
Secure: credentials stay inside, continuous reconciliation
Key Takeaway
ArgoCD is a Kubernetes-native GitOps controller that runs inside the cluster, watches a Git repository containing manifests, Helm charts, or Kustomize overlays, and continuously synchronizes the cluster to match. Each deployable unit is an Application custom resource pointing at a repo, path, revision, and destination namespace. ArgoCD renders the manifests, compares them to the live cluster, and reports each application as Synced or OutOfSync and Healthy or Degraded.
The core difference from traditional CI/CD is pull versus push. In the push model, Jenkins holds kubeconfig credentials and runs kubectl apply from outside the cluster, which means powerful long-lived credentials live outside and the cluster API must be reachable from the CI network. In ArgoCD's pull model, the controller lives inside the cluster and reaches outward to read Git, so credentials stay inside, the cluster is not exposed, and deployment is continuous reconciliation rather than a one-shot push. This does not eliminate Jenkins; it repositions CI to build, test, and commit the new image tag to Git, while ArgoCD owns the deployment step.
Remember one sentence: ArgoCD pulls desired state from Git into the cluster, keeping deploy credentials inside and enabling continuous reconciliation, self-healing, and safe rollback by reverting a Git commit.
---