Server--:--:--You--:--:--

Kustomize Basics

By Prabath Thalangama· September 13, 2026· 3 min read
#kubernetes#kustomize#gitops

Introduction

Kustomize (built into kubectl -k and kubectl apply -k) customizes Kubernetes manifests without templates. You keep valid YAML and layer changes on top via overlays. It's the lighter alternative to Helm when you don't need distribution or complex logic.

Layout

base/
├── kustomization.yaml
├── deployment.yaml
├── service.yaml
overlays/
├── staging/
│   ├── kustomization.yaml
│   └── replicas-patch.yaml
└── prod/
    ├── kustomization.yaml
    ├── replicas-patch.yaml
    └── resources-patch.yaml
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml
commonLabels:
  app: myapp
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: prod
namePrefix: prod-
resources:
  - ../../base
patches:
  - path: replicas-patch.yaml
  - path: resources-patch.yaml
images:
  - name: myapp
    newTag: 1.4.2                 # bump this in CI on release
replicas:
  - name: myapp
    count: 6
labels:
  - pairs: { env: prod }
    includeSelectors: false
kubectl kustomize overlays/prod          # render to stdout
kubectl apply -k overlays/prod

Patches

Strategic merge — a partial manifest; fields you specify override, lists merge by key (usually name):

# replicas-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata: { name: myapp }
spec:
  template:
    spec:
      containers:
        - name: myapp           # matched by name
          resources:
            requests: { cpu: "500m", memory: "512Mi" }

JSON 6902 — precise operations, needed for list-by-index or remove:

patches:
  - target: { kind: Deployment, name: myapp }
    patch: |
      - op: add
        path: /spec/template/spec/containers/0/env/-
        value: { name: LOG_LEVEL, value: debug }
      - op: replace
        path: /spec/strategy/type
        value: Recreate

Generators

configMapGenerator:
  - name: app-config
    files: [config/app.yaml]
    literals: [LOG_LEVEL=info]
secretGenerator:
  - name: app-secret
    envs: [secret.env]           # keep this file out of git / use SOPS
generatorOptions:
  disableNameSuffixHash: false    # default: appends a content hash to the name

The name suffix hash is a feature: change the ConfigMap content → the generated name changes → the Deployment referencing it changes → a rollout happens automatically. Downside: anything referencing the ConfigMap by a fixed name (outside kustomize) breaks. disableNameSuffixHash: true if you need a stable name (and then handle rollouts yourself).

Components

Reusable, optional feature bundles (a monitoring sidecar, an mTLS config) that overlays can components: in — DRY across many overlays.

Verification and troubleshooting

kubectl kustomize overlays/prod | less        # what will be applied
kubectl kustomize overlays/prod | kubectl diff -f -
kustomize build overlays/prod --enable-helm   # if you inline Helm charts
  • Patch not appliedmetadata.name in the patch doesn't match the base resource (including any namePrefix — patches target the pre-prefix name), wrong apiVersion/kind, or the field path is wrong (JSON patch). Render and diff.
  • "no matches for Id ..." — the patch targets a resource not in resources, or the name/kind is off. For JSON patches use the exact target:.
  • ConfigMap name has a weird -abc123 suffix and a Service/other ref can't find it — the generator hash. If the reference is inside kustomize it's rewritten automatically; if it's external, disableNameSuffixHash: true.
  • commonLabels broke a rolling updatecommonLabels (old) also sets selector labels, and selectors are immutable. Use the newer labels: with includeSelectors: false for labels that shouldn't touch the selector.
  • Overlay pulls a stale base — remote bases (resources: - github.com/...?ref=...) are cached; pin a ref and kustomize build with --load-restrictor / clear the cache.
  • Image tag not overridden — the container's image: name in the base must match the images: - name: exactly (repo path included or not, consistently).
  • Helm chart inflation fails — needs --enable-helm and the helmCharts: field; kustomize's Helm support is limited (no hooks).
PrabathStuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.