Kustomize Overlays skill for Codex

One base, thin overlays, rendered diffs for every env. Codex organises Kubernetes YAML into a deployable base, thin dev, staging and production overlays, and opt-in components, choosing strategic merge or JSON 6902 patches by what is being changed. It renders every overlay before and after an edit and diffs them, so a change meant for staging cannot quietly reach production, and it migrates deprecated fields without touching immutable selectors.

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- kustomize-overlays

Installs to ~/.agents/skills/kustomize-overlays/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $kustomize-overlays, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Structures Kubernetes configuration with Kustomize - a shared base, per-environment overlays, reusable components, strategic-merge and JSON 6902 patches, configMapGenerator and secretGenerator hash suffixes, image tag overrides, replacements and the helmCharts inflator - and diffs rendered output per environment. Use when the same manifests must differ across dev, staging and production, when overlays have drifted into copies, when migrating off deprecated fields like patchesStrategicMerge, commonLabels or vars, or when reviewing a kustomization.yaml.

Use it when

  • The same app is deployed to several environments with small differences
  • Overlays have grown into near-copies of the base
  • kustomize build warns about deprecated fields
  • You need a reviewable rendered diff per environment

Use something else when

  • You are packaging an app for others to install with configurable values: use helm-charts
  • The base manifests themselves need probes, resources or PDB design: use kubernetes-manifests

How to check the result

kustomize build succeeds for every overlay and the per-overlay diff against the pre-change render shows changes only in the environments you intended.

The mistake it prevents

Converting commonLabels to labels with includeSelectors flipped, which changes Deployment selectors and gets rejected by the API server on apply.

~/.agents/skills/kustomize-overlays/SKILL.md

--- name: kustomize-overlays description: Structures Kubernetes configuration with Kustomize - a shared base, per-environment overlays, reusable components, strategic-merge and JSON 6902… license: MIT ---

Done well, the base is a complete, deployable description of the app; each overlay holds only what is genuinely different about its environment; and kustomize build for every overlay is rendered and diffed in review, so nobody guesses what production receives.

Inspect first

  1. Read AGENTS.md and find every kustomization.yaml (rg --files -g 'kustomization.yaml').
  2. Learn who renders it: kubectl apply -k, standalone kustomize build, Argo CD, or Flux. kubectl embeds an older Kustomize than the standalone binary; check both with kubectl version --client and kustomize version and write for the oldest one in use.
  3. Render every overlay before editing and save the output as a baseline:
