Skip to main content
DevopsAdvanced24 min readUpdated March 2025

GitOps with ArgoCD

GitOps is a deployment methodology where Git is the single source of truth for infrastructure and application state. ArgoCD is a declarative GitOps continuous delivery tool for Kubernetes that automatically syncs your cluster to match what is in Git.

What is GitOps?

GitOps is an operational framework that applies DevOps best practices (version control, collaboration, CI/CD) to infrastructure automation. The core principles are:

1. Declarative — The entire system is described declaratively (Kubernetes YAML, Helm charts, Kustomize) 2. Versioned and immutable — The desired state is stored in Git. Git history is the audit log. 3. Pulled automatically — Approved changes in Git are automatically applied to the system 4. Continuously reconciled — Software agents continuously ensure the actual state matches the desired state in Git

The key difference from traditional CI/CD: in GitOps, the cluster pulls changes from Git rather than a CI pipeline pushing to the cluster. This improves security (no cluster credentials in CI) and reliability.

ArgoCD Architecture

ArgoCD runs inside your Kubernetes cluster and continuously watches Git repositories:

  • API Server — gRPC/REST server that exposes the ArgoCD API. Used by the Web UI, CLI, and CI/CD systems.
  • Repository Server — Clones Git repos and generates Kubernetes manifests (from plain YAML, Helm, Kustomize, Jsonnet).
  • Application Controller — Continuously compares the live cluster state against the desired state in Git. Detects OutOfSync applications and optionally auto-syncs them.
  • ApplicationSet Controller — Generates ArgoCD Applications from templates (for managing many apps/clusters).
  • Dex — Identity provider for SSO integration (LDAP, SAML, OIDC).

Installing ArgoCD

Install ArgoCD into your Kubernetes cluster:

bash
# Install ArgoCD into its own namespace
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 the initial admin password
kubectl -n argocd get secret argocd-initial-admin-secret   -o jsonpath="{.data.password}" | base64 -d

# Port-forward to access the UI locally
kubectl port-forward svc/argocd-server -n argocd 8080:443

# Install ArgoCD CLI (macOS)
brew install argocd

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

# Change admin password
argocd account update-password

Creating an ArgoCD Application

An ArgoCD Application is a CRD (Custom Resource Definition) that links a Git repository path to a Kubernetes cluster/namespace:

yaml
# argocd-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web-app
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io  # Cascade delete
spec:
  project: default

  source:
    repoURL: https://github.com/myorg/k8s-manifests.git
    targetRevision: main          # Branch, tag, or commit SHA
    path: apps/web-app            # Path within the repo

    # For Helm charts:
    # chart: web-app
    # helm:
    #   valueFiles:
    #     - values.prod.yaml
    #   parameters:
    #     - name: image.tag
    #       value: "2.1.0"

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

  syncPolicy:
    automated:
      prune: true       # Delete resources removed from Git
      selfHeal: true    # Revert manual changes to cluster
    syncOptions:
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

The GitOps Workflow

The complete GitOps workflow with ArgoCD:

bash
# ---- Typical GitOps deployment flow ----

# 1. Developer pushes code to application repo
git push origin feature/new-feature

# 2. CI pipeline (GitHub Actions/Jenkins) runs tests and builds image
# CI pushes image: registry.company.com/web-app:sha-abc123

# 3. CI updates the image tag in the GitOps repo (separate from app repo)
# This is the "write to Git" step
git clone https://github.com/myorg/k8s-manifests.git
cd k8s-manifests
# Update image tag in values.yaml or kustomization.yaml
sed -i 's|image.tag:.*|image.tag: sha-abc123|' apps/web-app/values.yaml
git commit -am "chore: update web-app to sha-abc123"
git push origin main

# 4. ArgoCD detects the change in Git (polls every 3 min or via webhook)
# ArgoCD compares desired state (Git) with actual state (cluster)
# Status changes from "Synced" to "OutOfSync"

# 5. ArgoCD syncs (automatically if autoSync enabled, or manually)
argocd app sync web-app

# 6. ArgoCD applies the updated manifests to the cluster
# Kubernetes performs a rolling update

# ---- Useful ArgoCD CLI commands ----
argocd app list                          # List all applications
argocd app get web-app                   # App details and sync status
argocd app diff web-app                  # Show diff between Git and cluster
argocd app sync web-app                  # Manually trigger sync
argocd app rollback web-app 3            # Rollback to revision 3
argocd app history web-app               # Deployment history

App of Apps Pattern

The App of Apps pattern uses a root ArgoCD Application that manages other ArgoCD Applications. This enables managing an entire platform's worth of applications declaratively in Git.

Instead of manually creating each ArgoCD Application, you create one "root" app that points to a directory of Application manifests. When you add a new app manifest to Git, ArgoCD automatically creates and syncs it.

This pattern, combined with ApplicationSets (which generate Applications from templates based on clusters, environments, or Git directories), is how large organizations manage hundreds of microservices across multiple clusters with GitOps.

Key Takeaways

  • Pods are ephemeral — never create them directly; use Deployments to manage their lifecycle.
  • Deployments provide rolling updates, rollback, and self-healing for stateless applications.
  • Services provide a stable IP/DNS name that load-balances traffic across matching Pods via label selectors.
  • Use ClusterIP for internal services, LoadBalancer for internet-facing services.
  • ConfigMaps store non-sensitive config; Secrets store sensitive data — both inject into Pods as env vars or files.

Contact Us

Have a question or feedback? Fill out the form below or reach us directly at support@nvaitraining.com