Argo CD

CI/CDArgo CDGitOpsKubernetesDeploymentContinuous DeliveryApplicationSetDeclarative

CI/CD Tool

Argo CD

Overview

Argo CD is a declarative GitOps continuous delivery tool for Kubernetes. It monitors Git repository configuration changes and automatically executes deployments to Kubernetes clusters, enabling modern cloud-native operations.

Details

Argo CD is a declarative continuous delivery tool that implements GitOps methodology in Kubernetes environments, serving as a graduated project of the Cloud Native Computing Foundation (CNCF). In 2024-2025, ApplicationSet enhancements have significantly improved multi-application and multi-cluster management, accelerating adoption in large enterprises. Following core GitOps principles, it makes application definitions, configurations, and environments declarative and version-controlled, while automating deployment and lifecycle management in an auditable and understandable manner. When changes occur in Kubernetes configurations (manifest files) in Git, Argo CD notifies users and prompts synchronization with the desired state. When configuration drift occurs in production systems, Argo CD detects changes and automatically restores to the desired state defined in Git. Extending beyond Argo CD Application resources that deploy from a single Git repository to a single cluster/namespace, ApplicationSet uses template-based automation to create, modify, and manage multiple Argo CD applications simultaneously. It supports configuration management and templating tools including YAML, Helm charts, Jsonnet, and Kustomize, and can implement Canary and Blue-Green deployment strategies combined with Argo Rollouts. Integration with SSO providers including OIDC, OAuth2, LDAP, SAML 2.0, GitHub, GitLab, Microsoft, and LinkedIn provides enterprise-level security and multi-tenancy.

Pros and Cons

Pros

  • Declarative GitOps: Git as source of truth for configuration management and auto-sync
  • Full Kubernetes Integration: K8s-native configuration and CRD support
  • ApplicationSet: Centralized management of multiple apps across clusters
  • Visual UI: Intuitive web UI for deployment status monitoring
  • Auto-Recovery: Configuration drift detection and automatic desired state restoration
  • Multi-tenancy: Project-based permission and resource isolation
  • Rich Integrations: Support for Helm, Kustomize, Jsonnet
  • SSO Support: Enterprise authentication system integration
  • Rollback Capabilities: Easy previous version recovery via Git history

Cons

  • Kubernetes-Only: No support for other platforms
  • Learning Curve: Requires GitOps concepts and Kubernetes knowledge
  • Git Dependency: Deployment impact during Git outages
  • Configuration Complexity: ApplicationSet management in large environments
  • Real-time Limitations: Sync delays due to polling intervals
  • Debugging Difficulty: Complex manifest issue identification challenges
  • Permission Management: Operational overhead of granular RBAC configuration

Key Links

Code Examples

Basic Argo CD Installation

# Create Argo CD namespace
kubectl create namespace argocd

# Install Argo CD stable version
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Expose service (LoadBalancer)
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'

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

# Install Argo CD CLI
curl -sSL -o argocd-linux-amd64 https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
sudo install -m 555 argocd-linux-amd64 /usr/local/bin/argocd
rm argocd-linux-amd64

# CLI login
argocd login <ARGOCD_SERVER>

Basic Application Resource Definition

# application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/argoproj/argocd-example-apps.git
    targetRevision: HEAD
    path: guestbook
  destination:
    server: https://kubernetes.default.svc
    namespace: guestbook
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

Multi-Application Management with ApplicationSet

# applicationset.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: cluster-addons
  namespace: argocd
spec:
  goTemplate: true
  goTemplateOptions: ["missingkey=error"]
  generators:
  - clusters:
      selector:
        matchLabels:
          argocd.argoproj.io/secret-type: cluster
  - git:
      repoURL: https://github.com/example/cluster-addons.git
      revision: HEAD
      directories:
      - path: "cluster-addons/*"
  template:
    metadata:
      name: '{{.path.basename}}-{{.name}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/example/cluster-addons.git
        targetRevision: HEAD
        path: '{{.path.path}}'
      destination:
        server: '{{.server}}'
        namespace: '{{.path.basename}}'
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
        - CreateNamespace=true

Helm Chart Integration and Values File Management

