Module 04

ApplicationSets & Multi-Cluster

One template, many applications -- scaling GitOps across environments and clusters

Use arrow keys or click sides to navigate

The Problem

Copy-Paste Fatigue

Your team manages 12 microservices across 3 environments and 2 AKS clusters. That is 72 Application manifests. Every new service means copying YAML, changing fields, and hoping for no typos. There has to be a better way.

There is. It is called ApplicationSets.

What is an ApplicationSet?

An ApplicationSet is a template that automatically generates multiple ArgoCD Applications from a single definition.

ApplicationSet Template
App: frontend-dev
App: frontend-staging
App: frontend-prod

Analogy: If an Application is a single document, an ApplicationSet is a mail merge -- one template plus a data source produces many personalized documents.

ApplicationSet Anatomy

apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: frontend-apps namespace: argocd spec: generators: # Data source: where do parameters come from? - list: elements: [...] template: # Application template: what does each app look like? metadata: name: '{{name}}' spec: project: default source: repoURL: https://github.com/org/manifests.git targetRevision: '{{branch}}' path: '{{path}}' destination: server: '{{cluster}}' namespace: '{{namespace}}'

The List Generator

The simplest generator -- you explicitly list parameters for each Application.

spec: generators: - list: elements: - env: dev cluster: https://kubernetes.default.svc values: values-dev.yaml - env: staging cluster: https://kubernetes.default.svc values: values-staging.yaml - env: prod cluster: https://aks-prod.eastus.azmk8s.io values: values-prod.yaml template: metadata: name: 'frontend-{{env}}' spec: source: repoURL: https://github.com/org/frontend.git path: deploy/helm helm: valueFiles: ['{{values}}'] destination: server: '{{cluster}}' namespace: 'frontend-{{env}}'

The Git Directory Generator

Automatically creates an Application for every directory matching a pattern in your Git repo.

spec: generators: - git: repoURL: https://github.com/org/manifests.git revision: main directories: - path: apps/* # Match all dirs under apps/ - path: apps/excluded # Optionally exclude exclude: true template: metadata: name: '{{path.basename}}' # e.g., "frontend", "backend" spec: source: repoURL: https://github.com/org/manifests.git targetRevision: main path: '{{path}}' # e.g., "apps/frontend" destination: server: https://kubernetes.default.svc namespace: '{{path.basename}}'

Magic: Add a new directory under apps/ in Git and ArgoCD automatically creates a new Application. Delete the directory and the Application is removed.

Quiz Time

Generator Basics

1. What problem do ApplicationSets solve?

Correct! ApplicationSets use a template + generator pattern to automatically produce many Application resources from a single definition.

2. In the Git directory generator, what does {{path.basename}} resolve to?

Correct! {{path.basename}} is the last component of the matched directory path. For path "apps/frontend", basename is "frontend".

3. With the Git directory generator, what happens when you add a new directory to Git?

Correct! The Git directory generator watches for directory changes. Adding a new directory that matches the pattern automatically generates a new Application.

The Git File Generator

Reads JSON or YAML files from Git and uses their content as template parameters.

# config/dev.json in your Git repo: # { "env": "dev", "replicas": 2, "domain": "dev.example.com" } # config/prod.json in your Git repo: # { "env": "prod", "replicas": 5, "domain": "example.com" } spec: generators: - git: repoURL: https://github.com/org/config.git revision: main files: - path: "config/*.json" # Read all JSON files template: metadata: name: 'myapp-{{env}}' spec: source: repoURL: https://github.com/org/manifests.git path: deploy helm: parameters: - name: replicas value: '{{replicas}}' - name: domain value: '{{domain}}' destination: server: https://kubernetes.default.svc namespace: 'myapp-{{env}}'

The Cluster Generator

Creates an Application for every cluster registered in ArgoCD -- or clusters matching labels.

