Skip to content

ArgoCD App of Apps pattern

Kubernetes · GitOps
Studied

Problem

The cluster runs 30–50 applications: ingress-nginx, cert-manager, prometheus, product apps. Each ArgoCD Application is created by hand with kubectl apply or Helm, syncing is opaque, and it's easy to forget one. Onboarding a new cluster turns into a checklist of 40 kubectl apply commands.

Solution

The Argo CD docs describe the app of apps pattern as: "declaratively specify one Argo CD app that consists only of other apps". One root Application points to a Git directory that holds the manifests of the other Applications. ArgoCD picks up the root, then the children, and the children pick up the workloads. The state of the whole cluster lives in one repository and is deployed with a single kubectl apply of the root manifest.

Example

Layout of the argocd-apps/ repo:

argocd-apps/
├── root.yaml                     # The single entry point
└── apps/
    ├── ingress-nginx.yaml
    ├── cert-manager.yaml
    ├── prometheus.yaml
    └── app-product.yaml

root.yaml — the only manifest you apply by hand:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: root
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/acme/argocd-apps.git
    targetRevision: HEAD
    path: apps
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

apps/ingress-nginx.yaml — a typical child Application:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: ingress-nginx
  namespace: argocd
spec:
  project: default
  source:
    chart: ingress-nginx
    repoURL: https://kubernetes.github.io/ingress-nginx
    targetRevision: 4.11.3
    helm:
      valueFiles: [values.yaml]
  destination:
    server: https://kubernetes.default.svc
    namespace: ingress-nginx
  syncPolicy:
    automated: { prune: true, selfHeal: true }
    syncOptions: [CreateNamespace=true]

Onboarding a new cluster is now:

kubectl apply -f root.yaml
# That's it. ArgoCD creates the remaining 40 applications itself.

When to use

  • More than one cluster (staging + prod) and reproducibility matters.
  • More than ten applications per cluster.
  • The team wants to see cluster state in Git rather than via kubectl get all.

Source

How to apply it yourself

  1. Create a separate argocd-apps repository (or a directory in the infra monorepo).
  2. Move all existing Applications there.
  3. Write root.yaml pointing to the directory with the children.
  4. Apply the root by hand once.
  5. Make sure adding a new application = one PR to the repo, no manual kubectl. After that — status Studied.