Skip to content
Back to Blog
DevOps

ArgoCD: GitOps Continuous Delivery for Kubernetes

Deploy and manage applications on Kubernetes using ArgoCD: App of Apps pattern, sync policies, RBAC, and multi-cluster management.

Oct 2025
16 min read

Introduction

ArgoCD is a declarative, GitOps continuous delivery tool for Kubernetes. GitOps means your Git repository is the single source of truth for your infrastructure and application state — ArgoCD continuously watches your Git repo and ensures your Kubernetes cluster matches what's defined there. If someone makes a manual change to the cluster, ArgoCD detects the drift and can automatically revert it. This guide teaches you to implement GitOps with ArgoCD.

Why GitOps with ArgoCD?

Traditional CI/CD: Code → Build → Push → CI system PUSHES to cluster

GitOps: Code → Build → Update Git → ArgoCD PULLS from Git to cluster

Benefits:

  • Audit trail: Every deployment is a Git commit (who, what, when)
  • Easy rollback: git revert = instant rollback
  • Drift detection: Cluster always matches desired state
  • No cluster credentials in CI: CI doesn't need kubectl access

Installing ArgoCD

BASH
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=300s

# Get initial admin password
kubectl -n argocd get secret argocd-initial-admin-secret   -o jsonpath="{.data.password}" | base64 -d; echo

# Port-forward to access UI
kubectl port-forward svc/argocd-server -n argocd 8080:443
# Access at https://localhost:8080  (admin / <password above>)

Install ArgoCD CLI:

BASH
curl -sSL -o argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
chmod +x argocd && sudo mv argocd /usr/local/bin/

# Login
argocd login localhost:8080 --username admin --password <password> --insecure

Exposing ArgoCD via Ingress

YAML
# argocd-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  ingressClassName: nginx
  rules:
  - host: argocd.company.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              number: 443

Creating Your First Application

YAML
# app-myapp.yaml - Define ArgoCD Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp-production
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io  # Clean up when app deleted
spec:
  project: default

  source:
    repoURL: https://github.com/company/k8s-manifests.git
    targetRevision: main              # Branch/tag/commit to watch
    path: apps/myapp/production       # Directory within repo

  destination:
    server: https://kubernetes.default.svc  # Target cluster
    namespace: production

  syncPolicy:
    automated:
      prune: true     # Delete resources removed from Git
      selfHeal: true  # Revert manual changes
    syncOptions:
    - CreateNamespace=true
    - PrunePropagationPolicy=foreground
    retry:
      limit: 5
      backoff:
        duration: 5s
        maxDuration: 3m
        factor: 2
BASH
kubectl apply -f app-myapp.yaml

# Check status
argocd app list
argocd app get myapp-production

# Manual sync (if automated sync disabled)
argocd app sync myapp-production

# Wait for sync to complete
argocd app wait myapp-production --sync

Repository Structure for GitOps

TEXT
k8s-manifests/
├── apps/
│   ├── myapp/
│   │   ├── base/                    # Kustomize base
│   │   │   ├── deployment.yaml
│   │   │   ├── service.yaml
│   │   │   └── kustomization.yaml
│   │   ├── staging/
│   │   │   ├── kustomization.yaml   # Patches for staging
│   │   │   └── values-patch.yaml
│   │   └── production/
│   │       ├── kustomization.yaml   # Patches for production
│   │       └── replicas-patch.yaml
│   └── database/
│       └── ...
├── infrastructure/
│   ├── ingress-nginx/
│   └── cert-manager/
└── argocd/
    └── applications/               # ArgoCD Application manifests

Kustomization example:

YAML
# apps/myapp/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../base

patches:
  - path: replicas-patch.yaml

images:
  - name: company/myapp
    newTag: v3.5.2              # Update this for deployments

App of Apps Pattern

Manage multiple applications with a single ArgoCD Application:

YAML
# argocd/app-of-apps.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app-of-apps
  namespace: argocd
spec:
  source:
    repoURL: https://github.com/company/k8s-manifests.git
    targetRevision: main
    path: argocd/applications    # Directory with all Application CRDs
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

CI/CD Integration

YAML
# .github/workflows/deploy.yml
name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  update-image:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          repository: company/k8s-manifests
          token: ${{ secrets.GITOPS_TOKEN }}

      - name: Update image tag
        run: |
          # Update kustomization.yaml with new image tag
          cd apps/myapp/production
          kustomize edit set image company/myapp=company/myapp:${{ github.sha }}

      - name: Commit and push
        run: |
          git config user.email "ci@company.com"
          git config user.name "CI Bot"
          git add .
          git commit -m "Update myapp to ${{ github.sha }}"
          git push

RBAC and Projects

YAML
# argocd-project.yaml - Limit what each team can deploy
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: team-backend
  namespace: argocd
spec:
  description: Backend team deployments

  sourceRepos:
    - 'https://github.com/company/k8s-manifests.git'

  destinations:
    - namespace: backend-staging
      server: https://kubernetes.default.svc
    - namespace: backend-production
      server: https://kubernetes.default.svc

  clusterResourceWhitelist: []  # No cluster-level resources
  namespaceResourceWhitelist:
    - group: 'apps'
      kind: 'Deployment'
    - group: ''
      kind: 'Service'

Monitoring ArgoCD

BASH
# Watch all applications
argocd app list -w

# Check specific app diff (what would change on next sync)
argocd app diff myapp-production

# View sync history
argocd app history myapp-production

# Rollback to specific revision
argocd app rollback myapp-production 42

ArgoCD transforms Kubernetes deployments into a Git-centric workflow. Once implemented, every deployment becomes auditable, every rollback becomes a git revert, and your cluster state becomes verifiable against your repository.