Alle inzichten
DevOps & platform engineering Artikel

Vijf AKS-clusters, één Git-repository

Een technische implementatie van cluster-onboarding, ApplicationSets en CNCF-componenten. Met Git als bron van waarheid en duidelijke grenzen tussen nonprod en productie.

De kern: maak de cluster-directory de deploybare eenheid, laat ApplicationSets configuratie ontdekken en behandel platformwijzigingen als gewone softwarewijzigingen.

In dit artikel

Vijf clusters, twee harde grenzen

Een cluster dat vandaag goed draait, zegt weinig over de toestand over een half jaar. Handmatige wijzigingen stapelen zich op, versies lopen uiteen en de reden achter een instelling verdwijnt. Met vijf clusters wordt die afwijking snel structureel. Daarom is de volledige platformlaag declaratief vastgelegd: wat in Git staat, is wat er hoort te draaien.

Het landschap bestaat uit twee clusterfamilies. infra levert managementfuncties zoals identity, centrale observability en CI-runners. worker draait workloads en bijbehorende platformdiensten. Naast nonprod en prod is er een vnext-cluster waarop nieuwe componenten en versies als eerste landen.

Nonprod en productie krijgen ieder een eigen Argo CD-installatie. Die keuze kost extra beheer, maar maakt de grens concreet: een fout, upgrade of te ruim recht in de nonprod-control plane werkt niet rechtstreeks door naar productie. Voor nonprod geldt als uitgangspunt dat data kan uitlekken. Daarom is daar uitsluitend geanonimiseerde data toegestaan. In productie wordt echte data verwerkt; daar geldt dat data niet mag uitlekken.

01 / TOPOLOGY

Gescheiden control planes

GITPlatformrepository desired state
CONTROL PLANEArgo CD nonprod
infra-nonprodworker-nonprodworker-nonprod-vnext
CONTROL PLANEArgo CD prod
infra-prodworker-prod
Nonprod gebruikt uitsluitend geanonimiseerde data. Productie verwerkt echte data en vereist dat die data niet uitlekt.

De repository is het deploymentmodel

De repository bevat ruim 3.700 bestanden. Bijna 3.000 daarvan zijn gevendorde Helm-charts; de eigenlijke platformlogica beslaat ongeveer 770 bestanden. De omvang is minder belangrijk dan de vaste structuur:

applications/
  infrastructure/<component>/<cluster>/
  platform/<component>/<cluster>/
  applications/<workload>/<cluster>/
applicationsets/
  base/
  overlays/nonprod/
  overlays/prod/
argocd/
bootstrap/<stage>/
projects/
clusters/

Iedere combinatie van component en cluster heeft een eigen build-root. Daarin staan kustomization.yaml, helm-values.yaml en argocd-app-config.yaml. Het laatste bestand is deploymentmetadata voor de ApplicationSet: naam, namespace, sync-wave, doelcluster, stage en Git-revisie.

Gemeenschappelijke waarden worden soms herhaald. Dat is bewust. De build blijft binnen zijn eigen directory en één map laat volledig zien wat op dat cluster draait. Er is geen verborgen overerving door meerdere lagen nodig om een wijziging te beoordelen.

Charts worden gevendord

Upstream Helm-charts staan met hun exacte versie in de repository. Kustomize combineert de chart, aanvullende manifests en patches in één build. Daardoor heeft een render geen netwerktoegang nodig en blijft de uitkomst reproduceerbaar. Oude chartversies blijven beschikbaar zolang een cluster ze nog gebruikt.

Onboarding zonder centrale inventarislijst

Terraform maakt per omgeving één root-Application aan. Vanaf dat punt beheert Argo CD zichzelf en de rest van het platform. De bootstrap past AppProjects en de stage-specifieke ApplicationSets toe. Dertien ApplicationSets gebruiken ieder een Git-generator om configuratiebestanden te ontdekken.

Voor ieder gevonden argocd-app-config.yaml-bestand ontstaat een Application met een voorspelbare naam, bijvoorbeeld infra-prod-cert-manager. Argo CD voert vervolgens kustomize build --enable-helm uit, vergelijkt het resultaat met het doelcluster en synchroniseert alleen de afwijkingen.

02 / FLOW