spec: generators: - clusters: selector: matchLabels: env: production # Only clusters with this label template: metadata: name: 'monitoring-{{name}}' # {{name}} = cluster name spec: source: repoURL: https://github.com/org/monitoring.git targetRevision: main path: deploy destination: server: '{{server}}' # {{server}} = cluster URL namespace: monitoring

Power move: Register a new AKS cluster and label it env: production. The ApplicationSet automatically deploys your monitoring stack to it. Zero manual work.

Cluster Labels

# Add labels when registering a cluster argocd cluster add my-aks-cluster \ --label env=production \ --label region=eastus \ --label tier=premium # Or add labels to an existing cluster secret kubectl -n argocd label secret aks-prod-cluster \ env=production region=eastus tier=premium # Use labels in the cluster generator generators: - clusters: selector: matchLabels: env: production region: eastus

Labels on cluster secrets let you target subsets of clusters. Deploy monitoring to all clusters, but a special config only to production clusters in East US.

The Matrix Generator

Combines two generators by computing their Cartesian product.

spec: generators: - matrix: generators: # Generator 1: clusters - clusters: selector: matchLabels: env: production # Generator 2: git directories (services) - git: repoURL: https://github.com/org/services.git revision: main directories: - path: services/* template: metadata: name: '{{path.basename}}-{{name}}' # e.g., "api-aks-prod-eastus" spec: source: repoURL: https://github.com/org/services.git path: '{{path}}' destination: server: '{{server}}' namespace: '{{path.basename}}'

Result: Every service directory x every production cluster = an Application. 5 services x 3 clusters = 15 Applications from one template.

Quiz Time

Advanced Generators

1. What does the Matrix generator produce?

Correct! The Matrix generator computes the Cartesian product. If generator A produces 3 items and B produces 5 items, the result is 3 x 5 = 15 Applications.

2. Which generator reads JSON/YAML files from a Git repo as parameter sources?

Correct! The Git file generator reads JSON or YAML files from a Git repository and uses their key-value pairs as template parameters.

3. What happens when you register a new cluster with label env: production and a cluster generator selects that label?

Correct! The cluster generator dynamically watches for cluster secrets. When a new cluster with matching labels appears, it automatically generates Applications.

The Merge Generator

Combines generators by merging parameters from matched entries, not Cartesian product.

spec: generators: - merge: mergeKeys: - env # Match on 'env' field generators: # Base generator: defaults for all environments - list: elements: - env: dev replicas: "1" domain: dev.example.com - env: prod replicas: "5" domain: example.com # Override generator: prod gets extra settings - list: elements: - env: prod replicas: "10" # Override replicas for prod ha: "true"

Use case: Define defaults in one generator and environment-specific overrides in another. The merge generator combines them based on a key field.

Multi-Cluster on AKS

Your organization has three AKS clusters: dev in West Europe, staging in North Europe, and production in East US. You run a single ArgoCD instance in the dev cluster and manage all three from there. Platform services like monitoring and ingress controllers are deployed everywhere; application workloads go only to their designated cluster.

ArgoCD (aks-dev)
manages
aks-dev
aks-staging
aks-prod

Registering AKS Clusters

# Ensure you have kubeconfig contexts for all clusters az aks get-credentials --name aks-dev --resource-group rg-dev az aks get-credentials --name aks-staging --resource-group rg-staging az aks get-credentials --name aks-prod --resource-group rg-prod # Register each cluster with ArgoCD argocd cluster add aks-dev \ --label env=dev --label region=westeurope argocd cluster add aks-staging \ --label env=staging --label region=northeurope argocd cluster add aks-prod \ --label env=prod --label region=eastus # Verify argocd cluster list

Hub-and-Spoke Architecture

Hub Cluster

Runs ArgoCD and manages all other clusters. Typically your dev or management cluster.

  • Single ArgoCD installation
  • Central dashboard for all clusters
  • One place for RBAC and SSO

Spoke Clusters

Receive deployments from the hub. Only need a ServiceAccount for ArgoCD.

  • No ArgoCD installation needed
  • Minimal permissions required
  • Can be added/removed dynamically

