ArgoCD Applications & Projects

Applications are the core resource in ArgoCD. An Application represents a set of Kubernetes resources that should be deployed from a Git repository, Helm chart, or other source to a destination cluster and namespace.

What is an Application?

An Application is a Custom Resource Definition (CRD) that tells ArgoCD:

  • Source - Where to get the manifests (Git repo, Helm chart, etc.)
  • Destination - Where to deploy (cluster and namespace)
  • Sync Policy - How to sync (automated or manual)
  • Health - How to determine if the application is healthy
graph TB A[Application CRD] --> B[Source] A --> C[Destination] A --> D[Sync Policy] B --> E[Git Repository] B --> F[Helm Chart] B --> G[Kustomize] C --> H[Cluster] C --> I[Namespace] D --> J[Auto Sync] D --> K[Manual Sync] style A fill:#e1f5ff style B fill:#e8f5e9 style C fill:#fff4e1 style D fill:#f3e5f5

Creating Applications

Method 1: Declarative (YAML)

The recommended approach is to define Applications as YAML manifests:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/your-org/kubernetes-manifests
    targetRevision: main
    path: apps/web-app
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

Apply the Application:

kubectl apply -f application.yaml

Method 2: Using ArgoCD CLI

argocd app create web-app \
  --repo https://github.com/your-org/kubernetes-manifests \
  --path apps/web-app \
  --dest-server https://kubernetes.default.svc \
  --dest-namespace production \
  --sync-policy automated \
  --auto-prune \
  --self-heal

Method 3: Using ArgoCD UI

  1. Click “New App” button
  2. Fill in application details:
    • Application Name
    • Project
    • Source (Repository URL, Path, Revision)
    • Destination (Cluster, Namespace)
  3. Click “Create”

Application Spec Structure

Basic Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/user/repo
    targetRevision: HEAD
    path: manifests
  destination:
    server: https://kubernetes.default.svc
    namespace: default

Application with Helm Chart

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: nginx
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://charts.bitnami.com/bitnami
    chart: nginx
    targetRevision: 13.2.20
    helm:
      values: |
        service:
          type: LoadBalancer
        replicaCount: 3
  destination:
    server: https://kubernetes.default.svc
    namespace: default

Application with Kustomize

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: kustomize-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/user/repo
    targetRevision: main
    path: kustomize/base
    kustomize:
      images:
      - nginx:1.21.0
      commonAnnotations:
        app.kubernetes.io/managed-by: argocd
  destination:
    server: https://kubernetes.default.svc
    namespace: default

Application with Multiple Sources

ArgoCD supports applications with multiple sources (e.g., Helm chart + additional manifests):

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: multi-source-app
  namespace: argocd
spec:
  project: default
  sources:
  - repoURL: https://charts.bitnami.com/bitnami
    chart: nginx
    targetRevision: 13.2.20
    helm:
      values: |
        service:
          type: ClusterIP
  - repoURL: https://github.com/user/repo
    targetRevision: main
    path: additional-configs
  destination:
    server: https://kubernetes.default.svc
    namespace: default

Application Lifecycle

stateDiagram-v2 [*] --> Unknown Unknown --> Syncing: Sync Started Syncing --> Progressing: Resources Applied Progressing --> Healthy: All Resources Healthy Progressing --> Degraded: Some Resources Unhealthy Healthy --> OutOfSync: Git Changes Detected Healthy --> Degraded: Cluster Drift Detected OutOfSync --> Syncing: Sync Triggered Degraded --> Syncing: Self-Heal or Manual Sync Syncing --> Unknown: Sync Failed

Application States

  • Unknown - Initial state, not yet synced
  • Syncing - Currently applying changes
  • Progressing - Resources being created/updated
  • Healthy - All resources are healthy and in sync
  • Degraded - Some resources are unhealthy
  • Suspended - Application sync is paused
  • OutOfSync - Desired state differs from actual state

Application Health

ArgoCD determines application health based on resource health:

Built-in Health Checks

