Argo CD ApplicationSet Controller: Multi-Cluster GitOps Automation Explained

The Argo CD ApplicationSet controller is a Kubernetes controller that watches the ApplicationSet custom resource and automatically reconciles a fleet of Argo CD Application objects using generators, templates, and progressive sync policies.

The Argo CD ApplicationSet controller, housed in the argoproj/argo-cd repository, extends Argo CD’s capabilities by enabling declarative management of multiple Application resources across clusters and environments. Unlike the standard Application controller which manages individual deployments, this controller implements a reconcile loop that generates, validates, and synchronizes entire sets of applications based on dynamic data sources such as Git repositories, cluster lists, or SCM providers.

How the Argo CD ApplicationSet Controller Works

The controller implements a standard Kubernetes controller pattern through a five-stage reconcile loop defined in applicationset/controllers/applicationset_controller.go:

  1. Read the ApplicationSet spec to extract generator configurations and templates.
  2. Generate desired Application resources by invoking configured generators and executing template.GenerateApplications from applicationset/template/template.go.
  3. Validate generated applications against project existence, destination validity, and duplicate application names.
  4. Reconcile the current cluster state by creating new applications, updating changed ones via createOrUpdateInCluster, and deleting stale resources.
  5. Update the ApplicationSet status using updateResourcesStatus and setAppSetApplicationStatus to reflect resource health, progressive sync progress, and error conditions.

Core Architecture and Implementation

Reconciliation Logic in applicationset_controller.go

The primary entry point is the Reconcile(ctx, req) method in applicationset/controllers/applicationset_controller.go. This method drives the entire lifecycle process, handling resource deletion, progressive synchronization, and status migration. It manages complex scenarios such as invalid destinations through removeFinalizerOnInvalidDestination, which ensures finalizers are cleaned up when target clusters become unreachable, preventing deletion deadlocks.

Generator Plugin System

The controller delegates application generation to pluggable generators located in applicationset/generators/. Each generator—whether List, Git, Cluster, or SCM—produces parameter sets that the controller passes to template.GenerateApplications. This architecture allows the ApplicationSet to dynamically create Application manifests based on external data sources, such as discovering directories in a Git repository or listing available clusters from cluster secrets.

Progressive Sync and Rollout Management

The experimental progressive sync feature, implemented in applicationset/progressivesync, enables phased rollouts of applications across clusters. When the controller starts with the --enable-progressive-syncs flag, it executes the steps defined in spec.progressiveSync (such as pause or sync) sequentially rather than simultaneously. The controller updates the ApplicationSet status with rollout progress, allowing for canary-style deployments or maintenance windows.

Ownership and Finalizer Management

The controller establishes strict ownership relationships by adding the ApplicationSet as an OwnerReference to each generated Application. This ensures Kubernetes garbage collection removes dependent applications when the parent ApplicationSet is deleted. The finalizer logic guarantees safe deletion even when destination clusters become invalid, using removeFinalizerOnInvalidDestination to clean up resources that can no longer reach their targets.

Deployment and Operational Configuration

Controller Flags and Runtime Options

The controller runs as the binary argocd-applicationset-controller, typically deployed as a separate pod (argocd-applicationset-controller) with its own ServiceAccount and RBAC bindings. Key operational flags include:

  • --concurrent-application-updates: Controls parallelism for application modifications (default varies by version).
  • --enable-progressive-syncs: Activates the experimental progressive rollout feature.
  • --metrics-addr: Exposes Prometheus metrics via ApplicationsetMetrics (default :8080).

Documentation for these flags is maintained in docs/operator-manual/server-commands/argocd-applicationset-controller.md.

RBAC and Kubernetes Resources

Deployment manifests reside in manifests/base/applicationset-controller/, defining the controller’s Deployment, ServiceAccount, Role, and ClusterRole bindings. The Custom Resource Definition for the ApplicationSet API, including all generator and sync policy specifications, is defined in manifests/crds/applicationset-crd.yaml. Detailed specification documentation is available in docs/operator-manual/applicationset/applicationset-specification.md.

Practical Implementation Examples

Basic List Generator Configuration

