Skip to main content

Command Palette

Search for a command to run...

Kustomize in Kubernetes: Managing Multiple Environments with Transformers

Updated
7 min read
Kustomize in Kubernetes: Managing Multiple Environments with Transformers

Introduction

One of the biggest challenges in Kubernetes is managing the same application across multiple environments such as Development, Staging, and Production.

At first, teams often solve this by maintaining separate YAML files for each environment:

dev-deployment.yaml
staging-deployment.yaml
prod-deployment.yaml

While this works initially, it quickly becomes difficult to maintain.

Imagine updating:

  • Container images

  • Labels

  • Resource limits

  • Replica counts

  • Namespaces

across dozens of files.

This leads to:

❌ Configuration drift

❌ Duplicate manifests

❌ Increased maintenance effort

❌ Higher risk of deployment mistakes

This is the problem Kustomize was built to solve.


Kustomize in Kubernetes: Base and Overlay Explained

As Kubernetes deployments grow, managing separate YAML files for Development, Staging, and Production quickly becomes difficult.

Imagine maintaining the same Deployment, Service, ConfigMap, and Secret definitions for multiple environments. The only difference might be:

  • Replica count

  • Image version

  • Resource limits

  • Configuration values

Copying and maintaining separate YAML files for every environment leads to duplication, configuration drift, and operational headaches.

This is the exact problem Kustomize was designed to solve.


What is Kustomize?

Kustomize is a Kubernetes-native configuration management tool that allows you to customize Kubernetes manifests without modifying the original YAML files.

Unlike Helm, Kustomize does not use templates.

Instead, it works with:

  • A shared Base

  • Environment-specific Overlays

The result is a clean, reusable, and easy-to-maintain Kubernetes configuration structure.

One major advantage is that Kustomize is built directly into kubectl, so no additional installation is required for most use cases.

kubectl apply -k .

The Problem Kustomize Solves

Consider an application deployed to three environments:

Development:

replicas: 1

Staging:

replicas: 2

Production:

replicas: 5

Without Kustomize, you would typically maintain three separate Deployment files.

That means if you update:

  • Container image

  • Labels

  • Ports

  • Resource limits

You must update all three files.

This duplication increases maintenance effort and introduces risk.

Kustomize eliminates this by keeping a single source of truth and applying only environment-specific changes where needed.


Base and Overlay Architecture

Kustomize follows a simple structure:

Base

The base contains common Kubernetes resources shared by all environments.

Example:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      component: nginx
  template:
    metadata:
      labels:
        component: nginx
    spec:
      containers:
      - name: nginx
        image: nginx

The base acts as the foundation.


Overlays

Overlays contain only the changes required for a specific environment.

Development

spec:
  replicas: 1

Staging

spec:
  replicas: 1

Production

spec:
  replicas: 5

Each environment reuses the same base configuration while applying its own customizations.


A common Kustomize project structure looks like:

k8s/
├── base/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── kustomization.yaml
│
└── overlays/
    ├── dev/
    │   └── kustomization.yaml
    │
    ├── stg/
    │   └── kustomization.yaml
    │
    └── prod/
        └── kustomization.yaml

Base

Contains resources shared across environments.

Overlays

Contain environment-specific modifications.

This structure keeps Kubernetes manifests organized and scalable as applications grow.


Understanding the kustomization.yaml File

The heart of Kustomize is the kustomization.yaml file.

It tells Kustomize:

  1. Which resources to manage

  2. Which customizations to apply

Example:

resources:
  - deployment.yaml
  - service.yaml

commonLabels:
  app: nginx

In this example:

  • Deployment and Service are included

  • A common label is added to all resources

Think of kustomization.yaml as the entry point for Kustomize processing.

Building Kubernetes Manifests

Kustomize does not directly deploy resources.

Instead, it generates the final YAML after applying all customizations.

kustomize build k8s/

This command outputs the fully rendered Kubernetes manifests.

Applying Kustomize Configurations

You can pipe the output to kubectl:

kustomize build k8s/ | kubectl apply -f -

Or use the built-in kubectl integration:

kubectl apply -k k8s/

This is the most common approach used in modern Kubernetes workflows.

Deleting Resources Managed by Kustomize

