Managing Applications with ArgoCD

ArgoCD applications represent the fundamental unit of deployment, connecting Git repositories to Kubernetes clusters. Effective application management requires understanding configuration options, lifecycle operations, and organizational patterns.

Application Configuration

ArgoCD applications use declarative YAML specifications to define the relationship between Git and Kubernetes.

Basic Application

A minimal application configuration specifies source and destination:

apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: frontend-app namespace: argocd spec: project: default source: repoURL: https://github.com/organization/frontend-manifests targetRevision: main path: kubernetes/production destination: server: https://kubernetes.default.svc namespace: production

This application deploys manifests from the kubernetes/production directory to the production namespace in the local cluster.

Source Configuration

Different source types support various manifest formats:

# Plain Kubernetes manifests source: repoURL: https://github.com/organization/k8s-manifests targetRevision: v2.1.0 path: apps/api-service # Helm chart from Git repository source: repoURL: https://github.com/organization/helm-charts targetRevision: main path: charts/api-service helm: valueFiles: - values-production.yaml parameters: - name: image.tag value: "v2.1.0" - name: replicas value: "5" # Helm chart from Helm repository source: repoURL: https://charts.bitnami.com/bitnami chart: postgresql targetRevision: 12.1.2 helm: values: | global: postgresql: auth: database: appdb username: appuser # Kustomize overlay source: repoURL: https://github.com/organization/k8s-manifests targetRevision: main path: apps/api-service/overlays/production

Each source type enables ArgoCD to process different manifest formats, from plain YAML to templated Helm charts and Kustomize overlays.

Destination Configuration

Applications deploy to specific clusters and namespaces:

# Deploy to local cluster destination: server: https://kubernetes.default.svc namespace: production # Deploy to remote cluster by URL destination: server: https://prod-cluster.example.com namespace: production # Deploy to cluster by name destination: name: production-cluster namespace: production

The destination determines where ArgoCD applies manifests, enabling multi-cluster deployments from a single ArgoCD instance.

graph LR subgraph Source G[Git Repository] H[Helm Repository] end subgraph ArgoCD A[Application Spec] end subgraph Destinations C1[Local Cluster] C2[Remote Cluster 1] C3[Remote Cluster 2] end G --> A H --> A A --> C1 A --> C2 A --> C3 style A fill:#e1f5ff

Sync Policies

Sync policies control how ArgoCD reconciles Git with cluster state.

Manual Sync

Applications require explicit sync actions:

apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: frontend-app spec: project: default source: repoURL: https://github.com/organization/frontend-manifests targetRevision: main path: kubernetes/production destination: server: https://kubernetes.default.svc namespace: production # No syncPolicy - manual sync required

Manual sync gives operators full control over when changes deploy. Use this for production environments requiring human approval.

# Trigger manual sync argocd app sync frontend-app # Sync with prune (delete removed resources) argocd app sync frontend-app --prune # Preview sync without applying argocd app sync frontend-app --dry-run

Automated Sync

Applications sync automatically when Git changes:

apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: frontend-app spec: project: default source: repoURL: https://github.com/organization/frontend-manifests targetRevision: main path: kubernetes/production destination: server: https://kubernetes.default.svc namespace: production syncPolicy: automated: prune: false # Don't delete resources removed from Git selfHeal: false # Don't revert manual changes allowEmpty: false # Prevent syncing when source has no manifests

Automated sync deploys Git changes within minutes, enabling continuous deployment. Configure prune and selfHeal based on environment requirements.

Self-Healing

Automatically revert manual cluster changes:

syncPolicy: automated: prune: true selfHeal: true syncOptions: - CreateNamespace=true

Self-healing enforces Git as the source of truth by reverting any manual modifications. When someone scales a deployment manually, ArgoCD restores the replica count from Git.

sequenceDiagram participant Operator participant K8s as Kubernetes participant Argo as ArgoCD participant Git Operator->>K8s: kubectl scale deployment --replicas=10 K8s->>K8s: Update replicas to 10 loop Every 3 minutes Argo->>K8s: Get deployment state K8s->>Argo: Replicas: 10 Argo->>Git: Get desired state Git->>Argo: Replicas: 3 Argo->>Argo: Detect drift Argo->>K8s: Scale deployment to 3 K8s->>K8s: Update replicas to 3 end

Sync Options

Fine-tune sync behavior with sync options.

Common Sync Options

syncPolicy: syncOptions: # Create namespace if it doesn't exist - CreateNamespace=true # Validate resources before syncing - Validate=true # Use server-side apply (better for large resources) - ServerSideApply=true # Replace resources instead of applying - Replace=true # Skip schema validation - SkipSchemaValidation=true # Respect ignore differences - RespectIgnoreDifferences=true

Sync options customize how ArgoCD applies manifests, handling edge cases like namespace creation or large resource updates.

Selective Sync

Apply only specific resources:

# Sync only deployment resources argocd app sync frontend-app --resource apps:Deployment:frontend # Sync multiple specific resources argocd app sync frontend-app \ --resource apps:Deployment:frontend \ --resource v1:Service:frontend

Selective sync enables surgical updates when full application sync would affect too many resources.

Health Assessment

ArgoCD evaluates application health based on resource status.

Health Status

Applications report overall health:

# Check application health argocd app get frontend-app # Filter applications by health status argocd app list --health Degraded

Custom Health Checks

Define health checks for custom resources:

apiVersion: v1 kind: ConfigMap metadata: name: argocd-cm namespace: argocd data: resource.customizations: | example.com/MyCustomResource: health.lua: | hs = {} if obj.status ~= nil then if obj.status.phase == "Ready" then hs.status = "Healthy" hs.message = "Resource is ready" return hs end if obj.status.phase == "Failed" then hs.status = "Degraded" hs.message = obj.status.message return hs end end hs.status = "Progressing" hs.message = "Waiting for resource" return hs