Van directory naar cluster

  1. 01Commitreviewed Git state
  2. 02OntdekkenApplicationSet
  3. 03RenderenKustomize + Helm
  4. 04Validerenpolicy + diff
  5. 05Reconciliërenprune + self-heal
Een nieuwe component of cluster wordt toegevoegd via dezelfde drie bestanden. De generator ontdekt de configuratie zonder een centrale lijst bij te werken.

Drie soorten ApplicationSets

  • Lokale componenten: infrastructuur, platformdiensten en workloads uit deze repository.
  • Clusterconfiguratie-gedreven: configuratie uit infra bepaalt welke instance uit een andere repository wordt aangesloten.
  • Externe workloadrepositories: teams beheren hun deploymentconfiguratie zelf; de platformrepository bepaalt via welk AppProject en naar welke bestemming dat mag.

Operators en instances blijven zo gescheiden. De Keycloak- en RabbitMQ-operators horen bij het platform; hun instances staan bij de dienst die er verantwoordelijk voor is.

Volgorde en omgevingsscheiding staan in code

Platformcomponenten hebben harde afhankelijkheden. Gateway API-CRD’s moeten bestaan voordat Istio en gateways kunnen starten. De gewenste volgorde staat daarom als syncWave bij de component. De ApplicationSet zet deze waarde als annotation op de gegenereerde Application.

03 / ORDER

Afhankelijkheden als sync-waves

−6Gateway API CRDs
−5Istio + CNI
0Operators & gateways
+5Workloads
Negatieve waves leggen de fundering. Operators en gateways volgen zodra hun CRD’s en mesh beschikbaar zijn; workloads sluiten de keten.

De ApplicationSets zijn één keer gedefinieerd in een gedeelde base. De stage-selector heeft daar expres de ongeldige waarde REPLACE_ME. Alleen een overlay voor nonprod of prod vult een geldige stage in. Een per ongeluk gerenderde base selecteert dus niets. Ook toekomstige clusters blijven als .template staan totdat ze bij Argo CD zijn geregistreerd.

Gegenereerde Applications gebruiken automated sync met prune en selfHeal. Handmatige clusterwijzigingen worden teruggedraaid en verwijderde Git-resources verdwijnen uit het cluster. Afwijkingen voor controllers of webhooks worden gericht opgenomen in ignoreDifferences, zodat noodzakelijke mutaties geen permanente sync-lus veroorzaken.

Grenzen vóórdat een manifest het cluster bereikt

Vier AppProjects scheiden bootstrap, infrastructuur, platformdiensten en applicaties. Per project ligt vast welke repositories, clusters, namespaces en clusterbrede resourcetypes zijn toegestaan. Een workload kan daardoor geen ClusterRole aanmaken als het project dat niet toestaat, ook niet wanneer het manifest in de eigen repository staat.

Argo CD gebruikt deny-all-by-default RBAC. Aanmelding verloopt via Entra ID; groepslidmaatschap bepaalt de beschikbare projecten en verhoogde rechten worden via PIM geactiveerd. Secrets volgen één route: Azure Key Vault, via Workload Identity en External Secrets Operator, naar een Kubernetes Secret. In Git staat alleen de verwijzing.

De pull request is de eerste beleidsgrens

Elke gewijzigde cluster-directory wordt gerenderd. YAML- en schemacontroles, padvalidatie, Gitleaks, RBAC-validatie, Trivy en Kyverno CLI controleren daarna de werkelijke output. De manifest-diff maakt zichtbaar wat een chart-update echt verandert; één gewijzigde versieregel kan immers honderden regels aan manifests opleveren.

  • BuildKustomize per cluster-directory
  • SchemaYAML en Kubernetes-resources
  • SecretsGitleaks vóór merge
  • PolicyKyverno CLI en Trivy
  • RBACAppProjects en rechten
  • ReviewDiff van gerenderde manifests

Een platformlaag van CNCF-bouwstenen

De infrastructuurlaag telt 24 componenten. Niet ieder cluster krijgt dezelfde set: de functie van het cluster bepaalt welke operators en platformdiensten nodig zijn.

