Kustomize’s helmCharts field lets you inject Helm chart values directly into your Kubernetes manifests, but it’s not just a simple value merge; it’s a full-blown Helm render operation that Kustomize orchestrates.

Let’s see Kustomize in action with a simple example.

Imagine you have a kustomization.yaml that references a Helm chart:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

helmCharts:
  - chart: ./my-chart
    releaseName: my-release
    valuesFile: ./my-values.yaml

And a my-chart directory containing a standard Helm chart structure (Chart.yaml, values.yaml, templates/deployment.yaml).

templates/deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:

  name: {{ .Release.Name }}-app

spec:

  replicas: {{ .Values.replicaCount }}

  selector:
    matchLabels:

      app: {{ .Release.Name }}-app

  template:
    metadata:
      labels:

        app: {{ .Release.Name }}-app

    spec:
      containers:
      - name: app

        image: nginx:{{ .Values.imageTag }}

        ports:
        - containerPort: 80

my-values.yaml:

replicaCount: 3
imageTag: "1.21.6"

When you run kustomize build ., Kustomize will:

  1. Locate the Helm chart: It finds ./my-chart.
  2. Read my-values.yaml: It loads the specified values.
  3. Render the Helm chart: It uses Helm’s templating engine to process templates/deployment.yaml with the provided values.
  4. Inject the rendered manifest: The output of the Helm render (a complete Deployment object) is then included in Kustomize’s output.

The generated output would look something like this:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-release-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-release-app
  template:
    metadata:
      labels:
        app: my-release-app
    spec:
      containers:
      - image: nginx:1.21.6
        name: app
        ports:
        - containerPort: 80

This mechanism allows you to leverage the power of Helm for templating complex applications while integrating them seamlessly into a Kustomize workflow, managing your entire Kubernetes configuration as code. You can also specify nameSuffix, namePrefix, namespace, and version to further customize how the Helm chart is integrated.

The true power lies in Kustomize’s ability to patch these Helm-rendered resources. You can have a helmCharts entry and patchesStrategicMerge or patchesJson6902 entries in the same kustomization.yaml. Kustomize applies its patches after the Helm chart has been rendered and its output injected. This means you can take a complex Helm chart, render it, and then apply granular, Kustomize-native adjustments to the resulting Kubernetes objects without modifying the original Helm chart’s templates or values.

For instance, if you wanted to add a label to the my-release-app Deployment generated by Helm, you could add:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

helmCharts:
  - chart: ./my-chart
    releaseName: my-release
    valuesFile: ./my-values.yaml

patchesStrategicMerge:
  - deployment-patch.yaml

And deployment-patch.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-release-app # Must match the rendered name
  labels:
    environment: production

This would result in the Deployment having both the labels generated by Helm and the environment: production label. The releaseName from the helmCharts field is crucial for targeting the correct resource in subsequent patches.

The most surprising aspect is that Kustomize doesn’t just merge values; it performs a full Helm rendering. This means any logic within your Helm templates, including if statements, range loops, and function calls, is executed. Kustomize effectively acts as a Helm client, but instead of helm install or helm template, it outputs the rendered Kubernetes manifests directly into its own build process. This allows for a declarative, GitOps-friendly way to manage Helm-templated applications alongside other Kubernetes resources.

When you start using helmCharts with multiple charts or charts that have complex dependencies, you’ll quickly encounter the need to manage the order of operations, especially when dealing with cross-chart dependencies or when Kustomize needs to apply patches to resources generated by different Helm charts.

Want structured learning?

Take the full Kustomize course →