Kustomize overlays

Kubernetes · Practical · 10 min

You need dev, staging and prod variants of the same manifests without copy-pasting them.

Kustomize builds manifests from a kustomization.yaml without templates: the YAML stays valid Kubernetes YAML, and changes are layered on top. It is built into kubectl (kubectl apply -k dir/, kubectl kustomize dir/ to print the result).

The usual layout is a base with the shared manifests and an overlay per environment that references it:

  • resources: files or directories to include (an overlay lists the base).
  • namespace, namePrefix/nameSuffix, labels: applied to everything.
  • images: change image names or tags without touching the Deployment.
  • replicas: change replica counts.
  • patches: strategic-merge or JSON 6902 patches for anything else.
  • configMapGenerator / secretGenerator: build ConfigMaps from files or literals, adding a content hash to the name and updating references, so a config change triggers a rolling update automatically.

Kustomize versus Helm: Kustomize is great for your own apps' environment differences and for patching third-party YAML; Helm is better for distributing configurable packages to others. Many teams use both, for example applying a Kustomize patch on top of a rendered Helm chart.

CI pipelines and GitOps tools (Argo CD, Flux) understand Kustomize directories natively.

Example

# base/kustomization.yaml
resources: [deployment.yaml, service.yaml]

# overlays/prod/kustomization.yaml
resources: [../../base]
namespace: shop-prod
images:
  - name: ghcr.io/acme/web
    newTag: "1.5.0"
replicas:
  - {name: web, count: 6}
configMapGenerator:
  - name: web-config
    literals: [LOG_LEVEL=warn]
patches:
  - target: {kind: Deployment, name: web}
    patch: |-
      - op: add
        path: /spec/template/spec/containers/0/resources
        value: {requests: {cpu: 500m, memory: 1Gi}}
# kubectl kustomize overlays/prod | less ; kubectl apply -k overlays/prod

Remember

  • Base plus per-environment overlays, no templating
  • images, replicas, patches and generators cover most changes
  • Generated ConfigMaps get a hash suffix, so changes roll pods

Watch out for

  • Copying the whole base into each environment instead of patching only the differences.

Check yourself

  1. Why does configMapGenerator append a hash to the ConfigMap's name?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/