Just as easily, you can remove resources:

kubectl delete -k k8s/

or

kustomize build k8s/ | kubectl delete -f -

Managing Large Applications

As applications grow, a single folder becomes difficult to maintain.

Instead, resources can be organized by component.

Example:

k8s/
├── api/
├── db/
├── cache/
└── kafka/

Each directory contains its own manifests.

A top-level kustomization.yaml can then aggregate everything:

resources:
  - api/
  - db/
  - cache/
  - kafka/

This creates a modular and scalable structure for large Kubernetes applications.


Kustomize vs Helm

A common question is:

Why use Kustomize when Helm already exists?

Kustomize

✅ Built into kubectl
✅ Uses plain YAML
✅ Easier to read and review
✅ No templating language to learn

Helm

✅ Package manager for Kubernetes
✅ Supports loops and conditionals
✅ Supports chart repositories
✅ Better for distributing applications

A simple rule of thumb:

  • Use Kustomize when customizing existing manifests across environments.

  • Use Helm when packaging and distributing applications.

Many organizations actually use both together.


Kustomize Transformers

Once resources are organized, Kustomize provides Transformers to apply bulk changes across all resources.

Transformers eliminate the need to edit every manifest individually.

Common Labels Transformer

Labels are frequently used for:

  • Ownership

  • Cost allocation

  • Environment tracking

  • Governance

Instead of adding labels manually:

commonLabels:
  org: my-company

Kustomize injects the label across all managed resources.

Result

metadata:
  labels:
    org: my-company

This also updates selectors where appropriate.

Namespace Transformer

Deploying resources into a namespace often requires editing every YAML file.

Kustomize can do this automatically.

namespace: production

Result

metadata:
  namespace: production

Every resource receives the namespace.

CommonAnnotations Transformer

Annotations store metadata that is not used for resource selection.

Examples:

  • Git commit IDs

  • Build numbers

  • Deployment timestamps

  • Branch names

Configuration:

annotations:
    branch: main

Result:

metadata:
  annotations:
    branch: main

A CI/CD pipeline can dynamically inject:

commonAnnotations:
  build-number: "105"
  git-commit: "abc123"

making deployments fully traceable.


Name Prefix Transformer

Add a common prefix to all resources.

Configuration:

namePrefix: company-

Before:

name: api-service

After:

name: company-api-service

Name Suffix Transformer

Add a common suffix to all resources.

Configuration:

nameSuffix: -prod

Before:

name: api-service

After:

name: api-service-prod

Combining Prefix and Suffix

Both can be combined:

namePrefix: company-
nameSuffix: -dev

Result:

name: company-api-service-dev

This is useful for enforcing naming standards across environments.


Image Transformer

One of the most powerful Kustomize features is image management.

Suppose your Deployment contains:

containers:
- image: nginx

You can update the image version without modifying the Deployment file.

Updating Tags

images:
- name: nginx
  newTag: "2.4"

Result:

image: nginx:2.4

Perfect for CI/CD pipelines where image tags change frequently.

Replacing Images

Kustomize can also replace an image entirely.

Configuration:

images:
- name: nginx
  newName: haproxy
  newTag: "2.4"

Result:

image: haproxy:2.4

This allows different environments to use different container images while sharing the same base manifests.


Real-World Example

Base Configuration

resources:
- deployment.yaml
- service.yaml

Development Overlay

nameSuffix: -dev

commonLabels:
  env: dev

images:
- name: nginx
  newTag: "1.25"

Production Overlay

nameSuffix: -prod

commonLabels:
  env: prod

images:
- name: nginx
  newTag: "1.28"

replicas: 5

The same application now supports multiple environments without duplicating manifests.


Key Takeaways

Kustomize helps teams manage Kubernetes configurations by separating:

Base Configuration

What remains the same across environments.

Overlays

What changes between environments.

Combined with transformers, Kustomize enables:

✅ Environment-specific deployments
✅ Reusable manifests
✅ Consistent naming conventions
✅ Automated image updates
✅ Cleaner repositories
✅ Reduced configuration drift

For teams that prefer plain YAML over templates, Kustomize offers one of the cleanest approaches to Kubernetes configuration management.