🧠 The Concept (Explain Like I'm 5)
- Application (One Toy Box): An ArgoCD
Application deploys one microservice to one cluster. If you have 50 clusters and 200 microservices, creating 10,000 Application files by hand is impossible.
- ApplicationSet (The Toy Factory Matrix): An
ApplicationSet is a generator. You write one 20-line template that says: "For every cluster in my company, deploy these 10 core tools automatically." When an engineer connects cluster #51, all 10 tools deploy instantly with zero manual YAML!
- Crossplane vs. Terraform (Continuous Loop vs. One-Time Run):
- Terraform: Like baking a cake. You follow the recipe, bake it, and you're done. If someone eats half the cake 2 hours later, Terraform doesn't know until you run
terraform plan next week.
- Crossplane: Like a thermostat. You set the temperature to 72°F. If someone opens a window (manual AWS Console edit), the thermostat detects the cold air and automatically turns on the heater to push it back to 72°F (Continuous Reconciliation Loop).
🏢 The Enterprise Context
- ApplicationSet Generators: Supports Git Directory generators, Cluster generators, and Matrix generators (e.g. combining a list of 50 clusters with a list of 10 microservices to generate 500 applications dynamically).
- Crossplane vs. Terraform Trade-offs:
| Dimension |
HashiCorp Terraform |
Crossplane (Kubernetes Control Plane) |
| Execution Model |
Discrete, triggered by human or CI/CD pipeline |
Continuous 24/7 reconciliation loop ($k8s$ controller pattern) |
| State Storage |
terraform.tfstate in S3 / DynamoDB lock |
Stored natively in Kubernetes etcd as Custom Resources |
| Drift Management |
Detects drift only during terraform plan |
Automatically corrects drift immediately upon detection |
| API Interface |
HashiCorp Configuration Language (HCL) |
Native Kubernetes YAML / OpenAPI |
| Role in Platform |
Excellent for Day-0 Landing Zones & VPCs |
Superior for Day-2 Developer Self-Service Claims |
🗺️ Visual Architecture: The ApplicationSet Matrix Generator Flow
flowchart TD
GitClusters["<b>Cluster Discovery Generator</b><br/>• Cluster: prod-us-east-1<br/>• Cluster: prod-eu-west-1<br/>• Cluster: prod-ap-southeast-1"]
GitApps["<b>Git Directory Generator</b><br/>• Service: payment-api<br/>• Service: order-api<br/>• Service: auth-api"]
Matrix["<b>ArgoCD ApplicationSet (Matrix Generator)</b><br/>Cross-Multiplies: 3 Clusters × 3 Services = 9 Apps"]
subgraph GeneratedApps ["Dynamically Generated ArgoCD Applications"]
A1["App: payment-api on prod-us-east-1"]
A2["App: payment-api on prod-eu-west-1"]
A3["App: payment-api on prod-ap-southeast-1"]
A4["App: order-api on prod-us-east-1"]
A5["... Remaining 5 Applications"]
end
GitClusters --> Matrix
GitApps --> Matrix
Matrix --> GeneratedApps
💻 Production Code: ArgoCD Matrix ApplicationSet Manifest
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: fleet-monitoring-deployer
namespace: argocd
spec:
generators:
- matrix:
generators:
# Generator 1: Discover all production clusters registered with ArgoCD
- clusters:
selector:
matchLabels:
environment: production
# Generator 2: Discover monitoring components from Git folders
- git:
repoURL: https://github.com/my-org/gitops-platform.git
revision: HEAD
directories:
- path: platform-tools/*
template:
metadata:
name: '{{name}}-{{path.basename}}'
spec:
project: default
source:
repoURL: https://github.com/my-org/gitops-platform.git
targetRevision: HEAD
path: '{{path}}'
destination:
server: '{{server}}' # Injected dynamically per cluster
namespace: '{{path.basename}}'
syncPolicy:
automated:
prune: true
selfHeal: true