Kubernetes kustomization.yaml Guide
Write kustomization.yaml files for Kubernetes resource management. Overlays, patches, generators, transformers, and multi-environment deployment patterns.
π‘ Quick Answer:
kustomization.yamlis the manifest file for Kustomize β it declares which resources to include, patches to apply, and generators to run. Usekubectl apply -k ./to deploy. Overlays extend a base for different environments without duplicating YAML.
The Problem
Managing Kubernetes manifests across environments means:
- Duplicating YAML files with minor differences (dev vs staging vs prod)
- Forgetting to update all copies when base config changes
- No templating needed β just declarative patching
- Want to use
kubectlnatively without Helm
The Solution
Basic kustomization.yaml
# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# Resources to include
resources:
- deployment.yaml
- service.yaml
- configmap.yaml
# Common labels applied to ALL resources
commonLabels:
app: myapp
team: platform
# Common annotations
commonAnnotations:
managed-by: kustomize
# Namespace override (applies to all resources)
namespace: production
# Name prefix/suffix
namePrefix: prod-
nameSuffix: -v2# Preview rendered output
kubectl kustomize ./
# Apply directly
kubectl apply -k ./Directory Structure
myapp/
βββ base/
β βββ kustomization.yaml
β βββ deployment.yaml
β βββ service.yaml
β βββ configmap.yaml
βββ overlays/
βββ dev/
β βββ kustomization.yaml
β βββ replica-patch.yaml
βββ staging/
β βββ kustomization.yaml
β βββ resource-patch.yaml
βββ prod/
βββ kustomization.yaml
βββ replica-patch.yaml
βββ hpa.yamlBase kustomization.yaml
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yamlOverlay kustomization.yaml
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base # Include base resources
- hpa.yaml # Additional prod-only resources
namespace: production
# Strategic merge patch
patches:
- path: replica-patch.yaml
# Or inline patch:
- patch: |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 5
# Image override
images:
- name: myapp
newName: registry.example.com/myapp
newTag: v1.2.3
# ConfigMap generator
configMapGenerator:
- name: app-config
literals:
- LOG_LEVEL=info
- DB_HOST=postgres.production.svc
files:
- configs/app.properties
# Secret generator
secretGenerator:
- name: app-secrets
literals:
- API_KEY=supersecret
type: OpaquePatches
# Strategic Merge Patch (overlays/prod/replica-patch.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 5
template:
spec:
containers:
- name: app
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "1Gi"# JSON6902 Patch (more precise)
# kustomization.yaml
patches:
- target:
kind: Deployment
name: myapp
patch: |-
- op: replace
path: /spec/replicas
value: 5
- op: add
path: /metadata/annotations/deploy-env
value: productionConfigMap and Secret Generators
# kustomization.yaml
configMapGenerator:
# From literal values
- name: app-env
literals:
- DATABASE_URL=postgres://db:5432/app
- REDIS_URL=redis://redis:6379
# From files
- name: nginx-config
files:
- nginx.conf
- mime.types
# From env file
- name: dotenv
envs:
- .env.production
secretGenerator:
- name: tls-certs
files:
- tls.crt=certs/server.crt
- tls.key=certs/server.key
type: kubernetes.io/tls
# Disable hash suffix (not recommended for production)
generatorOptions:
disableNameSuffixHash: trueArchitecture
graph TD
A[base/kustomization.yaml] --> B[Base Resources]
C[overlays/dev/kustomization.yaml] -->|references| A
C --> D[Dev Patches]
C --> E[Dev Output]
F[overlays/prod/kustomization.yaml] -->|references| A
F --> G[Prod Patches]
F --> H[Prod Output]
E -->|kubectl apply -k overlays/dev/| I[Dev Cluster]
H -->|kubectl apply -k overlays/prod/| J[Prod Cluster]Image Transformers
# Override image tags without patching
images:
- name: nginx # Match container image name
newName: my-registry.com/nginx
newTag: "1.27-alpine"
- name: myapp
newTag: "abc123" # Git SHA as tag
digest: sha256:abc... # Or pin by digestCommon Issues
| Issue | Cause | Fix |
|---|---|---|
| βno matches for kind Kustomizationβ | Missing apiVersion field | Add apiVersion: kustomize.config.k8s.io/v1beta1 |
| Resource not found in base | Wrong relative path | Use ../../base from overlay |
| Patch doesnβt apply | Name mismatch between patch and resource | Ensure metadata.name matches exactly |
| ConfigMap hash changes break refs | Hash suffix changes on content update | Use generatorOptions.disableNameSuffixHash or let rolling update handle it |
| Duplicate resource error | Same resource in base and overlay resources | Only add NEW resources in overlay |
Best Practices
- Keep base minimal β only shared config; all env-specific goes in overlays
- Use
imagestransformer β never hardcode tags in base YAML - Keep hash suffix enabled β triggers automatic rollout on config changes
- One overlay per environment β dev, staging, prod as separate directories
- Commit rendered output in CI β
kubectl kustomize ./ > rendered.yamlfor review
Key Takeaways
kustomization.yamlis declarative config management β no templating, just patching- Base + Overlays pattern eliminates YAML duplication across environments
configMapGenerator/secretGeneratorcreate resources with content-hash suffixesimagestransformer overrides tags without touching base files β perfect for CI/CD- Built into
kubectlβ no extra tooling needed (kubectl apply -k ./)

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
