Stackbook Logo
← Back to Tools

Argo CD and GitOps Deployment

Use Argo CD to continuously deploy Kubernetes applications from Git: install, Application manifests, sync policies, app of apps and common pitfalls.

4 min read

What it is and when to use it

Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. It runs inside your cluster, watches a Git repository, and keeps the live cluster state equal to what Git describes. When someone merges a change, Argo CD notices the difference and syncs it. If someone edits the cluster by hand, Argo CD reports drift and can revert it.

Use it when you want Git to be the single source of truth, auditable deployments through pull requests, easy rollback by reverting a commit, and a clear view of what is running on many clusters. It supports plain YAML, Helm, Kustomize and Jsonnet.

Quick start

Install into its own namespace and reach the UI.

kubectl create namespace argocd
kubectl apply -n argocd --server-side -f \
  https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

kubectl port-forward svc/argocd-server -n argocd 8080:443

argocd admin initial-password -n argocd
argocd login localhost:8080 --username admin --insecure

Change the initial admin password after first login and delete the initial secret. Then register an application, either with the CLI or with a manifest.

argocd app create guestbook \
  --repo https://github.com/argoproj/argocd-example-apps.git \
  --path guestbook \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace demo
argocd app sync guestbook
argocd app get guestbook

Core concepts

Application is a custom resource that links a source (repo, revision, path) to a destination (cluster and namespace). Declaring it in YAML means Argo CD itself is managed by GitOps.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/example/deploy-config.git
    targetRevision: main
    path: apps/myapp/overlays/prod
  destination:
    server: https://kubernetes.default.svc
    namespace: myapp
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

Sync status and health. Synced means live state matches Git. Health reflects whether resources, such as Deployments, are actually running. An application can be Synced yet Degraded.

Sync policy. Manual sync gives a human gate. Automated sync applies commits as they arrive. The prune option deletes resources removed from Git, and selfHeal reverts manual cluster changes.

Projects (AppProject) restrict which repos, clusters and namespaces a team can deploy to, which is the basis of multi-tenancy.

Helm and Kustomize sources. For Helm, point the path at a chart and set values in the source block.

source:
  repoURL: https://github.com/example/charts.git
  path: charts/myapp
  targetRevision: v1.4.2
  helm:
    valueFiles:
      - values-prod.yaml

App of apps and ApplicationSet. A root Application can point at a directory containing other Application manifests, bootstrapping a whole cluster. ApplicationSet generates many Applications from templates, for example one per cluster or per directory.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: envs
  namespace: argocd
spec:
  generators:
    - list:
        elements:
          - env: staging
          - env: prod
  template:
    metadata:
      name: myapp-env
    spec:
      project: default
      source:
        repoURL: https://github.com/example/deploy-config.git
        targetRevision: main
        path: apps/myapp/overlays/prod
      destination:
        server: https://kubernetes.default.svc
        namespace: myapp

In a real set, the template uses the env parameter inside double braces so each element yields its own name, path and namespace.

Sync waves and hooks order resources using the argocd.argoproj.io/sync-wave annotation, and run Jobs before or after a sync.

Pitfalls

  • Do not store application source code and deployment config in the same repo if every code commit would trigger config churn. A separate config repo is the usual pattern.
  • Secrets cannot sit in Git unencrypted. Use Sealed Secrets, External Secrets Operator or SOPS.
  • Automated prune with a wrong path can delete workloads. Test on staging, and protect critical resources with the Prune=false annotation.
  • Fields mutated by controllers, such as replica counts under an autoscaler, cause perpetual OutOfSync. Use ignoreDifferences.
  • Pin targetRevision to tags or commits for production rather than a moving branch when you need strict promotion.
  • Lock down RBAC and the admin account, and use SSO for real teams.

How it fits an architecture

A typical flow: CI in GitHub Actions builds and tests an image, pushes it, and opens a commit or pull request that bumps the image tag in the config repo. Argo CD detects the merge and rolls it out. Terraform creates the cluster and installs Argo CD once; from then on Argo CD manages everything else, including Helm releases, ingress and mesh configuration. Rollback is a git revert.

Key takeaways

  • Argo CD pulls from Git into the cluster, so CI never needs cluster credentials.
  • Application resources define source, destination and sync behavior declaratively.
  • Enable selfHeal and prune only once you trust your repo layout.
  • Use ApplicationSet and app of apps to scale across clusters and environments.
  • Keep secrets encrypted and use projects and RBAC for team isolation.