The following manifest uses the list generator to create two Application resources—one for development and one for production—from a single template:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: guestbook
spec:
  generators:
  - list:
      elements:
      - cluster: dev
        url: https://k8s.dev.example.com
      - cluster: prod
        url: https://k8s.prod.example.com
  template:
    metadata:
      name: '{{cluster}}-guestbook'
    spec:
      project: default
      source:
        repoURL: https://github.com/argoproj/guestbook
        path: helm
        targetRevision: HEAD
      destination:
        server: '{{url}}'
        namespace: guestbook

The controller processes the list elements and generates two separate Application objects, substituting {{cluster}} and {{url}} with the respective values.

Progressive Sync with Rolling Strategy

To enable phased rollouts across multiple applications, configure the progressiveSync field and ensure the controller runs with --enable-progressive-syncs:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: rolling-demo
spec:
  syncPolicy:
    syncOptions:
    - CreateNamespace=true
  progressiveSync:
    steps:
    - pause: {}
    - sync: {}
  generators:
  - git:
      repoURL: https://github.com/example/applications
      revision: main
      directories:
      - path: '*'
  template:
    metadata:
      name: '{{path.basename}}'
    spec:
      project: default
      source:
        repoURL: https://github.com/example/applications
        targetRevision: main
        path: '{{path}}'
      destination:
        server: https://kubernetes.default.svc
        namespace: default

This configuration pauses before syncing each application discovered in the Git repository, allowing for manual verification or automated checks between steps.

Running the Controller Locally

For development or debugging outside of cluster deployments, execute the controller directly with specific flags:


# Start the controller inside the cluster (usually launched by the Helm chart)

argocd-applicationset-controller \
  --loglevel info \
  --concurrent-application-updates 5 \
  --enable-progressive-syncs \
  --metrics-addr :8080

This command exposes metrics on port 8080 and limits concurrent updates to five applications to prevent API server throttling.

Summary

  • The Argo CD ApplicationSet controller automates the creation and management of multiple Application resources from a single declarative specification, turning high-level descriptions into concrete Argo CD applications.
  • It implements a reconcile loop in applicationset/controllers/applicationset_controller.go that generates applications via pluggable generators, validates them against project and destination constraints, and reconciles cluster state.
  • The controller supports advanced rollout strategies through progressive sync, managed via the applicationset/progressivesync package, when enabled with the --enable-progressive-syncs flag.
  • It handles resource ownership through Kubernetes owner references and finalizers to ensure safe deletion and prevent orphaned resources.
  • Deployed as the argocd-applicationset-controller binary with dedicated RBAC, it operates independently from the main Argo CD server and exposes metrics via ApplicationsetMetrics.

Frequently Asked Questions

What is the difference between Application and ApplicationSet in Argo CD?

An Application is a single deployable unit targeting one specific cluster and source repository, while an ApplicationSet is a parent resource that generates and manages multiple Application objects across clusters or environments. The ApplicationSet controller watches the ApplicationSet CR and reconciles the desired state of the underlying Application fleet, enabling template-based multi-cluster deployments.

How does the ApplicationSet controller handle application deletion?

When an ApplicationSet is deleted, the controller uses Kubernetes owner references to ensure all generated Application resources are garbage collected. Additionally, the removeFinalizerOnInvalidDestination function in applicationset_controller.go removes finalizers from applications when their target clusters become unreachable, preventing deletion deadlocks and ensuring clean resource removal.

What generators are available in the Argo CD ApplicationSet controller?

The controller supports multiple generators defined in applicationset/generators/, including the List generator (for static parameter sets), Git generator (for directories or files in repositories), Cluster generator (for discovered clusters from secrets), and SCM generator (for pull requests in source control providers). Each generator produces parameter sets that feed into the Application template rendering process.

Is progressive sync production-ready in Argo CD?

Progressive sync remains an experimental feature as implemented in the applicationset/progressivesync package. It requires explicitly enabling the --enable-progressive-syncs flag on the argocd-applicationset-controller binary and defining rollout steps in the spec.progressiveSync field. Check the official Argo CD documentation and release notes for current maturity status before deploying in production environments.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →