Problem
Teams need last-mile changes to Deployah-generated objects (extra labels, sidecar env, tolerations, annotation tweaks, JSON6902 patches) that profiles and the spec cannot express. Today:
- Extras (
.deployah/manifests/) only append YAML via extras.PostRenderer; colliding with a generated object is an error by design.
- There is no supported way to mutate the rendered Deployment/Service/Ingress stream short of forking the chart or fighting the collision rule.
Helm's answer is a post-renderer; the common tool for that is Kustomize. Deployah already wires postrenderer.PostRenderer through plan/deploy/render; it just needs a Kustomize implementation in the chain.
Goals
- Optional Kustomize overlay that runs as a Helm post-renderer on the rendered release (plan + deploy + offline plan).
- Support strategic-merge / JSON6902 patches (and normal
kustomization.yaml features) against generated resources.
- Keep "one binary" where practical: prefer embedding Kustomize (library /
krusty) over requiring a host kustomize binary.
- Clear layout under
.deployah/ with per-environment overlays (same env-dir idea as manifests).
- Compose with existing extras: defined pipeline order and collision rules.
- Preserve Deployah identity labels/annotations after Kustomize (re-assert or validate; do not allow stripping reserved
deployah.dev/* ownership).
Non-goals
- Replacing the Deployah chart with a user-owned chart.
- Replacing extras entirely (literal additive YAML stays useful).
- Arbitrary executable post-renderers (
--post-renderer ./script.sh) in v1 (security + portability; follow-up).
- Full GitOps Kustomize app-of-apps / multi-base repos.
- Letting Kustomize delete Deployah-managed identity keys without error.
Proposed design
Pipeline
Helm chart render
-> Kustomize post-renderer (optional) # transform / patch generated objects
-> extras append post-renderer # current .deployah/manifests behavior
-> install / plan diff
Kustomize may add resources too (via resources: / generators). Prefer patches-first UX; document that additive YAML can stay in extras for simpler authorship.
Layout
.deployah/
kustomize/
kustomization.yaml # base overlays applied to every env
patches/
add-labels.yaml
production/
kustomization.yaml # env-specific; merges/chains from parent
patches/
replicas.yaml
manifests/ # existing extras (unchanged)
crds/
Env subdirectory rules mirror manifests (production matches production and related wildcard envs per existing Deployah conventions).
Minimal kustomization.yaml mental model (implementation detail: stdin/resources file is staged in a temp dir, as Kustomize does not take Helm stdin natively):
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- all.yaml # written by Deployah from Helm render
patches:
- path: patches/add-labels.yaml
target:
kind: Deployment
Spec / flags
No required spec field if presence of .deployah/kustomize/ enables it. Optional knobs:
# deployah.yaml or platform (pick one owner)
# kustomize:
# enabled: true
# path: .deployah/kustomize
CLI escape: deployah deploy --skip-kustomize / deployah plan --skip-kustomize for debugging.
Identity and safety
After Kustomize runs:
- Re-apply or verify reserved labels/annotations on objects that still match generated identities.
- Fail if a patch removes
deployah.dev/managed-by / project / environment keys Deployah requires.
- Extras collision check runs on the post-Kustomize stream (extras still cannot clobber an object that exists after patches).
Implementation sketch
- New
extras.KustomizePostRenderer (or internal/kustomize) implementing postrenderer.PostRenderer.
- Chain:
Chain{Kustomize, Extras} or a small composite runner.
- Embed
sigs.k8s.io/kustomize/api / krusty; pin version; no shell kustomize in v1.
- Temp dir per render: write
all.yaml + copy overlay; krusty.MakeKustomizer(...).Run.
Failure modes
- Invalid
kustomization.yaml / patch target miss → render error with Kustomize message.
- Patch deletes required Deployah metadata → validation error.
- Extras collide with post-Kustomize object → same error as today.
- Empty / absent
.deployah/kustomize/ → no-op; present but broken → error.
Alternatives considered
- Extras only (status quo). Cannot patch generated objects.
- Allow extras to overwrite chart objects. Loses clear ownership; ad-hoc YAML merge is weaker than Kustomize patches.
- Shell out to
kustomize / user --post-renderer. Flexible; breaks one-binary and is harder to secure; follow-up.
- Profiles for every possible tweak. Does not scale; profiles stay for platform policy.
Compatibility and migration
Test plan
Checklist
Problem
Teams need last-mile changes to Deployah-generated objects (extra labels, sidecar env, tolerations, annotation tweaks, JSON6902 patches) that profiles and the spec cannot express. Today:
.deployah/manifests/) only append YAML viaextras.PostRenderer; colliding with a generated object is an error by design.Helm's answer is a post-renderer; the common tool for that is Kustomize. Deployah already wires
postrenderer.PostRendererthrough plan/deploy/render; it just needs a Kustomize implementation in the chain.Goals
kustomization.yamlfeatures) against generated resources.krusty) over requiring a hostkustomizebinary..deployah/with per-environment overlays (same env-dir idea as manifests).deployah.dev/*ownership).Non-goals
--post-renderer ./script.sh) in v1 (security + portability; follow-up).Proposed design
Pipeline
Kustomize may add resources too (via
resources:/ generators). Prefer patches-first UX; document that additive YAML can stay in extras for simpler authorship.Layout
Env subdirectory rules mirror manifests (
productionmatchesproductionand related wildcard envs per existing Deployah conventions).Minimal
kustomization.yamlmental model (implementation detail: stdin/resources file is staged in a temp dir, as Kustomize does not take Helm stdin natively):Spec / flags
No required spec field if presence of
.deployah/kustomize/enables it. Optional knobs:CLI escape:
deployah deploy --skip-kustomize/deployah plan --skip-kustomizefor debugging.Identity and safety
After Kustomize runs:
deployah.dev/managed-by/ project / environment keys Deployah requires.Implementation sketch
extras.KustomizePostRenderer(orinternal/kustomize) implementingpostrenderer.PostRenderer.Chain{Kustomize, Extras}or a small composite runner.sigs.k8s.io/kustomize/api/ krusty; pin version; no shellkustomizein v1.all.yaml+ copy overlay;krusty.MakeKustomizer(...).Run.Failure modes
kustomization.yaml/ patch target miss → render error with Kustomize message..deployah/kustomize/→ no-op; present but broken → error.Alternatives considered
kustomize/ user--post-renderer. Flexible; breaks one-binary and is harder to secure; follow-up.Compatibility and migration
.deployah/kustomize/→ behavior unchanged.deployah-extras(proposal: Agent Skills catalog and deployah skills install #28).Test plan
scenarios/with.deployah/kustomize/Checklist