πŸ“šBook Signing at KubeCon EU 2026Meet us at Booking.com HQ (Mon 18:30-21:00) & vCluster booth #521 (Tue 24 Mar, 12:30-1:30pm) β€” free book giveaway!RSVP Booking.com Event
Configuration intermediate ⏱ 15 minutes K8s 1.21+

Kubernetes kustomization.yaml Guide

Write kustomization.yaml files for Kubernetes resource management. Overlays, patches, generators, transformers, and multi-environment deployment patterns.

By Luca Berton β€’ β€’ πŸ“– 5 min read

πŸ’‘ Quick Answer: kustomization.yaml is the manifest file for Kustomize β€” it declares which resources to include, patches to apply, and generators to run. Use kubectl 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 kubectl natively 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.yaml

Base kustomization.yaml

# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml

Overlay 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: Opaque

Patches

# 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: production

ConfigMap 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: true

Architecture

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 digest

Common Issues

IssueCauseFix
”no matches for kind Kustomization”Missing apiVersion fieldAdd apiVersion: kustomize.config.k8s.io/v1beta1
Resource not found in baseWrong relative pathUse ../../base from overlay
Patch doesn’t applyName mismatch between patch and resourceEnsure metadata.name matches exactly
ConfigMap hash changes break refsHash suffix changes on content updateUse generatorOptions.disableNameSuffixHash or let rolling update handle it
Duplicate resource errorSame resource in base and overlay resourcesOnly add NEW resources in overlay

Best Practices

  1. Keep base minimal β€” only shared config; all env-specific goes in overlays
  2. Use images transformer β€” never hardcode tags in base YAML
  3. Keep hash suffix enabled β€” triggers automatic rollout on config changes
  4. One overlay per environment β€” dev, staging, prod as separate directories
  5. Commit rendered output in CI β€” kubectl kustomize ./ > rendered.yaml for review

Key Takeaways

  • kustomization.yaml is declarative config management β€” no templating, just patching
  • Base + Overlays pattern eliminates YAML duplication across environments
  • configMapGenerator / secretGenerator create resources with content-hash suffixes
  • images transformer overrides tags without touching base files β€” perfect for CI/CD
  • Built into kubectl β€” no extra tooling needed (kubectl apply -k ./)
#kustomize #kustomization #configuration #overlays #gitops
Luca Berton
Written by Luca Berton

Principal Solutions Architect specializing in Kubernetes, AI/GPU infrastructure, and cloud-native platforms. Author of Kubernetes Recipes and creator of CopyPasteLearn courses.

Kubernetes Recipes book cover

Want More Kubernetes Recipes?

This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.

Luca Berton Ansible Pilot Ansible by Example Open Empower K8s Recipes Terraform Pilot CopyPasteLearn ProteinLens