85 lines
4.1 KiB
Markdown
85 lines
4.1 KiB
Markdown
# ADR-I2: Why the Incubator + Generic Chart Pattern
|
||
|
||
> Architecture Decision Record for `devops-infra-argo-config`.
|
||
>
|
||
> **Status:** Accepted (in production use)
|
||
>
|
||
> **Layer:** 1-T reference. This ADR documents the load-bearing architectural decision behind the repo's structure.
|
||
|
||
---
|
||
|
||
## Context
|
||
|
||
`devops-infra-argo-config` manages ArgoCD `Application` resources for infrastructure tooling across ~19 Kubernetes clusters. The early approach was direct Application YAML files — one file per tool per cluster.
|
||
|
||
**Problem with the direct approach:**
|
||
- Adding a tool to 15 clusters = 15 new YAML files
|
||
- Each file had ~40 lines of near-identical boilerplate (metadata, syncPolicy, finalizers, source URLs)
|
||
- Updating a field common to all clusters (e.g., `targetRevision`) required editing 15 files
|
||
- Drift between files was hard to detect and frequently occurred
|
||
|
||
---
|
||
|
||
## Decision
|
||
|
||
Adopt the **App-of-Applications incubator pattern**:
|
||
|
||
1. One **parent Application** per cluster (the "incubator"). It points at a Helm chart in this repo + a values file.
|
||
2. One **generic Helm chart** (`generic-argo-apps-chart/`) that templates child Applications from a list.
|
||
3. One **values file** per cluster that defines `clusterSpec`, `teamSpec`, `argocdSpec`, and the `appSpec[]` list.
|
||
|
||
To add a tool to a cluster: add one entry to `appSpec[]` in the values file. The chart renders the Application. No boilerplate.
|
||
|
||
---
|
||
|
||
## Consequences
|
||
|
||
### Positive
|
||
|
||
| Benefit | Detail |
|
||
| ------- | ------ |
|
||
| **Single editing surface** | Adding or removing a tool = one list entry in one values file |
|
||
| **Consistent Application shape** | All child Applications are rendered by the same template → same syncPolicy, finalizers, label schema |
|
||
| **Drift is visible** | Comparing `appSpec[]` across values files is trivially scriptable |
|
||
| **Chart-level changes propagate instantly** | Update `generic-argo-apps-chart/` once → all clusters reflect it on next sync |
|
||
| **Naming is deterministic** | Application names are generated by the template, not hand-typed |
|
||
|
||
### Negative / constraints
|
||
|
||
| Constraint | Detail |
|
||
| ---------- | ------ |
|
||
| **`generic-argo-apps-chart/` changes are fleet-wide** | A bug in the template breaks ALL clusters simultaneously — HIGH RISK edits |
|
||
| **Three-file invariant** | Adding a cluster requires coordinated creation of incubator + values file + helm-overrides folder in the sister repo |
|
||
| **Cross-repo dependency** | `appSpec[].chartDir` and `valuesDir` must exist in `devops-infra-helm-charts` — the repos are coupled |
|
||
| **No per-cluster template customization** | If a cluster needs a fundamentally different Application shape (different syncPolicy, different project), the generic chart must be extended rather than overridden per cluster |
|
||
|
||
---
|
||
|
||
## Alternatives considered
|
||
|
||
### Alternative 1: Direct Application YAMLs per tool per cluster
|
||
|
||
Rejected. Scale problem: 50 tools × 19 clusters = 950 files. Drift is unmanageable.
|
||
|
||
### Alternative 2: ApplicationSet with cluster generators
|
||
|
||
Considered for a future phase. ApplicationSet would allow truly declarative fleet management (define a tool once, it appears on all matching clusters). Not adopted yet because:
|
||
- Migration cost is high (existing Applications would need recreation)
|
||
- ApplicationSet behavior on cluster removal requires careful finalizer design
|
||
- The current pattern is working and well-understood by the team
|
||
|
||
ApplicationSet remains a candidate for Phase 2.
|
||
|
||
### Alternative 3: Separate generic chart per team/BU
|
||
|
||
Rejected. The complexity of maintaining multiple templates outweighs the benefit of per-team customization. A single chart with cluster-level values is sufficient.
|
||
|
||
---
|
||
|
||
## References
|
||
|
||
- [SANCTITY_RULES.md R2](../../docs/global/SANCTITY_RULES.md) — the incubator ↔ values ↔ generic-chart contract is sacred
|
||
- [ADR-I1: Why one generic chart per cluster](ADR-I1-generic-chart-per-cluster.md) — companion ADR on the chart design
|
||
- [values-file-schema.md](../../docs/platform/schemas/values-file-schema.md) — full field reference
|
||
- [incubator-values-schema.md](../../docs/platform/schemas/incubator-values-schema.md) — incubator Application schema
|