Back to Distributed Systems & Kubernetes Series

Kustomize Track Part 2: Patches & SecretGenerator

June 6, 2026 Wasil Zafar 30 min read

Patches let you surgically modify specific fields in your base manifests — update replicas in production, add resource limits in staging, change environment variables per cluster. SecretGenerator and ConfigMapGenerator create resources from literals or files, with automatic content hashing for rolling updates.

Table of Contents

  1. Strategic Merge Patches
  2. JSON 6902 Patches
  3. ConfigMapGenerator
  4. SecretGenerator
  5. Kustomize Components
  6. Exercises
  7. Key Takeaways

Strategic Merge Patches

Strategic merge patches are the most natural Kustomize patch type. You write a partial YAML that mirrors the structure of the resource you want to modify — Kustomize merges the patch into the base, field by field.

Inline Patches

# kustomization.yaml — inline patches (Kustomize v4.0+)
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base

patches:
  # Patch 1: Increase replicas for production
  - patch: |
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: grade-api
      spec:
        replicas: 3
    target:
      kind: Deployment
      name: grade-api

  # Patch 2: Add resource limits (absent from base)
  - patch: |
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: grade-api
      spec:
        template:
          spec:
            containers:
              - name: grade-api
                resources:
                  requests:
                    cpu: "200m"
                    memory: "256Mi"
                  limits:
                    cpu: "1000m"
                    memory: "512Mi"

  # Patch 3: Override an environment variable
  - patch: |
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: grade-api
      spec:
        template:
          spec:
            containers:
              - name: grade-api
                env:
                  - name: LOG_LEVEL
                    value: "warn"   # Overrides base value "info"

File Patches

# kustomization.yaml — reference patch files
patches:
  - path: replicas-patch.yaml
  - path: resources-patch.yaml
    target:
      kind: Deployment
      labelSelector: "app=grade-api"
# overlays/production/replicas-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: grade-api          # Must match base resource name
spec:
  replicas: 5              # Overrides base replicas

JSON 6902 Patches

JSON Patch (RFC 6902) gives you precise operations: add, remove, replace, move, copy, test. Unlike strategic merge patches, you specify the exact JSON Pointer path to modify.

# kustomization.yaml with JSON 6902 patches
patches:
  # Replace a specific field by path
  - patch: |
      - op: replace
        path: /spec/replicas
        value: 5
    target:
      kind: Deployment
      name: grade-api

  # Add a new annotation
  - patch: |
      - op: add
        path: /metadata/annotations/deploy-time
        value: "2026-06-06"
    target:
      kind: Deployment

  # Remove a field entirely
  - patch: |
      - op: remove
        path: /spec/template/spec/containers/0/livenessProbe
    target:
      kind: Deployment
      name: grade-api

  # Add an item to an array
  - patch: |
      - op: add
        path: /spec/template/spec/containers/0/env/-
        value:
          name: EXTRA_VAR
          value: "extra-value"
    target:
      kind: Deployment
      name: grade-api
When to use which patch type: Use strategic merge patches when you want to merge/override entire sub-objects (containers, env vars). Use JSON 6902 patches when you need to add/remove array items by index, or when the field doesn't exist in the base and strategic merge might not find the right merge key.

ConfigMapGenerator

# kustomization.yaml
configMapGenerator:
  # From literals
  - name: app-config
    literals:
      - LOG_LEVEL=info
      - DB_POOL_SIZE=10
      - ENVIRONMENT=production

  # From a .env file
  - name: feature-flags
    envs:
      - feature-flags.env    # KEY=VALUE format file

  # From file contents (entire file as a config value)
  - name: nginx-config
    files:
      - nginx.conf
      - conf.d/default.conf=custom-default.conf   # key=filename

  # Merge multiple sources
  - name: combined-config
    literals:
      - APP_NAME=grade-api
    envs:
      - base-config.env
    behavior: merge          # merge | replace | create (default: create)