ArgoCD has built-in health checks for:

  • Deployment - Checks if replicas match desired count
  • StatefulSet - Checks if replicas match desired count
  • DaemonSet - Checks if pods are scheduled
  • Service - Always healthy (no runtime health)
  • Pod - Checks phase (Running, Pending, Failed)
  • Job - Checks completion status
  • PersistentVolumeClaim - Checks if bound

Custom Health Checks

Define custom health checks using Lua scripts:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  resource.customizations.health.argoproj.io_Application: |
    hs = {}
    if obj.status ~= nil then
      if obj.status.health ~= nil then
        hs.status = obj.status.health.status
        hs.message = obj.status.health.message
      else
        hs.status = "Progressing"
        hs.message = "Waiting for health status"
      end
    else
      hs.status = "Unknown"
      hs.message = "No status available"
    end
    return hs

Application Sync

Manual Sync

Sync an application manually:

# Sync application
argocd app sync web-app

# Sync with specific revision
argocd app sync web-app --revision <COMMIT_HASH>

# Sync with prune (delete resources not in Git)
argocd app sync web-app --prune

# Sync with force (bypass hooks)
argocd app sync web-app --force

Automated Sync

Enable automated sync in the Application spec:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web-app
  namespace: argocd
spec:
  syncPolicy:
    automated:
      prune: true      # Delete resources removed from Git
      selfHeal: true   # Automatically sync on cluster drift
      allowEmpty: false # Allow apps with no resources

Sync Options

Configure sync behavior:

spec:
  syncPolicy:
    syncOptions:
    - CreateNamespace=true        # Create namespace if missing
    - PruneLast=true              # Prune resources last
    - PrunePropagationPolicy=foreground
    - RespectIgnoreDifferences=true
    - ApplyOutOfSyncOnly=true     # Only sync out-of-sync resources

ApplicationSets

ApplicationSets manage multiple Applications from a single definition. Useful for:

  • Multiple environments (dev, staging, prod)
  • Multiple clusters
  • Multiple applications with similar configs

List ApplicationSet

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: web-apps
  namespace: argocd
spec:
  generators:
  - list:
      elements:
      - cluster: production
        url: https://prod.example.com
        namespace: prod
      - cluster: staging
        url: https://staging.example.com
        namespace: staging
  template:
    metadata:
      name: '{{cluster}}-web-app'
    spec:
      project: default
      source:
        repoURL: https://github.com/user/repo
        targetRevision: main
        path: apps/web-app
      destination:
        server: '{{url}}'
        namespace: '{{namespace}}'
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

Cluster Generator

Generate applications for multiple clusters:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: multi-cluster-app
  namespace: argocd
spec:
  generators:
  - clusters:
      selector:
        matchLabels:
          environment: production
  template:
    metadata:
      name: '{{name}}-app'
    spec:
      project: default
      source:
        repoURL: https://github.com/user/repo
        targetRevision: main
        path: apps/my-app
      destination:
        server: '{{server}}'
        namespace: default

Git Directory Generator

Generate applications from Git directory structure:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: git-directory-apps
  namespace: argocd
