Kustomize’s vars functionality is being deprecated in favor of a more robust and explicit replacements mechanism.

Let’s see Kustomize in action with replacements. Imagine you have a kustomization.yaml file and you want to inject a specific value into a Kubernetes manifest.

Original kustomization.yaml (using deprecated vars):

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

resources:
- deployment.yaml

vars:
- name: IMAGE_TAG
  objref:
    kind: Deployment
    name: my-app
    apiVersion: apps/v1
  fieldref:
    fieldpath: spec.template.spec.containers[0].image

Original deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app-container
        image: my-registry/my-app:latest # This image will be replaced

When you run kustomize build . with this setup, Kustomize would look for the IMAGE_TAG variable and try to substitute it into the spec.template.spec.containers[0].image field of the my-app deployment. However, vars requires you to also provide the value for the variable, usually through an environment variable or a configMapGenerator. This indirection is what makes it less explicit and harder to debug.

The Problem with vars:

The primary issue with vars is its implicit nature. You define where a variable should go (objref, fieldref) but not what the value is directly within the kustomization.yaml. You relied on external mechanisms (like environment variables) to provide the actual value, making it brittle and hard to track down configuration drift. If the environment variable wasn’t set correctly, or if it had the wrong value, the build would either fail in unexpected ways or produce a manifest with the wrong configuration, without a clear indicator of why.

Introducing replacements:

The replacements field addresses this by being explicit about both the target and the source of the replacement. It allows you to directly specify the value you want to inject or to reference another resource’s field.

Migrated kustomization.yaml (using replacements):

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

resources:
- deployment.yaml

images:
- name: my-registry/my-app # The image name to target
  newTag: v1.2.3         # The new tag to apply

# Alternatively, for more general field replacements:
# replacements:
# - sourcePath: "/spec/template/spec/containers/0/image"
#   target:
#     kind: Deployment
#     name: my-app
#     version: v1
#     group: apps
#   source:
#     kind: ConfigMap
#     name: my-app-config
#     version: v1
#     group: ""
#     fieldPath: data.imageTag

Explanation of images:

The images field is a common and convenient way to manage image tags.

  • name: This is the exact image name as it appears in your manifest (e.g., my-registry/my-app). Kustomize will find all occurrences of this image name across your resources.
  • newTag: This is the new tag you want to apply to that image.

When you run kustomize build . with this kustomization.yaml, Kustomize will locate the my-registry/my-app:latest in your deployment.yaml and replace it with my-registry/my-app:v1.2.3. The deployment.yaml file itself is not modified by Kustomize; the output of kustomize build will contain the updated image.

Explanation of replacements (general):

The more general replacements field offers fine-grained control:

  • sourcePath: This is the JSONPath to the field within the target resource that you want to modify.
  • target: This specifies the resource you want to modify. You provide kind, name, version, and group.
  • source: This defines where the new value comes from. It can be a literal value (not shown above but possible) or, more commonly, a field from another resource (like a ConfigMap or Secret). Here, it specifies a ConfigMap named my-app-config and a fieldPath within that ConfigMap’s data section.

Why replacements is better:

replacements makes the intent of your configuration explicit. You can clearly see what is being targeted and where the new value is coming from, all within your kustomization.yaml. This dramatically improves readability, debuggability, and maintainability. When using images, the intent to update an image tag is immediately obvious. When using the general replacements, the source and target are clearly defined, leaving less room for misinterpretation.

The images field is a specialized form of replacements that is highly optimized for the common task of managing container image tags. It’s generally preferred for this specific use case due to its simplicity and clarity.

The next thing you’ll likely run into is managing different configurations for different environments (dev, staging, prod) using Kustomize’s patches and overlays features.

Want structured learning?

Take the full Kustomize course →