EthicsComputerCourses
Join training +91 90532 10052

Kustomize: Bases & Overlays

Kubernetes · Lesson 25 of 30 Advanced 7 min read Updated

Helm solves "same app, different settings" with templates. Kustomize takes the opposite approach: no templates at all. You keep ordinary, valid YAML as a base, and each environment has a small overlay that says how to change it: a different image tag, more replicas, a name prefix, a patch. Kustomize is built into kubectl (you saw Kustomize Version: v5.8.1 in kubectl version), so there is nothing extra to install.

In this lesson you will turn the menu app into a base with dev and prod overlays, generate ConfigMaps that trigger rollouts when they change, and see when to pick Kustomize or Helm.

The layout

Text
menu/
├── base/
│   ├── kustomization.yaml
│   ├── deployment.yaml
│   └── service.yaml
└── overlays/
    ├── dev/
    │   └── kustomization.yaml
    └── prod/
        ├── kustomization.yaml
        └── resources-patch.yaml

Every folder that Kustomize builds has a kustomization.yaml. The base lists its manifests; deployment.yaml and service.yaml are the plain menu Deployment and Service from earlier lessons, untouched:

YAML
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml
labels:
  - pairs:
      app.kubernetes.io/part-of: tea-stalls

labels adds a label to every object. By default it does not touch selectors, which is what you want, because Deployment selectors cannot change after creation.

An overlay for production

The production overlay points at the base and describes only the differences:

YAML
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: shop-prod
namePrefix: prod-
resources:
  - ../../base
images:
  - name: nginx
    newTag: 1.30-alpine
replicas:
  - name: menu
    count: 4
configMapGenerator:
  - name: menu-settings
    literals:
      - SHOP_CITY=Pune
      - OPEN_HOURS=7am-11pm
patches:
  - path: resources-patch.yaml
    target:
      kind: Deployment
      name: menu
  • namespace puts every object into shop-prod.
  • namePrefix renames everything (menu becomes prod-menu) and updates references to those names, such as a Deployment's reference to its ConfigMap.
  • images changes the tag of every container that uses the image nginx, without touching the YAML in the base.
  • replicas sets the replica count of the named Deployment.
  • configMapGenerator creates a ConfigMap from literals, files or .env files.
  • patches applies a patch file to matching objects.

The patch is a fragment of a Deployment containing only the fields to add or change. Kustomize merges it into the base using the same rules as kubectl apply (a strategic merge patch), which matches list items such as containers by their name:

YAML
# overlays/prod/resources-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: menu
spec:
  template:
    spec:
      containers:
        - name: web
          envFrom:
            - configMapRef:
                name: menu-settings
          resources:
            requests:
              cpu: 100m
              memory: 64Mi
            limits:
              memory: 128Mi

Notice that the patch uses the base names, menu and menu-settings; Kustomize applies the prefix and the hash suffix afterwards and fixes the references.

Build, preview and apply

Terminal
kubectl kustomize overlays/prod            # print the final YAML
kubectl diff -k overlays/prod              # compare with the cluster
kubectl apply -k overlays/prod             # apply it
kubectl get deployment -n shop-prod
Output
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
prod-menu   4/4     4            4           40s

(The output of the first three commands is long and left out.) -k means "build this folder with Kustomize first", and kubectl kustomize shows exactly what would be sent, so check it before every change. The namespace must exist; add a Namespace manifest to the overlay or create it once by hand.

Why the generated ConfigMap has a hash

In the built output the ConfigMap is not called prod-menu-settings but prod-menu-settings- followed by a short hash of its contents, and the Deployment refers to that full name. Change OPEN_HOURS and the hash changes, so the ConfigMap gets a new name, so the Deployment's Pod template changes, so a normal rolling update starts and the Pods pick up the new settings. This solves the problem from ConfigMaps & Secrets that environment variables never update in running Pods, and a rollback brings back the old settings too. secretGenerator works the same way for Secrets. Old generated ConfigMaps are left behind; tools such as Argo CD can prune them.

A dev overlay

Development is the same app with one replica and the latest test image:

YAML
# overlays/dev/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: shop-dev
namePrefix: dev-
resources:
  - ../../base
images:
  - name: nginx
    newTag: 1.31-alpine
replicas:
  - name: menu
    count: 1

Both overlays share every line of the base. Fix a bug in base/deployment.yaml and both environments get it; change only overlays/prod and only production changes. This "one base, small overlays" shape reads very well in Git reviews.

Kustomize or Helm?

KustomizeHelm
ApproachPatches on plain YAMLTemplates plus values
InstallBuilt into kubectlSeparate CLI
Sharing an app with the worldAwkwardExcellent: versioned charts in repositories
Release history and rollbackNo (use Git)Yes (helm rollback)
Learning curveSmallMedium (template language)

A common pattern is to use Helm for third-party software (databases, ingress or gateway controllers, monitoring) and Kustomize for your own apps. They also combine: Kustomize can render Helm charts, and GitOps tools such as Argo CD and Flux understand both natively, as the next lesson shows.

Common mistakes

  • Patching with the prefixed name. Patches and replicas use the base names (menu), not prod-menu.
  • Applying the base directly in production. Apply the overlay; the base is a shared starting point.
  • Turning on includeSelectors for an existing app. Selectors change and the API server rejects the Deployment.
  • Disabling the ConfigMap hash suffix and then wondering why Pods keep old settings.

Key points

  • Kustomize customises plain YAML with no templates; it is built into kubectl (kubectl kustomize, apply -k, diff -k).
  • A base holds shared manifests; overlays reference the base and add namespaces, prefixes, image tags, replica counts and patches.
  • Strategic merge patches are partial manifests that match list items such as containers by name.
  • configMapGenerator and secretGenerator add a content hash to names, so changes trigger rolling updates.
  • Use Kustomize for your own apps and Helm for packaged third-party software; GitOps tools support both.

Exercise

Add a staging overlay for the menu app: namespace shop-staging, name prefix staging-, 2 replicas, image tag 1.31-alpine, and a generated ConfigMap menu-settings with SHOP_CITY=Kochi. Write its kustomization.yaml and the two commands to preview and apply it.

Show solution
YAML
# overlays/staging/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: shop-staging
namePrefix: staging-
resources:
  - ../../base
images:
  - name: nginx
    newTag: 1.31-alpine
replicas:
  - name: menu
    count: 2
configMapGenerator:
  - name: menu-settings
    literals:
      - SHOP_CITY=Kochi
Terminal
kubectl kustomize overlays/staging
kubectl apply -k overlays/staging

The generated ConfigMap is only used once a container refers to it, so in a real setup you would also copy the envFrom patch from the prod overlay (or move it into the base).

Quick Quiz

1. What does an overlay contain?

2. Why does a ConfigMap from configMapGenerator get a hash in its name?

3. Which command prints the final YAML of an overlay without applying it?

4. With namePrefix: prod-, which name do you use in a patch's target?

Learn Kubernetes with a mentor

Free lessons get you started. Our Cloud & DevOps training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call