Skip to content

11.02 Kustomize vs Helm

Abstract

Kustomize and Helm both help manage Kubernetes YAML across multiple environments, but they solve the problem differently.

  • Kustomize customizes plain YAML using base + overlays
  • Helm generates YAML using templates + values files

Why Compare Kustomize and Helm?

In production Kubernetes, the same application often needs different settings for each environment.

Example:

Environment Replica Count Image Tag
dev 1 dev
stg 2 stg
prod 5 2.4.4

Instead of manually editing YAML files for every environment, teams use tools like Kustomize or Helm.

Question

Which one should you use?

It depends on whether you need simple YAML customization or full application packaging and lifecycle management.


Helm Approach

Helm uses Go templating syntax inside Kubernetes manifests.

Instead of hardcoding values, Helm uses variables such as:

replicas: {{ .Values.replicaCount }}

and:

image: "nginx:{{ .Values.image.tag }}"

These values are supplied from a values.yaml file.

replicaCount: 1

image:
  tag: "2.4.4"

Note

Helm templates are not pure Kubernetes YAML until Helm renders them.


Helm Template Example

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Values.name }}
  template:
    metadata:
      labels:
        app: {{ .Values.name }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "nginx:{{ .Values.image.tag }}"

Corresponding values.yaml:

name: nginx-app
replicaCount: 1

image:
  tag: "2.4.4"

Example

Helm replaces template variables with values from values.yaml during install or upgrade.


Helm Environment Structure

A common Helm structure for multiple environments:

k8s/
├── environments/
│   ├── values.dev.yaml
│   ├── values.stg.yaml
│   └── values.prod.yaml
└── templates/
    ├── nginx-deployment.yaml
    ├── nginx-service.yaml
    ├── db-deployment.yaml
    └── db-service.yaml

Install with environment-specific values:

helm install nginx-app ./k8s -f environments/values.dev.yaml
helm install nginx-app ./k8s -f environments/values.stg.yaml
helm install nginx-app ./k8s -f environments/values.prod.yaml

Tip

Use separate values files for each environment instead of editing templates directly.


Kustomize Approach

Kustomize does not use templates.

It keeps Kubernetes YAML as plain YAML and modifies it using overlays.

base/
  deployment.yaml
  service.yaml

overlays/
  dev/
  stg/
  prod/

Apply environment-specific configuration:

kubectl apply -k overlays/dev
kubectl apply -k overlays/stg
kubectl apply -k overlays/prod

Success

Kustomize is simpler because the manifests remain valid YAML.


Kustomize Structure Example

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

Production patch example:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 5

Note

Kustomize modifies existing YAML instead of generating YAML from templates.


Main Difference

Area Kustomize Helm
Style Overlay-based Template-based
YAML readability Plain YAML Go templates inside YAML
Complexity Lower Higher
Built into kubectl Yes No, separate CLI
Package manager No Yes
Release tracking No Yes
Rollback support No native release rollback Yes
Best use case Environment-specific YAML customization Application packaging and lifecycle management

Kustomize vs Helm Workflow

Base YAML
   +
Overlay patches
Final Kubernetes YAML
kubectl kustomize overlays/prod
kubectl apply -k overlays/prod

Best when you want simple environment customization using plain YAML.

Templates
   +
values.yaml
Rendered Kubernetes YAML
Helm release
helm template nginx-app ./chart -f values.prod.yaml
helm install nginx-app ./chart -f values.prod.yaml

Best when you want package management, upgrades, rollbacks, and reusable charts.


When to Use Kustomize

Use Kustomize when:

  • You want plain Kubernetes YAML
  • You need simple dev/stg/prod differences
  • You want fewer abstractions
  • You do not need release tracking
  • You are using GitOps tools like Argo CD or Flux
  • Your team prefers readable manifests

Good fit

Kustomize is a strong choice for internal platform manifests, environment overlays, and GitOps repositories.


When to Use Helm

Use Helm when:

  • You need to package a full application
  • You want install, upgrade, rollback, and uninstall commands
  • You want to use public charts like Bitnami, Prometheus, or NGINX
  • You need loops, conditionals, functions, or hooks
  • You want release history
  • You distribute applications across teams or customers

Good fit

Helm is a strong choice for reusable application packages and third-party software installation.


Helm Strengths

  • Complete Kubernetes package manager
  • Supports release lifecycle management
  • Supports install, upgrade, rollback, and uninstall
  • Supports reusable public charts
  • Supports functions, conditionals, loops, and hooks
  • Good for complex applications like WordPress, Prometheus, Grafana, and cert-manager
helm install my-release bitnami/wordpress
helm upgrade my-release bitnami/wordpress
helm rollback my-release 1
helm uninstall my-release

Tip

Use Helm when you need application lifecycle management, not just YAML customization.


Helm Limitations

Warning

Helm templates can become difficult to read when charts grow large.

Common issues:

  • Template syntax can make YAML harder to understand
  • Debugging rendered output may take extra steps
  • Chart behavior may be hidden behind variables and conditions
  • Bad charts can generate unsafe or unexpected resources
  • Values files can become large and complex

Preview rendered YAML before applying:

helm template my-release ./chart -f values.prod.yaml

Kustomize Strengths

  • Uses plain YAML
  • Easier to read and review
  • Built into kubectl
  • No separate templating language
  • Good for GitOps workflows
  • Clean environment-specific overlays
  • Easy to see exactly what changes between environments
kubectl kustomize overlays/prod
kubectl apply -k overlays/prod

Tip

Use Kustomize when your main goal is clean environment customization.


Kustomize Limitations

Warning

Kustomize is not a full package manager.

Limitations:

  • No native release tracking
  • No built-in rollback history like Helm
  • No chart repository model
  • No native lifecycle hooks like Helm
  • Can become hard to manage if overlays are deeply nested or overused

Production Decision Guide

Requirement Recommended Tool
Simple environment customization Kustomize
Plain readable YAML Kustomize
GitOps environment overlays Kustomize
Installing third-party apps Helm
Application packaging Helm
Rollbacks and release history Helm
Complex reusable app deployment Helm
Advanced templating logic Helm

Example

A common production pattern is to use Helm to install vendor applications and Kustomize to manage environment-specific overlays.


Production Best Practices

Recommended

  • Preview rendered manifests before applying
  • Keep environment-specific values separate
  • Store all manifests and values files in Git
  • Avoid hardcoding secrets in YAML
  • Use immutable image tags in production
  • Validate generated manifests in CI
  • Keep Helm values files small and documented
  • Keep Kustomize overlays focused and minimal
  • Use GitOps tools for deployment consistency

Do's

Kustomize

  • Use base/ for shared manifests
  • Use overlays for environment differences
  • Keep patches small
  • Preview with kubectl kustomize
  • Use GitOps-friendly folder structures

Helm

  • Use separate values files per environment
  • Preview with helm template
  • Track releases with helm list
  • Review release history with helm history
  • Use verified charts when possible

Don'ts

Kustomize

  • Don't duplicate full manifests per environment
  • Don't put production-only settings in the base
  • Don't make overlays too complex
  • Don't store raw secrets in Git

Helm

  • Don't install charts without reviewing generated YAML
  • Don't put every value behind unnecessary templates
  • Don't use unknown/untrusted charts in production
  • Don't store passwords directly in values files
  • Don't rely only on Helm rollback for database recovery

Security Considerations

Danger

Both Helm and Kustomize can deploy privileged or insecure Kubernetes resources if manifests are not reviewed.

Production safeguards:

  • Use RBAC with least privilege
  • Scan manifests in CI
  • Use admission controllers or policy engines
  • Avoid plaintext secrets
  • Review container images and registries
  • Use signed or trusted charts where possible
  • Restrict who can deploy to production namespaces

Troubleshooting Commands

kubectl kustomize overlays/prod
kubectl apply -k overlays/prod
kubectl diff -k overlays/prod
helm template my-release ./chart -f values.prod.yaml
helm install my-release ./chart -f values.prod.yaml
helm upgrade my-release ./chart -f values.prod.yaml
helm list
helm history my-release
helm rollback my-release 1

Exam / Interview Notes

Quote

  • Kustomize uses base and overlays
  • Helm uses templates and values
  • Kustomize keeps YAML simple and readable
  • Helm provides package management and release lifecycle
  • Helm is more powerful but more complex
  • Kustomize is simpler but does not manage releases

Summary

Quote

  • Use Kustomize for simple, readable environment customization
  • Use Helm for application packaging, releases, upgrades, and rollbacks
  • Helm uses Go templates and values files
  • Kustomize uses plain YAML patches and overlays
  • In production, always preview generated manifests before applying