11.09 Overlays
Kustomize overlays let you reuse one shared Kubernetes base and apply environment-specific changes for dev, stg, and prod without duplicating full YAML files.
Goal
Keep common manifests in base/, then use overlays to patch or extend them per environment.
Why Overlays?
Without overlays, teams often copy the same YAML files into separate folders:
That works for small labs, but it becomes hard to maintain in production because every change must be copied across environments.
Problem with duplicated YAML
If a new service, label, security setting, probe, or resource limit is added in one environment but forgotten in another, your environments drift.
Kustomize solves this by using:
Base vs Overlay
| Part | Purpose | Example |
|---|---|---|
base/ |
Shared/default Kubernetes configs | Deployment, Service, Redis deployment |
overlays/dev/ |
Development-specific changes | Smaller replica count, debug ConfigMap |
overlays/stg/ |
Staging-specific changes | Medium replica count |
overlays/prod/ |
Production-specific changes | Higher replicas, Grafana, stricter config |
Note
The base is not directly tied to one environment. It is the reusable default configuration.
Recommended Folder Structure
k8s/
├── base/
│ ├── kustomization.yaml
│ ├── nginx-depl.yaml
│ ├── service.yaml
│ └── redis-depl.yaml
└── overlays/
├── dev/
│ ├── kustomization.yaml
│ └── config-map.yaml
├── stg/
│ ├── kustomization.yaml
│ └── config-map.yaml
└── prod/
├── kustomization.yaml
├── config-map.yaml
└── grafana-depl.yaml
Tip
Put shared/default resources in base/. Put environment-specific patches or extra resources in each overlay folder.
Base kustomization.yaml
The base kustomization.yaml lists shared resources.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- nginx-depl.yaml
- service.yaml
- redis-depl.yaml
Example base deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
Note
The base can define default values, such as replicas: 1. Overlays can replace only the values that differ.
Overlay kustomization.yaml
An overlay imports the base using a relative path, then applies patches.
Newer Kustomize syntax
Older examples may use bases:. Modern Kustomize recommends using resources: to reference the base directory.
Relative path
From k8s/overlays/dev/kustomization.yaml, the path ../../base means:
Adding Extra Resources in an Overlay
Overlays are not limited to patches. They can also add new resources that do not exist in the base.
Example: add Grafana only in production.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
- config-map.yaml
- grafana-depl.yaml
patches:
- target:
kind: Deployment
name: nginx-deployment
patch: |-
- op: replace
path: /spec/replicas
value: 3
Success
This keeps Grafana production-only while the base remains clean and reusable.
Feature-Based Overlay Structure
For larger applications, you can organize overlays by feature or component.
k8s/
├── base/
│ ├── db/
│ │ ├── db-depl.yaml
│ │ ├── db-service.yaml
│ │ └── kustomization.yaml
│ ├── api/
│ │ ├── api-depl.yaml
│ │ ├── api-service.yaml
│ │ └── kustomization.yaml
│ └── kustomization.yaml
└── overlays/
├── dev/
│ ├── db/
│ │ ├── db-patch.yaml
│ │ └── kustomization.yaml
│ ├── api/
│ │ ├── api-patch.yaml
│ │ └── kustomization.yaml
│ └── kustomization.yaml
└── prod/
├── db/
│ ├── db-patch.yaml
│ └── kustomization.yaml
├── api/
│ ├── api-patch.yaml
│ └── kustomization.yaml
└── kustomization.yaml
Tip
Your base and overlay subdirectories do not have to match exactly, but they must import the correct resources through kustomization.yaml.
Build and Apply
Note
kustomize build only renders YAML. It does not deploy anything unless you pipe it to kubectl apply -f - or use kubectl apply -k.
Common Overlay Use Cases
| Use Case | Dev | Staging | Production |
|---|---|---|---|
| Replicas | 1 or 2 | 2 or 3 | 3+ |
| Resource limits | Low | Medium | Strictly defined |
| ConfigMaps | Debug config | Pre-prod config | Production config |
| Extra tools | Optional | Optional | Monitoring/logging |
| Namespaces | dev |
stg |
prod |
| Image tags | Fast-moving | Release candidate | Stable version |
Example
A production overlay may add Grafana, stricter resource limits, higher replicas, and production-only ConfigMaps.
Production Best Practices
Do
- Keep
base/small, reusable, and environment-neutral. - Use overlays for environment-specific changes only.
- Use separate overlays for
dev,stg, andprod. - Validate output with
kustomize buildbefore applying. - Commit rendered changes through pull requests when using GitOps.
- Keep patches focused and easy to review.
- Use clear folder names such as
overlays/dev,overlays/stg, andoverlays/prod.
Don't
- Do not duplicate full YAML files across environments.
- Do not put production-only resources in the base.
- Do not hardcode secrets in overlay YAML files.
- Do not mix unrelated changes in one large patch.
- Do not apply overlays without reviewing the final rendered output.
- Do not let environment overlays drift without review.
Common mistake
Adding a patch in an overlay but forgetting to import the base with ../../base means Kustomize has nothing to patch.
Do and Don't Summary
| Do | Don't |
|---|---|
Use base/ for shared defaults |
Copy the same YAML into every environment |
| Use overlays for environment-specific config | Edit base directly for production-only needs |
Preview with kustomize build |
Apply blindly |
Add extra prod-only resources in overlays/prod |
Put prod-only tools into base |
| Keep patches small | Create huge unreadable patch files |
Quick Troubleshooting
Why did my patch not apply?
Check that the target.name, target.kind, and resource name match exactly.
Why is Kustomize unable to find the base?
Verify the relative path from the overlay file. From k8s/overlays/dev, the base path is usually:
Why did a resource appear only in prod?
It is likely listed only in overlays/prod/kustomization.yaml, such as:
Avoid environment drift
If dev, stg, and prod behave differently, confirm whether the difference is intentional and documented in the overlay.
Final Mental Model
Quote
Base is the common starting point. Overlay is the environment-specific change layer. Kustomize combines both and produces the final Kubernetes manifest.
base/
shared defaults
overlays/dev/
dev patches + dev-only resources
overlays/stg/
staging patches + staging-only resources
overlays/prod/
production patches + production-only resources
Success
This gives you clean, reusable, production-friendly Kubernetes configuration management without copying YAML across environments.