Custom health checks enable accurate status reporting for CRDs and operators that ArgoCD doesn't understand by default.

Diff Customization

Control how ArgoCD compares Git with cluster state.

Ignore Differences

Exclude specific fields from diff detection:

apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: frontend-app spec: ignoreDifferences: # Ignore all differences in replicas field - group: apps kind: Deployment jsonPointers: - /spec/replicas # Ignore webhook configurations (mutated by webhooks) - group: apps kind: Deployment jsonPointers: - /spec/template/metadata/annotations # Ignore storage size (can't be decreased) - group: "" kind: PersistentVolumeClaim jsonPointers: - /spec/resources/requests/storage

Ignoring differences prevents false out-of-sync status for fields that change frequently or are managed by other controllers.

Managed Namespaces

Track additional namespaces beyond the destination:

apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: frontend-app spec: destination: server: https://kubernetes.default.svc namespace: production syncPolicy: managedNamespaceMetadata: labels: managed-by: argocd environment: production annotations: description: Production frontend application

Managed namespace metadata ensures ArgoCD tracks namespace-level resources and labels.

Application Operations

Perform various operations on applications.

Rollback

Revert to a previous revision:

# View application history argocd app history frontend-app # Rollback to specific revision argocd app rollback frontend-app 5 # Rollback to previous revision argocd app rollback frontend-app

Rollback changes the target revision in Git or reverts to a previous sync operation, providing quick recovery from bad deployments.

Refresh

Force ArgoCD to compare Git with cluster state:

# Soft refresh (read cache) argocd app get frontend-app --refresh # Hard refresh (bypass cache) argocd app get frontend-app --hard-refresh

Refresh triggers immediate comparison instead of waiting for the next polling cycle, useful when validating recent Git commits.

Terminate Operation

Cancel an in-progress sync:

# Terminate sync operation argocd app terminate-op frontend-app

Terminating operations stops a sync that's taking too long or applying incorrect changes.

Application Organization

Structure applications for maintainability and scalability.

Projects

Group applications with Projects:

apiVersion: argoproj.io/v1alpha1 kind: AppProject metadata: name: production-apps namespace: argocd spec: description: Production environment applications # Allowed source repositories sourceRepos: - https://github.com/organization/production-manifests # Allowed destination clusters destinations: - namespace: production server: https://kubernetes.default.svc - namespace: production-* server: https://kubernetes.default.svc # Allowed resource types clusterResourceWhitelist: - group: '*' kind: '*' # RBAC policies roles: - name: developer policies: - p, proj:production-apps:developer, applications, get, production-apps/*, allow - p, proj:production-apps:developer, applications, sync, production-apps/*, allow groups: - dev-team

Projects enforce boundaries, restricting which repositories, namespaces, and resources applications can access, enabling multi-tenant ArgoCD instances.

Application of Applications Pattern

Manage multiple applications with a parent application:

# apps/production.yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: production-apps namespace: argocd spec: project: default source: repoURL: https://github.com/organization/argocd-apps targetRevision: main path: applications/production destination: server: https://kubernetes.default.svc namespace: argocd syncPolicy: automated: prune: true selfHeal: true

The applications directory contains child applications:

argocd-apps/ └── applications/ └── production/ ├── frontend-app.yaml ├── backend-app.yaml └── database-app.yaml

This pattern simplifies managing many applications by organizing them hierarchically and enabling bulk operations.

graph TD A[Parent Application: production-apps] --> B[Child: frontend-app] A --> C[Child: backend-app] A --> D[Child: database-app] B --> E[Git: frontend-manifests] C --> F[Git: backend-manifests] D --> G[Git: database-manifests] E --> H[K8s: frontend resources] F --> I[K8s: backend resources] G --> J[K8s: database resources] style A fill:#fff4e6

ApplicationSet

Generate applications dynamically:

apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: cluster-apps namespace: argocd spec: generators: # Generate from cluster list - clusters: selector: matchLabels: environment: production template: metadata: name: '{{name}}-frontend' spec: project: default source: repoURL: https://github.com/organization/frontend-manifests targetRevision: main path: kubernetes/production destination: server: '{{server}}' namespace: production syncPolicy: automated: prune: true selfHeal: true

ApplicationSet reduces configuration duplication by templating applications across clusters, namespaces, or Git repositories.

Monitoring and Observability

Track application status and performance.

Metrics

ArgoCD exposes Prometheus metrics:

# ServiceMonitor for Prometheus Operator apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: argocd-metrics namespace: argocd spec: selector: matchLabels: app.kubernetes.io/name: argocd-server endpoints: - port: metrics

Key metrics include:

Logs

Access application controller logs for troubleshooting:

# View application controller logs kubectl logs -n argocd deployment/argocd-application-controller # View logs for specific application kubectl logs -n argocd deployment/argocd-application-controller | grep frontend-app # View repository server logs kubectl logs -n argocd deployment/argocd-repo-server

Logs provide detailed information about sync operations, Git fetch errors, and resource application failures.

Common Pitfalls

Excessive Polling: Polling too frequently increases load on Git servers. Default 3-minute interval works for most use cases; avoid reducing below 30 seconds.

No Resource Limits: Large applications without pruning accumulate resources over time. Enable prune: true to delete removed resources automatically.

Ignoring Drift: Disabling self-healing while expecting consistent state creates confusion. Either enforce Git as source of truth with self-healing or accept manual changes.

Flat Application Structure: Managing dozens of applications at the top level becomes unwieldy. Use Projects, App of Apps, or ApplicationSet to organize hierarchically.

Key Takeaways