# helm-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: prometheus
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://prometheus-community.github.io/helm-charts
    chart: prometheus
    targetRevision: 25.27.0
    helm:
      valueFiles:
      - values-production.yaml
      parameters:
      - name: server.persistentVolume.size
        value: 100Gi
      - name: server.replicaCount
        value: "2"
  destination:
    server: https://kubernetes.default.svc
    namespace: monitoring
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

Kustomize Integration and Overlay Management

# kustomize-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: webapp-production
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/example/webapp-config.git
    targetRevision: HEAD
    path: overlays/production
    kustomize:
      images:
      - webapp:v1.2.3
      patches:
      - target:
          kind: Deployment
          name: webapp
        patch: |-
          - op: replace
            path: /spec/replicas
            value: 5
  destination:
    server: https://kubernetes.default.svc
    namespace: webapp-prod
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
    - RespectIgnoreDifferences=true
  ignoreDifferences:
  - group: apps
    kind: Deployment
    jsonPointers:
    - /spec/replicas

Environment × Cluster Deployment with Matrix Generator

# matrix-applicationset.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: webapp-environments
  namespace: argocd
spec:
  goTemplate: true
  generators:
  - matrix:
      generators:
      - git:
          repoURL: https://github.com/example/app-config.git
          revision: HEAD
          files:
          - path: "environments/*/config.json"
      - clusters:
          selector:
            matchLabels:
              environment: '{{.path.basename}}'
  template:
    metadata:
      name: 'webapp-{{.path.basename}}-{{.name}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/example/webapp.git
        targetRevision: HEAD
        path: k8s
        kustomize:
          images:
          - webapp:{{.config.image.tag}}
      destination:
        server: '{{.server}}'
        namespace: webapp-{{.path.basename}}
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
        - CreateNamespace=true

Progressive Rollout Strategy

# progressive-rollout-applicationset.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: webapp-rollout
  namespace: argocd
spec:
  generators:
  - list:
      elements:
      - cluster: dev-cluster
        env: dev
        priority: "1"
      - cluster: staging-cluster
        env: staging
        priority: "2"
      - cluster: prod-us-west
        env: production
        priority: "3"
      - cluster: prod-eu-west
        env: production
        priority: "3"
      - cluster: prod-asia
        env: production
        priority: "4"
  strategy:
    type: RollingUpdate
    rollingUpdate:
      steps:
      - matchExpressions:
        - key: priority
          operator: In
          values: ["1"]
        maxUpdate: 0  # Update all simultaneously
      - matchExpressions:
        - key: priority
          operator: In
          values: ["2"]
        maxUpdate: 1  # Update one by one
      - matchExpressions:
        - key: priority
          operator: In
          values: ["3"]
        maxUpdate: 50%  # Update 50% at a time
      - matchExpressions:
        - key: priority
          operator: In
          values: ["4"]
  template:
    metadata:
      name: 'webapp-{{.cluster}}'
      labels:
        env: "{{.env}}"
        priority: "{{.priority}}"
    spec:
      project: default
      source:
        repoURL: https://github.com/example/webapp.git
        targetRevision: HEAD
        path: k8s/{{.env}}
      destination:
        server: '{{.cluster}}'
        namespace: webapp
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

Private Repository and Secret Management

# private-repo-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: private-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: https://github.com/company/private-repo.git
  username: deployment-bot
  password: $GITHUB_TOKEN
  project: webapp-project

---
# cluster-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: cluster
stringData:
  name: production-cluster
  server: https://production-k8s.company.com
  config: |
    {
      "bearerToken": "$CLUSTER_TOKEN",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "$CA_DATA"
      }
    }

---
# app-project.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: webapp-project
  namespace: argocd
spec:
  description: "Web Application Project"
  sourceRepos:
  - 'https://github.com/company/*'
  - 'https://helm-charts.company.com/*'
  destinations:
  - namespace: 'webapp-*'
    server: '*'
  clusterResourceWhitelist:
  - group: ''
    kind: Namespace
  namespaceResourceWhitelist:
  - group: apps
    kind: Deployment
  - group: ''
    kind: Service
  - group: ''
    kind: ConfigMap
  - group: ''
    kind: Secret
  roles:
  - name: webapp-admin
    description: Admin access to webapp project
    policies:
    - p, proj:webapp-project:webapp-admin, applications, *, webapp-project/*, allow
    - p, proj:webapp-project:webapp-admin, repositories, *, *, allow
    groups:
    - company:webapp-team