spec:
  generators:
  - git:
      repoURL: https://github.com/user/repo
      revision: main
      directories:
      - path: apps/*
  template:
    metadata:
      name: '{{path.basename}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/user/repo
        targetRevision: main
        path: '{{path}}'
      destination:
        server: https://kubernetes.default.svc
        namespace: '{{path.basename}}'

Projects

Projects provide a way to group Applications and enforce policies.

Project Structure

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: production
  namespace: argocd
spec:
  description: Production applications
  sourceRepos:
  - 'https://github.com/your-org/*'
  - 'https://charts.bitnami.com/bitnami'
  destinations:
  - namespace: production
    server: https://kubernetes.default.svc
  - namespace: '*'
    server: https://prod-cluster.example.com
  clusterResourceWhitelist:
  - group: '*'
    kind: '*'
  namespaceResourceWhitelist:
  - group: '*'
    kind: '*'

Project Restrictions

Projects can restrict:

  • Source Repositories - Which Git repos can be used
  • Destinations - Which clusters/namespaces can be targeted
  • Resources - Which Kubernetes resources can be deployed
  • Sync Windows - When syncs are allowed

Example: Restricted Project

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: restricted
  namespace: argocd
spec:
  description: Restricted project with limited permissions
  sourceRepos:
  - 'https://github.com/your-org/approved-repo'
  destinations:
  - namespace: staging
    server: https://kubernetes.default.svc
  namespaceResourceWhitelist:
  - group: apps
    kind: Deployment
  - group: v1
    kind: Service
  - group: v1
    kind: ConfigMap
  # Deny all cluster-scoped resources
  clusterResourceWhitelist: []

Sync Windows

Define when Applications can be synced:

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: production
  namespace: argocd
spec:
  syncWindows:
  - kind: allow
    schedule: '0 9 * * 1-5'  # Weekdays 9 AM
    duration: 8h
    applications:
    - 'production-*'
  - kind: deny
    schedule: '* * * * *'     # All other times
    applications:
    - 'production-*'

Managing Applications

View Application Status

# List all applications
argocd app list

# Get application details
argocd app get web-app

# Watch application status
argocd app get web-app --watch

# Get application resources
argocd app resources web-app

Application Operations

# Sync application
argocd app sync web-app

# Delete application (keeps resources in cluster)
argocd app delete web-app

# Delete application and resources
argocd app delete web-app --cascade

# Suspend application (pause sync)
argocd app suspend web-app

# Resume application
argocd app resume web-app

# Rollback to previous version
argocd app rollback web-app <REVISION>

Application History

# View sync history
argocd app history web-app

# View specific revision
argocd app get web-app --revision <REVISION>

Best Practices

1. Use Declarative Applications

Store Application definitions in Git:

# apps/web-app/application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web-app
  namespace: argocd
spec:
  # ...

2. Organize with Projects

Use Projects to:

  • Group related applications
  • Enforce policies
  • Limit access
  • Define sync windows

3. Use ApplicationSets for Multiple Environments

Instead of creating multiple Applications manually, use ApplicationSets:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: web-app-environments
  namespace: argocd
spec:
  generators:
  - list:
      elements:
      - env: dev
        namespace: dev
      - env: staging
        namespace: staging
      - env: prod
        namespace: production
  template:
    metadata:
      name: web-app-{{env}}
    spec:
      project: default
      source:
        repoURL: https://github.com/user/repo
        targetRevision: main
        path: apps/web-app/overlays/{{env}}
      destination:
        server: https://kubernetes.default.svc
        namespace: {{namespace}}

4. Pin Revisions

For production, pin to specific revisions:

spec:
  source:
    targetRevision: v1.2.3  # Tag
    # or
    targetRevision: abc123f  # Commit hash

5. Use Sync Policies Appropriately

  • Automated sync - For development/staging
  • Manual sync - For production (with approvals)
  • Self-heal - Enable to prevent drift

6. Monitor Application Health

Set up alerts for:

  • Application health status
  • Sync failures
  • OutOfSync state
  • Degraded resources

Troubleshooting

Application Stuck in Syncing

# Check application status
argocd app get web-app

# Check application controller logs
kubectl logs -n argocd -l app.kubernetes.io/name=argocd-application-controller

# Force sync
argocd app sync web-app --force

Application OutOfSync

# Check what's different
argocd app diff web-app

# View resources
argocd app resources web-app

# Sync to fix
argocd app sync web-app

Health Check Failures

# Get detailed health status
argocd app get web-app --show-operation

# Check resource health
argocd app resources web-app

# Check Kubernetes resources directly
kubectl get all -n <NAMESPACE>

Summary

Applications are the core of ArgoCD, defining what to deploy and where. Key points:

  • Applications define source, destination, and sync policy
  • Projects group applications and enforce policies
  • ApplicationSets manage multiple applications from one definition
  • Use declarative Application definitions stored in Git
  • Configure sync policies based on environment needs
  • Monitor application health and status

Next, learn about Sync Policies to configure automated sync, hooks, and sync windows.