# feature-flags.env
FEATURE_NEW_GRADING=true
FEATURE_ANALYTICS=false
FEATURE_EXPORT_PDF=true
# Build and inspect the generated ConfigMap
kubectl kustomize ./overlays/production | grep -A 20 "kind: ConfigMap"
# The ConfigMap gets a content hash suffix:
# name: app-config-7h9k8m2t4f
# This suffix changes when the content changes,
# triggering a rolling update to Pods that reference it.

# To disable the hash suffix:
# generatorOptions:
#   disableNameSuffixHash: true

SecretGenerator

# secretGenerator creates Secrets with base64 encoding automatically
secretGenerator:
  # From literals (values stored in base64 in the Secret)
  - name: db-credentials
    literals:
      - DB_PASSWORD=super-secret-password
      - DB_USERNAME=grade_api_user
    type: Opaque

  # From files (e.g., TLS certificates)
  - name: tls-cert
    files:
      - tls.crt
      - tls.key
    type: kubernetes.io/tls

  # From a .env file
  - name: api-secrets
    envs:
      - secrets.env
# IMPORTANT: Never commit secrets.env or secret literal values to Git!
# SecretGenerator is useful for local development and CI where you
# can inject secrets via files/env vars without storing them in Git.
#
# For production, use:
# - External Secrets Operator (pulls from Vault, AWS SSM, GCP SM)
# - Sealed Secrets (encrypts before Git commit)
# - Flux's postBuild.substituteFrom with cluster Secrets
# generatorOptions applies to all generators in the file
generatorOptions:
  disableNameSuffixHash: true     # Don't add content hash suffix
  labels:
    app.kubernetes.io/managed-by: kustomize
  annotations:
    note: auto-generated-by-kustomize
  immutable: true                 # Make generated ConfigMap/Secret immutable

Kustomize Components

Components (introduced in Kustomize v3.7) let you create reusable patch bundles that can be included in any overlay without being a full base:

# Directory structure with components
base/
  deployment.yaml
  service.yaml
  kustomization.yaml
components/
  metrics/
    kustomization.yaml     # apiVersion: kustomize.config.k8s.io/v1alpha1, kind: Component
    servicemonitor.yaml
  tracing/
    kustomization.yaml
    env-patch.yaml
overlays/
  production/
    kustomization.yaml     # includes components/metrics and components/tracing
  staging/
    kustomization.yaml     # includes only components/metrics
# components/metrics/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1alpha1
kind: Component             # Not 'Kustomization' — this is a Component
resources:
  - servicemonitor.yaml
patches:
  - patch: |
      - op: add
        path: /spec/template/spec/containers/0/ports/-
        value:
          name: metrics
          containerPort: 9090
    target:
      kind: Deployment
# overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base
components:
  - ../../components/metrics
  - ../../components/tracing
patches:
  - path: replicas-patch.yaml
images:
  - name: ghcr.io/your-org/grade-api
    newTag: v1.5.2

Exercises

Exercise 1 — Patch Chain: Create a base Deployment with 1 replica and no resource limits. Create a staging overlay that adds resource limits via a strategic merge patch. Create a production overlay that additionally sets 3 replicas via a JSON 6902 patch. Build both and compare.
Exercise 2 — ConfigMapGenerator: Create a ConfigMapGenerator from a .env file and literals. Apply to a cluster. Change one value in the .env file and re-apply. Observe: the ConfigMap name changes (new hash suffix), and Pods are rolling-updated automatically.
Exercise 3 — Component: Create a Kustomize Component that adds a sidecar container (e.g., a log forwarder). Include it in a production overlay but not a staging overlay. Build both overlays and verify the sidecar only appears in production.

Key Takeaways

Key Takeaways:
  • Strategic merge patches are the most readable — they look like partial versions of the resource being patched
  • JSON 6902 patches are more precise — use them for array operations and adding fields that don't exist in the base
  • ConfigMapGenerator auto-hashes content — the name suffix changes when content changes, guaranteeing rolling updates
  • SecretGenerator is convenient for local dev/CI; use External Secrets or Sealed Secrets for production
  • Components are reusable patch bundles — include them selectively in overlays to compose environment-specific features
  • The Flux Kustomization CRD runs kustomize build internally — these Kustomize files are exactly what Flux consumes