GitOps consume — overview
How the platform-managed ApplicationSet discovers tenant overlays in GitLab and turns them into namespace-scoped Argo Applications on each spoke.
This subsection is for platform-admin operators, not tenant developers. It describes how a tenant overlay sitting in a GitLab app repo turns into a running Deployment on spoke-dc-v6. The pipe between Git and the cluster is owned by platform-gitops; tenants do not write Application or ApplicationSet YAML, and the platform team does not write tenant Deployment YAML.
Whiteboard — Tenant overlay to spoke namespace
Read the diagram top-down:
- The tenant app repo in GitLab carries the overlay layout from the app-repo overlay contract.
- The platform-managed ApplicationSet in
platform-gitops/clusters/spoke-dc-v6/appsets/watches that repo with agitgenerator. For every directory matchingapps/*/*/overlays/*/kustomization.yaml, it templates one ArgoApplicationper (team, app, env, target-cluster) tuple. - The ACM Placement / PlacementDecision pair feeds the ApplicationSet’s
clusterDecisionResourcegenerator, so an overlay only becomes an Application on clusters where ACM has placed it. - The hub Argo CD turns each templated Application into a ManifestWork addressed at the matching spoke (Red Hat pull model, per ADR 0018).
- The spoke Argo CD pulls its ManifestWork through the klusterlet’s outbound gRPC channel and reconciles the contained
Applicationagainst the spoke’s local API server. - Each Application is constrained by an AppProject (one per team) that whitelists source repos, destination namespaces, and resource kinds the tenant may create.
- The Application’s
destinationNamespaceisapps-<division>-<team>-<env>(already provisioned by tenant onboarding). kustomize buildof the overlay renders the finalDeployment(image pinned by digest),Service,Route, and anyExternalSecret, which Argo applies into the tenant namespace.
What this subsection covers
| Page | Purpose |
|---|---|
| 02 — ApplicationSet generator pattern | The git + clusterDecisionResource generator combination, ApplicationSet YAML, and the templating that produces one Application per (team, app, env). |
| 03 — App-repo overlay contract | The directory layout, naming rules, and images: block convention that every tenant repo MUST honour for ApplicationSet to discover it. |
For the tenant side (what to put in apps/<team>/<app>/), see the app-repo overlay contract. For the platform side (where the ApplicationSet ships from), see federated GitLab and pull-model.
Where the pieces live
| Piece | Repo | Path |
|---|---|---|
| ApplicationSet | comptech-platform/openshift-ops/openshift-platform-gitops | clusters/spoke-dc-v6/appsets/tenant-apps-appset.yaml |
| AppProject (per team) | comptech-platform/openshift-ops/openshift-platform-gitops | clusters/spoke-dc-v6/appprojects/team-<team>.yaml |
| Tenant overlays | divisions/<division>/<division>-apps-monorepo | apps/<team>/<app>/overlays/<env>/ |
| Pull-mode wiring (klusterlet, manifest agent) | platform-gitops | clusters/spoke-dc-v6/platform/ |
| Cluster-wide app-registry pull secret | platform-gitops | clusters/spoke-dc-v6/secrets/app-registry-pull/ |
Operating boundary
Three boundaries are load-bearing and must be preserved when you change anything in this subsection:
- Tenants cannot write
ApplicationorApplicationSetCRs. The AppProject’srolesdo not include those kinds. If a tenant needs a non-templated Application (a one-off CronJob, a Job), they file atype/enhancementissue againstopp-full-plat; the platform team adds it to the ApplicationSet template or to a separate AppSet shipping fromplatform-gitops. - CI cannot push to
stg/orprd/overlays. The Jenkins overlay-patch step and the Tekton overlay-patch step both refuse to write outsidedev/. Promotion is a human-drivenscripts/promote.shrun that copies the digest forward. See the promotion model for the rationale andpromote.shfor the mechanics. - The hub Argo CD never reconciles into the spoke directly. Every tenant Application is wrapped in a ManifestWork and the spoke’s local Argo CD does the actual
kustomize buildandapply. This is what makes the pattern survive a hub outage and what keeps the hub CPU footprint flat as spokes scale.
Failure-mode preview
These reappear with full symptom → root cause → fix → prevention tables on the per-page sections, but flagged here so the operator knows the four most common ways this pipeline breaks:
- Argo silent / not syncing at all on a spoke after a manifest change. Usually the ACM gitops-addon installed a rogue
routes.route.openshift.ioCRD that shadows the aggregated OpenShift Route APIService and crashes the/openapi/v2endpoint, which stalls every Argo sync silently. See the platform incident page — fix isoc delete crd routes.route.openshift.io. OutOfSyncon a brand-new tenant app because the cluster-wideapp-registry-pullSecret was never materialised into the new namespace. Symptom isImagePullBackOffon theDeployment. Fix is to label the namespaceapps.platform/tenant=trueso theClusterExternalSecretfans the Secret in; see 04 — ESO Secret and pullSecret.- ApplicationSet creates an Application against the wrong cluster. Usually the Placement label matcher overlaps two clusters. Re-run the Placement evaluation:
oc -n open-cluster-management get placementdecision <name> -o yamland confirmstatus.decisionscontains exactly the target. kustomize buildsucceeds in Argo but the rendered manifest has a tag, not a digest. The overlay was hand-edited to anewTag:after the digest was patched in by CI. Lint catches this pre-merge; thekustomize build … | grep -v @sha256negative check in 03 — App-repo overlay contract catches it post-merge.
References
opp-full-plat/connection-details/app-repo-contract.md(issue #182)opp-full-plat/connection-details/image-digest-overlay.md(issue #185)opp-full-plat/connection-details/promotion-model.md(issue #184)opp-full-plat/connection-details/app-registry-pullsecret.md(issue #172)opp-full-plat/adr/0014-developer-readiness-platform-contract.mdopp-full-plat/adr/0015-federated-gitops-repo-architecture.mdopp-full-plat/adr/0018-acm-openshift-gitops-pull-model-v6.md- ACM gitops-addon Routes CRD lab memory (incident #153, 2026-05-10)