for o in overlays/*/; do kustomize build "$o" > "/tmp/before-$(basename "$o").yaml"; done

Layout

k8s/
├── base/
│   ├── kustomization.yaml
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   └── config.env
├── components/
│   ├── debug-sidecar/          # kind: Component, opt-in per overlay
│   └── pdb/
└── overlays/
    ├── dev/
    │   └── kustomization.yaml
    ├── staging/
    └── production/
        ├── kustomization.yaml
        ├── replicas-resources.yaml
        └── config.env

Rules for the split:

Put it inWhen
baseTrue for every environment: containers, ports, probes, labels, default config
overlayDiffers per environment: replicas, resources, hostnames, image tag, namespace
componentAn optional feature several overlays enable (PDB, HPA, sidecar, network policy)
separate baseThe “variant” differs in more than half its fields; it is a different app

Base

# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
labels:
  - pairs:
      app.kubernetes.io/name: orders
    includeSelectors: true      # flipping this later changes immutable selectors
resources:
  - deployment.yaml
  - service.yaml
  - ingress.yaml
configMapGenerator:
  - name: orders-config
    envs: [config.env]

Production overlay

# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: shop-prod
resources:
  - ../../base
components:
  - ../../components/pdb
labels:
  - pairs:
      environment: production
    includeSelectors: false     # never add environment labels to selectors
images:
  - name: registry.example.com/shop/orders
    newTag: "1.14.2"            # or digest: sha256:...
replicas:
  - name: orders
    count: 4
configMapGenerator:
  - name: orders-config
    behavior: merge
    envs: [config.env]
patches:
  - path: replicas-resources.yaml
  - target:
      kind: Ingress
      name: orders
    patch: |-
      - op: replace
        path: /spec/rules/0/host
        value: orders.example.com
# overlays/production/replicas-resources.yaml (strategic merge patch)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: orders
spec:
  template:
    spec:
      containers:
        - name: orders          # merge key: must match the base container name
          resources:
            requests: { cpu: "1", memory: 1Gi }
            limits: { memory: 1Gi }

Component:

# components/pdb/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component
resources:
  - pdb.yaml

Patch choice

ChangeUse
Add or change fields on a known objectStrategic merge patch file under patches:
Change one list item by index, remove a field, or patch CRDs without merge keysJSON 6902 patch (op: replace/add/remove) with a target
Same patch across many objectspatches with target selecting by kind, labelSelector or name regex
Copy a value from one object into another (Service name into an env var)replacements
Image tag per environmentimages: (CI can run kustomize edit set image registry.example.com/shop/orders:1.14.3)

Strategic merge on CRDs replaces whole lists because CRDs lack merge keys. Use JSON patches for CRD lists.

Deprecated fields to migrate

OldNew
patchesStrategicMerge, patchesJson6902patches (with path or patch, optional target)
commonLabelslabels with explicit includeSelectors
varsreplacements
bases:resources:

kustomize edit fix rewrites many of these automatically; review the diff afterwards. A commonLabels to labels move that changes includeSelectors alters Deployment selectors, which the API server rejects for existing objects.

Generators

  • configMapGenerator and secretGenerator append a content hash to the name and rewrite references, so a config change rolls the Deployment. Keep that; do not set disableNameSuffixHash: true unless something outside Kustomize needs a fixed name.
  • Old hashed ConfigMaps accumulate in the cluster; Argo CD prunes them, kubectl apply -k does not unless you use --prune with a label selector.
  • secretGenerator with literal values commits secrets to Git. Use it only with files that are gitignored or decrypted at build time (SOPS via KSOPS, or an external secrets operator). See $secrets-management.

Helm inside Kustomize

helmCharts:
  - name: redis
    repo: oci://registry-1.docker.io/bitnamicharts
    version: 21.2.5
    releaseName: cache
    valuesFile: redis-values.yaml

Needs kustomize build --enable-helm (and network for the chart pull). Pin version. Use this when you must patch something the chart’s values do not expose; otherwise deploy the chart directly.

Hard rules

  • Overlays never copy whole base files. If an overlay patch is larger than the base object, restructure.
  • Relative paths only, and only inside the repo. The default load restrictor blocks files outside the kustomization root; do not disable it with --load-restrictor LoadRestrictionsNone to work around a bad layout.
  • Names in patches must match the base name before namePrefix/nameSuffix are applied.
  • namespace: in an overlay overrides every namespaced object, including ones you meant to put elsewhere. Split those into their own kustomization.
  • Applying a production overlay is a deploy: show the rendered diff and get confirmation first.

Workflow

- [ ] 1. Render all overlays to baseline files
- [ ] 2. Make the change in the narrowest place (base, component, or one overlay)
- [ ] 3. Re-render every overlay and diff against its baseline
- [ ] 4. Validate rendered output with kubeconform
- [ ] 5. kubectl diff -k against the target cluster (needs access)
- [ ] 6. Apply only with user confirmation, or let GitOps sync it

Verification

for o in overlays/*/; do
  n=$(basename "$o")
  kustomize build "$o" > "/tmp/after-$n.yaml" || exit 1
  diff -u "/tmp/before-$n.yaml" "/tmp/after-$n.yaml" > "/tmp/diff-$n.patch"; echo "$n: $(grep -c '^[+-][^+-]' /tmp/diff-$n.patch) changed lines"
  kubeconform -strict -summary -ignore-missing-schemas "/tmp/after-$n.yaml"
done
kubectl diff -k overlays/staging

An unexpected change in an overlay you did not touch means the edit landed in the base or a shared component: confirm that was intended before continuing.

Output

**Change:** PDB moved from production overlay into components/pdb; enabled in staging and production
**Rendered diffs:** dev: none; staging: +PodDisruptionBudget orders; production: none (identical object)
**Migrations:** commonLabels -> labels (includeSelectors kept true, selectors unchanged)
**Checks:** kustomize build ok for 3 overlays, kubeconform clean, kubectl diff -k staging reviewed

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "Kustomize Overlays"
  short_description: "One base, thin overlays, rendered diffs for every env"
  default_prompt: "$kustomize-overlays Split these Kubernetes manifests into a Kustomize base with dev and prod overlays"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc
Just launched

Codex Skills Pro is live

79 premium skills for Codex, each with scripts, references and an evidence report that proves the result.

Bought one by one$882.21
All 79 skills$49
94% off

That's $0.62 a skill, paid once.

Get all 79 for $49Or pick single skills from $4.99 →

Secure checkout by Creem