Skip to content

ArgoCD ApplicationSet

KSail’s ArgoCD bootstrap creates a single Application CR that syncs manifests from a local OCI registry. ApplicationSet extends this by generating multiple Applications from a single template β€” useful for multi-environment deployments, multi-tenant clusters, and directory-based project structures.

Initialize a KSail project with ArgoCD as the GitOps engine:

Terminal window
ksail cluster init --gitops-engine ArgoCD
ksail cluster create

This scaffolds a ksail.yaml with spec.cluster.gitOpsEngine: ArgoCD and creates the cluster with:

  • ArgoCD installed via Helm
  • A bootstrap Application CR named ksail pointing to the local OCI registry
  • Automated sync, pruning, and self-healing enabled

During ksail cluster create, KSail creates a single Application that syncs everything in the k8s/ source directory:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: ksail
namespace: argocd
spec:
project: default
source:
repoURL: oci://<registry>/<project>
targetRevision: dev
path: "."
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

You can add ApplicationSet manifests to your source directory to generate additional Applications alongside the bootstrap one.

The directory generator creates one Application per subdirectory in a given path. This is useful for managing multiple independent workloads from a monorepo layout.

my-app/
β”œβ”€β”€ ksail.yaml # gitOpsEngine: ArgoCD
β”œβ”€β”€ k8s/
β”‚ β”œβ”€β”€ kustomization.yaml
β”‚ β”œβ”€β”€ applicationset.yaml # ApplicationSet manifest
β”‚ └── apps/
β”‚ β”œβ”€β”€ frontend/
β”‚ β”‚ β”œβ”€β”€ deployment.yaml
β”‚ β”‚ └── service.yaml
β”‚ β”œβ”€β”€ backend/
β”‚ β”‚ β”œβ”€β”€ deployment.yaml
β”‚ β”‚ └── service.yaml
β”‚ └── monitoring/
β”‚ β”œβ”€β”€ deployment.yaml
β”‚ └── service.yaml

Create k8s/applicationset.yaml:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: apps
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- git:
repoURL: oci://<registry>/<project>
revision: dev
directories:
- path: apps/*
template:
metadata:
name: "{{.path.basename}}"
spec:
project: default
source:
repoURL: oci://<registry>/<project>
targetRevision: dev
path: "{{.path.path}}"
destination:
server: https://kubernetes.default.svc
namespace: "{{.path.basename}}"
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

This generates three Applications (frontend, backend, monitoring), each deployed to its own namespace.

Add the ApplicationSet to your kustomization and push:

Terminal window
ksail workload push
ksail workload reconcile

The git generator can also use config.json files in each directory to pass parameters to the template. This enables per-application configuration without duplicating manifests.

my-app/
β”œβ”€β”€ ksail.yaml
β”œβ”€β”€ k8s/
β”‚ β”œβ”€β”€ kustomization.yaml
β”‚ β”œβ”€β”€ applicationset.yaml
β”‚ └── envs/
β”‚ β”œβ”€β”€ dev/
β”‚ β”‚ └── config.json
β”‚ β”œβ”€β”€ staging/
β”‚ β”‚ └── config.json
β”‚ └── production/
β”‚ └── config.json

Each config.json contains environment-specific parameters:

{
"env": "dev",
"namespace": "app-dev",
"replicas": 1
}
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: multi-env
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- git:
repoURL: oci://<registry>/<project>
revision: dev
files:
- path: envs/*/config.json
template:
metadata:
name: "app-{{.env}}"
spec:
project: default
source:
repoURL: oci://<registry>/<project>
targetRevision: dev
path: "envs/{{.env}}"
destination:
server: https://kubernetes.default.svc
namespace: "{{.namespace}}"
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true

KSail’s tenant management generates ArgoCD AppProject and Application resources per tenant. You can replace per-tenant Applications with a single ApplicationSet that auto-discovers tenant directories:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: tenants
namespace: argocd
spec:
goTemplate: true
goTemplateOptions: ["missingkey=error"]
generators:
- git:
repoURL: oci://<registry>/<project>
revision: dev
directories:
- path: tenants/*
template:
metadata:
name: "tenant-{{.path.basename}}"
spec:
project: "{{.path.basename}}"
source:
repoURL: oci://<registry>/<project>
targetRevision: dev
path: "{{.path.path}}"
destination:
server: https://kubernetes.default.svc
namespace: "{{.path.basename}}"
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
  • Inspect the bootstrap Application to get the correct repoURL and targetRevision values for your ApplicationSet templates:

    Terminal window
    ksail workload get application ksail -n argocd -o yaml
  • Use ksail workload push and ksail workload reconcile to deploy ApplicationSet manifests β€” they flow through the same OCI push pipeline as regular manifests.

  • Combine with multi-environment workflows by using separate ksail.<env>.yaml configs and ApplicationSet generators. See Multi-Environment Workflows for the --config pattern.