BereikComponentenFunctie
Alle clustersIstio, Gateway API, External Secrets, ExternalDNS, Kyverno, Alloy, kube-state-metricsNetwerk, secrets, policy en telemetry
infracert-manager, CloudNativePG, Keycloak Operator, Grafana, Mimir, Loki, Tempo, Actions Runner ControllerCentrale platform- en managementdiensten
workerKEDA, RabbitMQ Operator, Redis OperatorWorkloadgerichte platformdiensten
SelectiefHomepage, Reloader, Hubble UI, KialiBediening en inzicht waar nodig

Observability is centraal ingericht. Alloy verstuurt metrics, logs en traces vanaf elk cluster naar de LGTM-backend op infra. Dat houdt lokale agents klein en maakt analyse over clustergrenzen heen mogelijk.

Updates schuiven gecontroleerd richting productie

Renovate houdt chart- en imageversies bij, maar verandert nooit alle clusters tegelijk. Per component en per omgeving ontstaat een afzonderlijke pull request. Versies landen eerst op vnext en nonprod. Productie volgt pas wanneer een release minimaal zeven dagen beschikbaar is. De exacte versie blijft per cluster vastgelegd.

04 / RELEASE

Eén versie, drie release-lanes

01vnextworker-nonprod-vnext
direct
02nonprodinfra + worker
direct
03prodinfra + worker
≥ 7 dagen
Renovate opent per omgeving een eigen pull request. Productie volgt pas wanneer de versie minimaal zeven dagen beschikbaar is.

De verhouding tot Haven+

Haven+ is een referentiearchitectuur en implementatie voor aanvullende platformdiensten op een Haven Kubernetes-omgeving. De richting sluit aan: GitOps, open-source componenten en herhaalbare inrichting van monitoring, identity, certificaten, databases, policy en secrets. Deze vergelijking is een architectuurtoets en geen formele conformiteitsclaim.

De overlap is groot: Alloy, cert-manager, CloudNativePG, ExternalDNS, External Secrets, Grafana, Loki, Mimir, Tempo, Istio en Keycloak komen in beide landschappen terug. De invulling verschilt waar het doelplatform daarom vraagt. Logs en traces gebruiken Loki en Tempo in plaats van ECK. Secrets blijven in Key Vault in plaats van versleuteld in Git. Kyverno, KEDA, RabbitMQ, Redis en Actions Runner Controller vormen aanvullende keuzes.

De Kubernetes-patronen zijn overdraagbaar. De Azure-integraties zijn dat niet vanzelf.

De implementatie is nadrukkelijk Azure-specifiek door AKS, Azure DNS, Key Vault, Workload Identity en Azure Container Registry. Een exitstrategie moet dat onderscheid expliciet maken: GitOps- en Kubernetes-patronen kunnen mee, cloudkoppelingen vragen vervanging.

Wat deze inrichting praktisch oplevert

  1. Maak de cluster-directory de eenheid. Chart, values en deploymentmetadata blijven bij elkaar.
  2. Laat ApplicationSets ontdekken. Een generator hoeft niet te veranderen wanneer een cluster of component wordt toegevoegd.
  3. Scheid de control planes. Productie krijgt een grens die niet alleen van RBAC afhankelijk is.
  4. Maak builds reproduceerbaar. Vendor charts en pin iedere versie per cluster.
  5. Leg de baseline vast in code. Policy en CI toetsen afspraken bij iedere wijziging opnieuw.
  6. Houd secrets buiten Git. Gebruik een externe secret store met workload-identiteit.

De opzet is niet af. Componenten en referentiearchitecturen blijven ontwikkelen. De blijvende waarde zit in de werkwijze: iedere wijziging is reviewbaar, herleidbaar en terug te draaien. Voor software waar inwoners dagelijks op rekenen, is dat een basisvoorwaarde.

Bronnen en context

De beschreven implementatie komt voort uit praktijkervaring bij WIGO4IT. Dit artikel wordt niet gepresenteerd als klantcase van Horst IT Consultancy. Genoemde aantallen en organisatorische keuzes zijn gebaseerd op de aangeleverde platformbeschrijving; de documentatielinks onderbouwen de gebruikte GitOps-mechanismen.

Van losse clusters naar één beheerbaar platform.

Een Kubernetes-platform dat lastig reproduceerbaar of overdraagbaar is? Een technische review maakt zichtbaar waar GitOps, platformgrenzen en een gefaseerde onboarding het verschil kunnen maken.