GitOps in groĂem MaĂstab: App of Apps vs. ApplicationSet fĂŒr openDesk
Aktueller Stand: Eine ArgoCD-Application, ein Helmfile, 30+ Dienste, 8 Sync-Phasen. Zielzustand: Eine Multi-Cluster-, Multi-Umgebungs-GitOps-Architektur, die skaliert.
Dieser Beitrag untersucht, wo wir stehen, wohin wir wollen und die beiden wichtigsten ArgoCD-Muster â App of Apps und ApplicationSet â die uns dorthin bringen können.
Wo Wir Heute Stehen
openDesk Edu wird derzeit mit einer monolithischen ArgoCD-Application bereitgestellt, die auf dem Helmfile-Plugin basiert. Eine einzelne Application-Ressource in ArgoCD verweist auf ein Helmfile, das alle 30+ Dienste ĂŒber 8 Sync-Phasen orchestriert:
| Phase | Was bereitgestellt wird |
|---|---|
| 0 | Pre-Deployment-Migrationsjobs |
| 1 | Kerndienste (Home, Zertifikate, Alarme) |
| 2 | Datenbanken, Caches, S3, Mail-Relay |
| 3 | Nubus IAM, Keycloak, Portal |
| 4â5 | Groupware, Apps (Nextcloud, Jitsi, OX, usw.) |
| 6â7 | Bootstrap-Jobs und Post-Migrationen |
Das funktioniert. Der Cluster lĂ€uft, die Dienste sind gesund und Backups werden durchgefĂŒhrt. Aber wĂ€hrend wir skalieren â mehr Umgebungen (Dev/Staging/Prod), mehr Cluster (HRZ, zukĂŒnftige Standorte) und mehr Dienste (6 fehlen noch) â werden die Grenzen einer einzelnen Application deutlich.
Was im GroĂen Bricht
- Einzelner Blast Radius: Eine fehlerhafte Helmfile-Ănderung betrifft jeden Dienst. Es gibt kein schrittweises Rollout.
- Kein Self-Service: Einen Dienst hinzufĂŒgen bedeutet, das zentrale Helmfile zu bearbeiten und auf die Freigabe durch die Betreiber zu warten.
- Langsame Syncs: Die Root-App gleicht alle 30+ Dienste auf einmal ab. Sync-Timeouts und Ressourcenkonflikte sind real.
- Keine dienstspezifische Sync-Richtlinie: Sie können nicht einen Dienst automatisch synchronisieren, wÀhrend Sie einen anderen manuell promoten. Es ist alles oder nichts.
- Keine Umgebungsdifferenzierung: UmgebungsĂŒberschreibungen leben in einer einzigen
global.yaml.gotmpl. Sie können Bedingungen formulieren, aber die Struktur skaliert nicht auf N Umgebungen.
Die Community hat sich auf zwei Muster geeinigt, um diese Probleme zu lösen: App of Apps und ApplicationSets. Sie schlieĂen sich nicht gegenseitig aus, sondern bedienen unterschiedliche Anforderungen.
Muster 1: App of Apps
Das App-of-Apps-Muster verwendet eine Root-ArgoCD-Application, die ein Verzeichnis mit anderen Application-Manifesten synchronisiert. Die Root-App entdeckt untergeordnete Applications, erstellt sie und ĂŒberwacht ihre Gesundheit. Das Löschen eines untergeordneten Manifests aus Git fĂŒhrt dazu, dass ArgoCD es entfernt.
# Root Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-opendesk
namespace: argocd
spec:
source:
repoURL: https://github.com/opendesk-edu/gitops-config.git
path: apps/
destination:
server: https://kubernetes.default.svc
syncPolicy:
automated:
prune: true
# apps/keycloak.yaml â untergeordnete Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: keycloak
namespace: argocd
spec:
source:
repoURL: https://github.com/opendesk-edu/gitops-config.git
path: charts/keycloak/
destination:
server: https://kubernetes.default.svc
namespace: opendesk
syncPolicy:
automated:
selfHeal: true
Vorteile
- Volle Kontrolle pro App. Jede untergeordnete Application erhÀlt eine eigene Sync-Richtlinie, Sync-Wellen, Ignorierunterschiede und ein eigenes Projekt. Sie können Keycloak automatisch synchronisieren, wÀhrend Sie Nextcloud manuell promoten.
- Helm/Kustomize-Templating. Das Apps-Verzeichnis kann selbst ein Helm-Chart sein, sodass Sie Application-Manifeste mit
values.yamltemplaten. Eine WerteÀnderung propagiert sich auf alle generierten Apps. - Einfaches mentales Modell. Es sind nur Applications, die Applications verwalten. Keine neuen CRDs, keine Generatoren, keine Templating-Sprache. Jeder ArgoCD-Benutzer versteht es.
- AbhÀngigkeitsreihenfolge. Sync-Wellen funktionieren auf Application-Ebene. Sie setzen
sync-wave: 1auf Datenbanken,sync-wave: 5auf Apps, die von ihnen abhĂ€ngen. - Erprobt. Das Muster ist seit ArgoCD v1.x im Produktionseinsatz. Die Maintainer haben ausdrĂŒcklich erklĂ€rt, dass es nicht veraltet ist (Diskussion #11892).
Nachteile
- Ein YAML pro App pro Umgebung. Bei 30 Diensten Ă 3 Umgebungen = 90 Application-Manifeste. Selbst mit Helm-Templating ist das eine Menge zu pflegender Dateien.
- Keine dynamische Erkennung. Einen Dienst hinzufĂŒgen bedeutet, ein neues Application-YAML zu committen. Es gibt kein âDieses Verzeichnis scannen und automatisch Apps erstellen".
- Nur fĂŒr Administratoren geeignet. Das Erstellen von Applications ĂŒber Projekte hinweg erfordert Admin-Rechte. Teams Self-Service zu geben bedeutet, ihnen Application-Manifeste anzuvertrauen, einschlieĂlich sensibler Felder wie
project,clusterundnamespace. - Root-App kann zum Engpass werden. Die ĂŒbergeordnete Application synchronisiert alle untergeordneten. Wenn eine untergeordnete App falsch konfiguriert ist, kann die Root-App als beeintrĂ€chtigt angezeigt werden, auch wenn der Rest gesund ist.
Wann es GlÀnzt
- Einzelner Cluster mit einer festen Anzahl von Diensten
- Teams, die feingranulare Kontrolle pro App benötigen
- Komplexe AbhÀngigkeitsketten mit strenger Reihenfolge
- Migration von einer monolithischen App â die Struktur spiegelt das wider, was bereits vorhanden ist
Muster 2: ApplicationSet
ApplicationSets sind ArgoCDs nativer generatorbasierter Ansatz. Statt N Application-Manifeste zu schreiben, definieren Sie einen ApplicationSet mit einer Vorlage und einem Generator, der die Parameter erzeugt. Der Controller erstellt, aktualisiert und löscht Applications automatisch.
Relevante Generatortypen fĂŒr openDesk
Git Directory Generator â entdeckt Dienste automatisch durch Scannen von Repository-Verzeichnissen:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: opendesk-services
namespace: argocd
spec:
goTemplate: true
generators:
- git:
repoURL: https://github.com/opendesk-edu/gitops-config.git
revision: main
directories:
- path: services/*
template:
metadata:
name: '{{.path.basename}}'
spec:
project: opendesk
source:
repoURL: https://github.com/opendesk-edu/gitops-config.git
path: '{{.path.path}}'
destination:
server: https://kubernetes.default.svc
namespace: '{{.path.basename}}'
syncPolicy:
automated:
selfHeal: true
Neuer Dienst? Erstellen Sie ein services/nextcloud/-Verzeichnis mit Ihrem Kustomize-Overlay. ArgoCD erkennt es. Keine KonfigurationsĂ€nderungen, kein PR-Review fĂŒr den ApplicationSet selbst.
Matrix Generator â kombiniert Cluster und Dienste fĂŒr Multi-Umgebungs-Bereitstellungen:
generators:
- matrix:
generators:
- git:
repoURL: https://github.com/opendesk-edu/gitops-config.git
directories:
- path: services/*
- clusters:
selector:
matchLabels:
env: prod
Dies erzeugt jede Kombination aus Dienst Ă Cluster. Drei Cluster Ă 30 Dienste = 90 Applications aus einem Manifest.
Cluster Generator â stellt die gleichen Dienste in jedem Cluster bereit, der auf einen Label-Selektor passt. FĂŒgen Sie einen Cluster hinzu, labeln Sie ihn mit env: staging, und jeder Dienst wird automatisch bereitgestellt.
List Generator â explizite Kontrolle, wenn Verzeichnisstrukturen nicht ausreichen. Definieren Sie eine einfache YAML-Liste von ParametersĂ€tzen.
Vorteile
- Dynamische Erkennung. Dienste erscheinen und verschwinden basierend auf der Git-Repository-Struktur. Kein manuelles Application-Management.
- Multi-Cluster-nativ. Ein ApplicationSet kann 10 Cluster ansteuern. Der Cluster-Generator erkennt automatisch in ArgoCD registrierte Cluster.
- Self-Service-sicher. Administratoren sperren sensible Felder (
project,cluster,namespace) in der Vorlage. Entwickler kontrollieren nur, was in das Quell-Repository geht. Dies ist das offizielle, von der ArgoCD-Dokumentation empfohlene Self-Service-Muster. - DRY im groĂen MaĂstab. Eine Vorlage ersetzt 30+ Application-Manifeste. Mit Matrix-Generatoren ersetzt ein Manifest 90+.
- Ressourcen beim Löschen erhalten. Die Option
preserveResourcesOnDeletionverhindert das kaskadenförmige Löschen von Live-Workloads, wenn ein ApplicationSet entfernt wird.
Nachteile
- Schwerer zu debuggen. ApplicationSet-Fehler erscheinen in den Controller-Logs, nicht in der ArgoCD-BenutzeroberflĂ€che. Wenn die Generierung stillschweigend fehlschlĂ€gt, bemerken Sie es möglicherweise erst, wenn Dienste fehlen. Wie ein Community-Mitglied anmerkte: âWenn nichts generiert wird, merken Sie es erst, wenn Sie in den Logs graben" (Diskussion #11892).
- EingeschrÀnkte Anpassung pro App. Die Vorlage wird einheitlich auf alle generierten Applications angewendet. Keycloak mit einer anderen Sync-Richtlinie als Nextcloud? Sie benötigen separate ApplicationSets oder Selektorbasierte Workarounds.
- Templating-KomplexitÀt. Go-Vorlagen mit verschachtelten Generatoren können schwer zu lesen und zu warten sein. Die Option
missingkey=errorhilft, aber das Debuggen der Vorlagen-Renderings ist eine eigene FĂ€higkeit. - Sync-Wellen gelten pro ApplicationSet, nicht pro App. Sie können keine unterschiedlichen Sync-Wellen fĂŒr verschiedene Dienste innerhalb desselben ApplicationSets festlegen, ohne sie auf mehrere ApplicationSets aufzuteilen.
- Blast Radius. Ein falsch konfiguriertes ApplicationSet-Template kann Dutzende oder Hunderte von Applications gleichzeitig beeintrĂ€chtigen. GrĂŒndliches CI-Linting ist unerlĂ€sslich.
Wann es GlÀnzt
- Multi-Cluster-Bereitstellungen (5+ Cluster)
- Dienste, die einem konsistenten Muster folgen (gleiches Repo-Layout, gleiche Sync-Richtlinie)
- Self-Service-Workflows, bei denen Teams Dienste unabhĂ€ngig hinzufĂŒgen
- Vorschau-Umgebungen pro Pull-Request (PR Generator)
- Jedes Szenario, in dem sich die Cluster- oder Dienstinventur hÀufig Àndert
Muster 3: Hybrid (Der Community-Konsens)
Wenn man die GitHub-Diskussionen liest und mit Teams spricht, die ArgoCD in Produktion betreiben, ist die hĂ€ufigste Empfehlung keines der reinen Muster â es ist ein geschichteter Hybrid:
âIch verwende App-of-Apps und ApplicationSet gleichzeitig: App-of-Apps fĂŒr das allererste Bootstrapping, mit eigentlich zwei Ebenen von App-of-Apps, und dann AppSet fĂŒr Self-Service durch die Teams." â Community-Mitglied, Diskussion #11892
âIch verwende typischerweise AppSets auf der obersten Ebene und App-of-Apps als zweite Ebene. Die oberste Ebene stellt sicher, dass alle Regionen das Produkt haben. Die zweite Ebene stellt sicher, dass das Produkt innerhalb der Region konsistent bereitgestellt wird." â @nastacio, Diskussion #11892
Eine praktische geschichtete Architektur:
ApplicationSet (Cluster Generator)
âââ pro Cluster: Root Application (App of Apps)
âââ pro Dienst: Child Application
âââ Helm/Kustomize-Bereitstellung
Oder umgekehrt, je nachdem, wo die Dynamik benötigt wird:
Root Application (App of Apps)
âââ ApplicationSet (Git Directory Generator)
âââ Anwendung pro Dienst
âââ Helm/Kustomize-Bereitstellung
Entscheidungsmatrix
| Faktor | App of Apps | ApplicationSet |
|---|---|---|
| Lernkurve | Niedrig | Mittel |
| Anpassung pro App | VollstÀndig | EingeschrÀnkt (erfordert Aufteilung) |
| Multi-Cluster | Manuelle Duplikation | Nativ (Cluster Generator) |
| Self-Service-Sicherheit | Niedrig (nur Admin-Rechte) | Hoch (Vorlage sperrt Felder) |
| Debugging | Einfach (UI zeigt alles) | Schwer (Controller-Logs) |
| Skalierung auf 100+ Apps | MĂŒhsam (Dateianzahl) | NatĂŒrlich (ein Manifest) |
| Sync-Wellen-UnterstĂŒtzung | Pro Application | Pro ApplicationSet |
| Dynamische Erkennung | Nein (manuelles YAML) | Ja (Git-Verzeichnisscan) |
| Reifegrad | Seit ArgoCD v1.x | Seit ArgoCD v2.x |
Unsere Empfehlung fĂŒr openDesk
FĂŒr den spezifischen Kontext von openDesk Edu â 30+ Dienste, auf 1â3 Cluster ausgerichtet, mit Bedarf an Umgebungsdifferenzierung und spĂ€terem Self-Service â sehen wir zwei natĂŒrliche Phasen:
Phase 1: App of Apps (jetzt)
Migration von der monolithischen Helmfile-Application zu einer App-of-Apps-Struktur. Dies ist die Migration mit dem geringsten Risiko:
- Jede Helmfile-Release eines Dienstes als separate ArgoCD-Application kapseln
- Gemeinsame Infrastruktur (Datenbanken, Caches) in einer gemeinsamen Sync-Phase gruppieren
- Die Helmfile-Orchestrierung beibehalten, aber in untergeordnete Applications zerlegen
- Kontrolle ĂŒber die Sync-Reihenfolge und dienstspezifische Richtlinien behalten
Phase 2: ApplicationSet (als NĂ€chstes)
Sobald die App-of-Apps-Struktur lĂ€uft und stabil ist, ApplicationSets fĂŒr sich wiederholende Muster einfĂŒhren:
- Einen Git Directory Generator verwenden, um Dienste automatisch zu erkennen, die einem Standardlayout folgen
- Einen Matrix Generator (Git Ă Cluster) fĂŒr Multi-Umgebungs-Promotion (Dev â Staging â Prod) verwenden
- Self-Service fĂŒr bildungsspezifische Dienste an Teams ĂŒber eingeschrĂ€nkte ApplicationSets mit gesperrten Vorlagen auslagern
Was Wir Nicht Tun
- Helmfile nicht vollstÀndig entfernen. Das Helmfile-Plugin handhabt die AbhÀngigkeitsreihenfolge und das Wertetemplating bereits gut. Die Application-Ebene (App of Apps oder ApplicationSet) sollte Helmfile-Releases orchestrieren, nicht ersetzen.
- Nicht von Tag eins an vollstĂ€ndig auf ApplicationSet umstellen. Die Debugging- und Templating-KomplexitĂ€t ist es fĂŒr eine Bereitstellung mit einem einzelnen Cluster und einer festen Anzahl von Diensten nicht wert. ApplicationSet zahlt sich aus, wenn Sie 10+ Cluster oder 50+ Dienste erreichen.
Referenzen
- ArgoCD Diskussion #11892 â ApplicationSets vs App-of-apps vs Kustomize
- ArgoCD Dokumentation â ApplicationSet
- ArgoCD Dokumentation â Cluster Bootstrapping
- ArgoCD Application Patterns: App of Apps, ApplicationSets, and Beyond â DevOpsil
- ArgoCD ApplicationSet Multi-Cluster Guide â Opsio
- How to Implement the App-of-Apps Pattern at Scale â OneUptime
- One Manifest, Hundreds of Apps: How Argo CD ApplicationSets Work â Burrell Tech
- Getting Started with ApplicationSets â Red Hat
- openDesk Edu â Aktuelle ArgoCD-Bereitstellung