AKS consideration: Use Azure Private Link or VNet peering to ensure the hub cluster can reach spoke cluster API servers securely.

Quiz Time

Multi-Cluster Knowledge

1. In a hub-and-spoke ArgoCD architecture, where is ArgoCD installed?

Correct! In hub-and-spoke, ArgoCD runs only on the hub cluster and manages all spoke clusters remotely via their Kubernetes API servers.

2. How does the Merge generator differ from the Matrix generator?

Correct! The Merge generator joins entries from multiple generators by matching on specified key fields, while the Matrix generator produces the Cartesian product of all entries.

3. What do spoke clusters need for ArgoCD to manage them?

Correct! Spoke clusters only need a ServiceAccount (created by argocd cluster add) that gives ArgoCD permissions to manage resources. No ArgoCD installation is needed.

Progressive Rollout Strategy

Deploy to environments sequentially using ApplicationSet with strategy.

spec: strategy: type: RollingSync rollingSync: steps: - matchExpressions: - key: env operator: In values: - dev - matchExpressions: - key: env operator: In values: - staging maxUpdate: 100% # Sync all staging at once - matchExpressions: - key: env operator: In values: - prod maxUpdate: 1 # Sync prod one at a time

Progressive delivery: Deploy to dev first, then staging, then prod one cluster at a time. If any step fails, the rollout stops.

ApplicationSet Policies

spec: # What happens when an ApplicationSet is deleted? syncPolicy: preserveResourcesOnDeletion: true # Keep apps when AppSet is deleted # What happens when a generated app is removed from the generator? # (e.g., a directory is deleted from Git) generators: - git: repoURL: ... directories: - path: apps/* # Control Application updates template: metadata: annotations: # Prevent ApplicationSet from overwriting manual app changes argocd.argoproj.io/managed-by: ""

Safety net: preserveResourcesOnDeletion: true ensures that deleting an ApplicationSet does not cascade-delete all generated Applications and their resources. Always set this in production.

Template Overrides

spec: generators: - list: elements: - env: dev cluster: https://kubernetes.default.svc - env: prod cluster: https://aks-prod.eastus.azmk8s.io # Per-element template override template: spec: syncPolicy: automated: prune: false # Override: no auto-prune for prod template: metadata: name: 'app-{{env}}' spec: syncPolicy: automated: prune: true # Default: auto-prune enabled selfHeal: true

Each generator element can override parts of the template. This lets you have different sync policies per environment.

Real-World Example

Platform Services Across All Clusters

apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: platform-services namespace: argocd spec: generators: - matrix: generators: - clusters: {} # ALL registered clusters - git: repoURL: https://github.com/org/platform.git revision: main directories: - path: services/* template: metadata: name: '{{path.basename}}-{{name}}' spec: project: platform source: repoURL: https://github.com/org/platform.git targetRevision: main path: '{{path}}' destination: server: '{{server}}' namespace: '{{path.basename}}' syncPolicy: automated: { prune: true, selfHeal: true } syncOptions: [CreateNamespace=true]
Quiz Time

ApplicationSet Mastery

1. What does preserveResourcesOnDeletion: true do?

Correct! This prevents cascade deletion of generated Applications when the ApplicationSet itself is deleted. Essential for production safety.

2. In the RollingSync strategy, what does maxUpdate: 1 mean?

Correct! maxUpdate: 1 means only one Application in that step group is synced at a time. This enables canary-style progressive rollouts across clusters.

3. Which generator combination would deploy every microservice to every production cluster?

Correct! The Matrix generator creates the Cartesian product: every matched cluster x every matched directory = an Application per service per cluster.
Summary

Module 04 Recap

Next up: Module 05 -- Advanced Patterns and Operations

Module 04 Complete

You can now scale ArgoCD across any number of services and clusters

Continue to Module 05 for advanced patterns and operational excellence

← Back