Files
devops-infra-helm-charts-gcp/claude/04-override-hierarchy.md
T
2026-08-26 03:39:42 +05:30

4.3 KiB
Raw Blame History

Per AI Blitz Plan §claude. Layer: 1. Repo: devops-infra-helm-charts.

04 — Override hierarchy

How the per-cluster override file, the chart's default values, and any raw-manifest sidecars compose at deploy time.

The three layers

For a given Argo Application targeting <cluster> × <app>, the rendered manifests come from three sources:

  1. Chart defaultshelm-templates/<chart>/values.yaml. The upstream values, possibly customized in an intentional fork. This is the lowest precedence.
  2. Cluster overridehelm-overrides/<cluster>/<app>/custom-values.yaml. Helm-merged on top of (1). This is what the agent edits day-to-day.
  3. Raw manifest sidecarshelm-overrides/<cluster>/<app>/<extra>.yaml (and optionally subdirectories like computeclass/, external-dns-services/). These are NOT consumed by Helm. Argo applies them directly to the cluster, in the same Application.

The Argo Application in the sister repo declares which path: (the override directory) and which helm.valueFiles: to use. Conventionally the Application points at the override directory and lists custom-values.yaml; raw sidecars in the same directory are picked up by Argo's manifest discovery.

Helm merge semantics

Helm performs a deep merge of (2) over (1):

  • Maps merge key-by-key.
  • Lists are replaced wholesale, not merged. This is the most common surprise — to extend an upstream list (tolerations, extraArgs, extraEnv), copy the upstream list into the override and edit there. Don't write a list expecting it to append.
  • null in the override deletes the key set in defaults.

If you need surgical list editing rather than wholesale replacement, you must fork the chart and rewrite the template — almost never the right call. See ../docs/platform/procedures/fork-upstream-chart.md.

Dry-running the merge

Always render before pushing. The command from the root CLAUDE.md Quick reference table:

helm template <release> helm-templates/<chart> \
  -f helm-overrides/<cluster>/<app>/custom-values.yaml

For wrapper charts (Chart.yaml dependencies:), refresh subcharts first:

helm dependency update helm-templates/<chart>

For raw sidecars, validate separately:

kubectl apply --dry-run=client -f helm-overrides/<cluster>/<app>/<extra>.yaml

Where each piece of config belongs

Config Goes in Why
Image tag pin (production registry) custom-values.yaml Per-cluster pinning is the whole point of the override layer.
replicaCount, resource requests custom-values.yaml Per-cluster capacity tuning.
nodeSelector, tolerations, computeClass custom-values.yaml Per-cluster node-pool topology. Never copy-paste across clusters.
fullnameOverride custom-values.yaml Pinned to keep Service DNS / PVC binding stable. Never change an existing one.
Helm-managed Service / Deployment / ConfigMap chart's templates/ (don't touch) Owned by upstream chart.
External-DNS record bound to a Service the chart doesn't manage external-dns-services/*.yaml raw sidecar Not part of the chart's surface.
ComputeClass definition (Autopilot) computeclass/*-cc.yaml raw sidecar Cluster-scoped object the chart can't render.
StorageClass / PriorityClass manifests/storageclass/, manifests/priorityclass/<cluster>/ Cluster-wide singleton, separate from any one Application.
Secret values External Secrets Operator + GCP Secret Manager / Vault Never in custom-values.yaml. See ./06-secrets-and-identity.md.

Schema details

See also