Resources
1Install
npx skillscat add julianobarbosa/claude-code-skills/skills-argocd-applicationset-skill Install via the SkillsCat registry.
ArgoCD ApplicationSet Skill
Comprehensive guide for implementing, configuring, and operating ArgoCD ApplicationSet - the powerful Kubernetes controller that automates Argo CD Application generation for multi-cluster, multi-tenant, and GitOps deployments.
ArgoCD Version: 2.9+ (ApplicationSet is built-in since v2.3)
API Version: argoproj.io/v1alpha1
Overview
ApplicationSet is a Kubernetes controller that adds support for the ApplicationSet CustomResourceDefinition (CRD), enabling:
- Multi-Cluster Deployment: Deploy applications across multiple Kubernetes clusters from a single manifest
- Monorepo Support: Generate applications from directory structures or configuration files in Git
- Multi-Tenant Self-Service: Allow developers to create Applications without cluster-admin intervention
- GitOps Automation: Automatically create, update, and delete Argo CD Applications based on generators
Quick Reference
| Resource | Path |
|---|---|
| Generator Examples | references/generators/ |
| Template Patterns | references/templates/ |
| Common Patterns | references/patterns/ |
| Troubleshooting | references/troubleshooting/ |
1. ApplicationSet Structure
Basic Structure
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: my-applicationset
namespace: argocd
spec:
# Generators produce parameters for templates
generators:
- list:
elements:
- cluster: dev
url: https://dev.example.com
- cluster: prod
url: https://prod.example.com
# Template defines the Application to create
template:
metadata:
name: '{{.cluster}}-myapp'
spec:
project: default
source:
repoURL: https://github.com/org/repo.git
targetRevision: HEAD
path: apps/myapp
destination:
server: '{{.url}}'
namespace: myapp
# Optional: Sync policy for application lifecycle
syncPolicy:
preserveResourcesOnDeletion: false
applicationsSync: sync
# Optional: Enable Go templating (recommended)
goTemplate: true
goTemplateOptions: ["missingkey=error"]Key Fields
| Field | Description | Required |
|---|---|---|
generators |
List of generators that produce parameters | Yes |
template |
Application template with parameter placeholders | Yes |
syncPolicy |
Controls application creation/update/deletion behavior | No |
goTemplate |
Enable Go text templating (recommended) | No |
goTemplateOptions |
Go template parsing options | No |
strategy |
Progressive sync strategy (RollingSync) | No |
preservedFields |
Fields to preserve during updates | No |
ignoreApplicationDifferences |
Fields to ignore during comparison | No |
2. Generators
Generators produce parameters that are substituted into the ApplicationSet template. Multiple generators can be combined.
2.1 List Generator
Creates applications from a fixed list of key/value pairs.
generators:
- list:
elements:
- cluster: engineering-dev
url: https://kubernetes.default.svc
environment: development
- cluster: engineering-prod
url: https://prod.example.com
environment: productionUse Cases:
- Fixed set of deployment targets
- Environment-specific configurations
- Simple multi-cluster deployments
2.2 Cluster Generator
Automatically discovers clusters registered in Argo CD.
generators:
- clusters:
# Select all clusters
selector: {}
# Or filter by labels
selector:
matchLabels:
environment: production
matchExpressions:
- key: region
operator: In
values:
- us-east
- us-west
# Pass additional values
values:
revision: HEAD
helmValues: productionGenerated Parameters:
{{.name}}- Cluster name{{.nameNormalized}}- DNS-safe cluster name{{.server}}- Cluster API server URL{{.metadata.labels.<key>}}- Cluster labels{{.metadata.annotations.<key>}}- Cluster annotations
Including Local Cluster:
The local cluster (in-cluster) doesn't have a Secret by default. To include it in label selectors, edit the cluster in Argo CD UI to create its Secret.
2.3 Git Generator - Directory
Generates applications based on directory structure in a Git repository.
generators:
- git:
repoURL: https://github.com/org/gitops-repo.git
revision: HEAD
directories:
# Include all directories under clusters/
- path: clusters/*
# Exclude specific directories
- path: clusters/deprecated/*
exclude: trueGenerated Parameters:
{{.path.path}}- Full directory path (e.g.,clusters/dev){{.path.basename}}- Directory name (e.g.,dev){{.path.basenameNormalized}}- DNS-safe directory name{{index .path.segments N}}- Path segment at index N
2.4 Git Generator - File
Generates applications from JSON/YAML configuration files.
generators:
- git:
repoURL: https://github.com/org/gitops-repo.git
revision: HEAD
files:
- path: "config/**/config.json"Example config.json:
{
"cluster": {
"owner": "team-a",
"name": "production",
"address": "https://prod.example.com"
},
"app": {
"name": "myapp",
"namespace": "default"
}
}Generated Parameters:
- All JSON fields are flattened:
{{.cluster.name}},{{.app.namespace}} - Path parameters:
{{.path.path}},{{.path.basename}},{{.path.filename}}
2.5 Matrix Generator
Combines two generators, creating every permutation of their outputs.
generators:
- matrix:
generators:
# First generator: Git directories (apps)
- git:
repoURL: https://github.com/org/apps.git
revision: HEAD
directories:
- path: apps/*
# Second generator: Clusters
- clusters:
selector:
matchLabels:
environment: productionResult: If Git finds 3 apps and Cluster finds 2 clusters, Matrix produces 6 Applications.
Restrictions:
- Maximum 2 child generators
- Only 1 level of nesting (no nested Matrix within Matrix)
- Child generators cannot have template overrides
2.6 Merge Generator
Merges parameters from multiple generators using merge keys.
generators:
- merge:
mergeKeys:
- cluster
generators:
# Base generator: All clusters
- clusters:
values:
helmValues: default
# Override for specific clusters
- clusters:
selector:
matchLabels:
environment: production
values:
helmValues: production
# Exception for specific cluster
- list:
elements:
- cluster: special-cluster
helmValues: customOverride Precedence: Bottom-to-top (later generators override earlier ones)
2.7 SCM Provider Generator
Discovers repositories from SCM platforms (GitHub, GitLab, Azure DevOps, Bitbucket).
generators:
- scmProvider:
# GitHub Organization
github:
organization: myorg
tokenRef:
secretName: github-token
key: token
allBranches: false
# Filter repositories
filters:
- repositoryMatch: ^microservice-.*
- pathsExist:
- kubernetes/
- labelMatch: deploy-enabled
cloneProtocol: https
requeueAfterSeconds: 300Azure DevOps Configuration:
generators:
- scmProvider:
azureDevOps:
organization: myorg
teamProject: MyProject
accessTokenRef:
secretName: azure-devops-token
key: token
allBranches: true
filters:
- repositoryMatch: ^app-.*Generated Parameters:
{{.organization}}- Organization/owner name{{.repository}}- Repository name{{.url}}- Clone URL{{.branch}}- Branch name{{.sha}}- Commit SHA{{.short_sha}}- Short commit SHA{{.labels}}- Repository labels/topics
2.8 Pull Request Generator
Generates applications for open pull requests.
generators:
- pullRequest:
github:
owner: myorg
repo: myrepo
tokenRef:
secretName: github-token
key: token
labels:
- preview
requeueAfterSeconds: 300Azure DevOps Configuration:
generators:
- pullRequest:
azuredevops:
organization: myorg
project: MyProject
repo: myrepo
tokenRef:
secretName: azure-devops-token
key: tokenGenerated Parameters:
{{.number}}- PR number{{.branch}}- Source branch name{{.branch_slug}}- DNS-safe branch name{{.target_branch}}- Target branch{{.head_sha}}- Head commit SHA{{.head_short_sha}}- Short head SHA{{.author}}- PR author{{.title}}- PR title
2.9 Plugin Generator
Custom generator using external RPC HTTP requests.
generators:
- plugin:
configMapRef:
name: my-plugin
input:
parameters:
key1: value1
requeueAfterSeconds: 3003. Templates
3.1 Basic Template
template:
metadata:
name: '{{.cluster}}-{{.app}}'
labels:
app: '{{.app}}'
environment: '{{.environment}}'
annotations:
notifications.argoproj.io/subscribe.on-sync-failed.slack: alerts
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: '{{.repoURL}}'
targetRevision: '{{.revision}}'
path: '{{.path}}'
destination:
server: '{{.url}}'
namespace: '{{.namespace}}'
syncPolicy:
automated:
prune: true
selfHeal: true3.2 Multi-Source Template
Combine Helm charts with external values files.
template:
metadata:
name: '{{.cluster}}-{{.app}}'
spec:
project: default
sources:
# Source 1: Helm chart from public repository
- chart: '{{.chart}}'
repoURL: '{{.chartRepo}}'
targetRevision: '{{.chartVersion}}'
helm:
releaseName: '{{.app}}'
valueFiles:
- $values/{{.valuesPath}}/values.yaml
# Source 2: Values from Git repository
- repoURL: '{{.valuesRepo}}'
targetRevision: '{{.valuesRevision}}'
ref: values
destination:
server: '{{.url}}'
namespace: '{{.namespace}}'3.3 Generator-Level Template Override
Override specific template fields per generator.
generators:
- list:
elements:
- cluster: dev
url: https://dev.example.com
# Override for this generator only
template:
spec:
source:
targetRevision: develop
- list:
elements:
- cluster: prod
url: https://prod.example.com
template:
spec:
source:
targetRevision: main
# Base template (can be overridden)
template:
metadata:
name: '{{.cluster}}-myapp'
spec:
project: default
source:
repoURL: https://github.com/org/repo.git
targetRevision: HEAD # Overridden by generator templates
path: apps/myapp
destination:
server: '{{.url}}'
namespace: myapp3.4 Template Patch (Advanced)
For non-string fields, use templatePatch with Go templating.
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- list:
elements:
- cluster: dev
replicas: 1
- cluster: prod
replicas: 3
template:
metadata:
name: '{{.cluster}}-myapp'
spec:
project: default
source:
repoURL: https://github.com/org/repo.git
path: apps/myapp
destination:
server: '{{.url}}'
templatePatch: |
spec:
source:
helm:
parameters:
- name: replicas
value: "{{.replicas}}"4. Go Templating
Enable Go templating for advanced functionality.
4.1 Configuration
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"] # Recommended: fail on undefined4.2 Available Functions
Sprig Functions (except env, expandenv, getHostByName):
- String:
lower,upper,trim,replace,contains,hasPrefix,hasSuffix - Lists:
list,first,last,index,slice - Math:
add,sub,mul,div - Date:
now,date,dateModify - Crypto:
sha256sum,b64enc,b64dec
Custom Functions:
normalize- Sanitize to DNS-compliant name (lowercase, alphanumeric, hyphens, dots)slugify- Smart truncation without cutting wordstoYaml/fromYaml/fromYamlArray- YAML conversion
4.3 Common Patterns
# Conditional with default
name: '{{.cluster}}{{dig "suffix" "" .}}'
# String manipulation
name: '{{ .cluster | lower | replace "_" "-" }}'
# Index access for labels with special characters
env: '{{ index .metadata.labels "env-type" }}'
# Conditional logic
{{- if eq .environment "production" }}
replicas: 3
{{- else }}
replicas: 1
{{- end }}
# List iteration (in templatePatch)
{{- range .namespaces }}
- namespace: {{ . }}
{{- end }}4.4 Migration from FastTemplate
| FastTemplate | Go Template |
|---|---|
{{ value }} |
{{ .value }} |
{{ path }} |
{{ .path.path }} |
{{ path.basename }} |
{{ .path.basename }} |
{{ path[0] }} |
{{ index .path.segments 0 }} |
{{ metadata.labels.my-label }} |
{{ index .metadata.labels "my-label" }} |
5. Sync Policies
5.1 Application Sync Policy
Control how generated Applications are synced.
spec:
syncPolicy:
# Prevent deletion of child resources when ApplicationSet is deleted
preserveResourcesOnDeletion: true
# Control application lifecycle: sync, create-only, create-update, create-delete
applicationsSync: syncapplicationsSync Options:
| Value | Create | Update | Delete |
|---|---|---|---|
sync (default) |
Yes | Yes | Yes |
create-only |
Yes | No | No |
create-update |
Yes | Yes | No |
create-delete |
Yes | No | Yes |
5.2 Progressive Syncs (Rolling Updates)
Deploy applications in controlled stages.
spec:
# Enable progressive syncs (requires controller flag)
strategy:
type: RollingSync
rollingSync:
steps:
# Step 1: Dev environments first
- matchExpressions:
- key: environment
operator: In
values:
- dev
maxUpdate: 100% # All dev at once
# Step 2: Staging
- matchExpressions:
- key: environment
operator: In
values:
- staging
maxUpdate: 50% # Half at a time
# Step 3: Production (careful rollout)
- matchExpressions:
- key: environment
operator: In
values:
- production
maxUpdate: 1 # One at a timeEnable Progressive Syncs:
# Via environment variable
ARGOCD_APPLICATIONSET_CONTROLLER_ENABLE_PROGRESSIVE_SYNCS=true
# Via ConfigMap
kubectl patch cm argocd-cmd-params-cm -n argocd --type merge -p '{"data":{"applicationsetcontroller.enable.progressive.syncs":"true"}}'6. Ignore Differences
Prevent ApplicationSet from overwriting certain Application fields.
spec:
ignoreApplicationDifferences:
# Ignore replica count changes (for HPA)
- jsonPointers:
- /spec/replicas
# Ignore specific annotations
- jqPathExpressions:
- .metadata.annotations["kubectl.kubernetes.io/last-applied-configuration"]
# Ignore for specific applications only
- name: "prod-*"
jsonPointers:
- /spec/source/targetRevision7. Security Considerations
7.1 Access Control
CRITICAL: Only admins should have permission to create, update, or delete ApplicationSets.
# RBAC Policy - Restrict ApplicationSet access
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
policy.csv: |
# Only admins can manage ApplicationSets
p, role:admin, applicationsets, *, */*, allow
# Developers can only view
p, role:developer, applicationsets, get, */*, allow7.2 Project Field Security
WARNING: If the project field is templated from Git sources, ensure:
- Repository write access is restricted to admins
- PRs require admin approval
- Use non-scoped repositories (blank project in Argo CD)
# DANGEROUS - Project templated from Git
spec:
template:
spec:
project: '{{.project}}' # Could be exploited!
# SAFER - Fixed project
spec:
template:
spec:
project: my-restricted-project7.3 Token Management
Store SCM tokens securely in Kubernetes Secrets.
apiVersion: v1
kind: Secret
metadata:
name: github-token
namespace: argocd
type: Opaque
stringData:
token: ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx8. Common Patterns
8.1 Multi-Cluster Deployment
Deploy to all registered clusters.
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: multi-cluster-app
namespace: argocd
spec:
goTemplate: true
generators:
- clusters:
selector:
matchLabels:
deploy: "true"
template:
metadata:
name: '{{.name}}-myapp'
spec:
project: default
source:
repoURL: https://github.com/org/repo.git
targetRevision: HEAD
path: apps/myapp
destination:
server: '{{.server}}'
namespace: myapp
syncPolicy:
automated:
prune: true
selfHeal: true8.2 Monorepo with Directory Structure
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: monorepo-apps
namespace: argocd
spec:
goTemplate: true
generators:
- git:
repoURL: https://github.com/org/monorepo.git
revision: HEAD
directories:
- path: apps/*
- path: apps/deprecated/*
exclude: true
template:
metadata:
name: '{{.path.basename}}'
spec:
project: default
source:
repoURL: https://github.com/org/monorepo.git
targetRevision: HEAD
path: '{{.path.path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{.path.basename}}'8.3 Preview Environments for Pull Requests
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: pr-preview
namespace: argocd
spec:
goTemplate: true
generators:
- pullRequest:
github:
owner: myorg
repo: myapp
tokenRef:
secretName: github-token
key: token
labels:
- preview
requeueAfterSeconds: 60
template:
metadata:
name: 'preview-{{.number}}'
labels:
app: myapp
pr: '{{.number}}'
spec:
project: previews
source:
repoURL: https://github.com/myorg/myapp.git
targetRevision: '{{.head_sha}}'
path: kubernetes
destination:
server: https://kubernetes.default.svc
namespace: 'preview-{{.number}}'
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true8.4 Helm Chart with Multi-Source Values
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: helm-multi-source
namespace: argocd
spec:
goTemplate: true
generators:
- list:
elements:
- cluster: cafehyna-dev
url: https://dev-cluster.example.com
environment: development
branch: main
- cluster: cafehyna-prod
url: https://prod-cluster.example.com
environment: production
branch: main
template:
metadata:
name: '{{.cluster}}-myapp'
spec:
project: default
sources:
# Helm chart from public repo
- chart: myapp
repoURL: https://charts.example.com
targetRevision: 1.0.0
helm:
releaseName: myapp
valueFiles:
- $values/helm-values/myapp/{{.cluster}}/values.yaml
# Values from Git
- repoURL: https://github.com/org/gitops-values.git
targetRevision: '{{.branch}}'
ref: values
destination:
server: '{{.url}}'
namespace: myapp8.5 App-of-Apps Pattern
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: app-of-apps
namespace: argocd
spec:
goTemplate: true
generators:
- git:
repoURL: https://github.com/org/gitops.git
revision: HEAD
files:
- path: "environments/*/apps.yaml"
template:
metadata:
name: '{{.environment}}-apps'
spec:
project: default
source:
repoURL: https://github.com/org/gitops.git
targetRevision: HEAD
path: 'environments/{{.environment}}'
destination:
server: '{{.cluster.server}}'
namespace: argocd9. Troubleshooting
9.1 Common Issues
| Issue | Cause | Solution |
|---|---|---|
| Applications not created | Generator returns empty results | Check generator filters, verify source data exists |
| Template substitution errors | Missing or undefined parameters | Use goTemplateOptions: ["missingkey=error"] to debug |
| Applications deleted unexpectedly | Generator no longer matches | Check syncPolicy, use preserveResourcesOnDeletion |
| Duplicate applications | Multiple generators produce same name | Add unique prefixes/suffixes to names |
| Rate limiting from SCM | Too frequent polling | Increase requeueAfterSeconds, use webhooks |
9.2 Debug Commands
# Check ApplicationSet status
kubectl get applicationsets -n argocd
# Describe ApplicationSet for events/errors
kubectl describe applicationset <name> -n argocd
# View generated Applications
kubectl get applications -n argocd -l app.kubernetes.io/instance=<appset-name>
# Check ApplicationSet controller logs
kubectl logs -n argocd -l app.kubernetes.io/name=argocd-applicationset-controller -f
# Dry-run to see what would be generated (via argocd CLI)
argocd appset generate <appset.yaml>9.3 Webhook Configuration
Reduce polling by configuring webhooks.
GitHub Webhook:
- URL:
https://argocd.example.com/api/webhook - Content Type:
application/json - Events:
Push,Pull Request - Secret: Configure in
argocd-secret
# argocd-secret
apiVersion: v1
kind: Secret
metadata:
name: argocd-secret
namespace: argocd
stringData:
webhook.github.secret: your-webhook-secret10. Best Practices
Always use Go templating with
goTemplate: trueandgoTemplateOptions: ["missingkey=error"]Use descriptive Application names that include cluster/environment identifiers
Add labels to generated Applications for filtering and grouping
Configure finalizers for proper cleanup:
resources-finalizer.argocd.argoproj.ioUse progressive syncs for production deployments to reduce blast radius
Restrict ApplicationSet RBAC - only admins should create/modify ApplicationSets
Never template the project field from untrusted sources
Use webhooks instead of polling for faster response to changes
Set appropriate requeue intervals to balance responsiveness and API rate limits
Use ignoreApplicationDifferences for fields managed by other controllers (HPA, etc.)
11. Reference Files
Additional templates and examples are in the references/ directory:
Generators:
references/generators/list-generator.yamlreferences/generators/cluster-generator.yamlreferences/generators/git-directory-generator.yamlreferences/generators/git-file-generator.yamlreferences/generators/matrix-generator.yamlreferences/generators/merge-generator.yamlreferences/generators/scm-provider-generator.yamlreferences/generators/pull-request-generator.yaml
Templates:
references/templates/basic-template.yamlreferences/templates/multi-source-template.yamlreferences/templates/helm-values-template.yaml
Patterns:
references/patterns/multi-cluster.yamlreferences/patterns/monorepo.yamlreferences/patterns/preview-environments.yamlreferences/patterns/progressive-rollout.yamlreferences/patterns/azure-devops-integration.yaml
Troubleshooting:
references/troubleshooting/common-issues.mdreferences/troubleshooting/debug-checklist.md
Related Skills
argocd-skill- General ArgoCD operationsgitops-principles-skill- GitOps methodologykargo-skill- Progressive delivery with Kargohelm-skill- Helm chart management