Kustomize uses a mechanism to automatically update Kubernetes Deployments, StatefulSets, and DaemonSets whenever a Secret or ConfigMap referenced by those workloads changes. This is achieved by injecting a hash of the Secret/ConfigMap’s data into an environment variable within the Pod spec. When the Secret/ConfigMap is updated, its hash changes, which in turn changes the Pod spec, triggering a rolling update of the Deployment.

Here’s how to set it up and understand it:

The Core Idea: A Phantom Environment Variable

Kustomize can be instructed to add a specific environment variable to your Pods. The value of this environment variable isn’t static; it’s dynamically generated as a hash of the contents of a specified Secret or ConfigMap.

# kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - deployment.yaml
  - my-secret.yaml # The secret we want to track

patchesStrategicMerge:
  - patch-deployment.yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: nginx:latest
        ports:
        - containerPort: 80
# my-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: my-app-secret
type: Opaque
data:
  # Base64 encoded data
  API_KEY: c29tZS1zZWNyZXQtdmFsdWUgMQ==

Now, the crucial part is the patch that tells Kustomize to add the hashed environment variable.

# patch-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    spec:
      containers:
      - name: my-app
        env:
        - name: SECRET_HASH
          valueFrom:
            configMapKeyRef:
              name: my-app-secret # This is the name of your Secret
              key: __data # This is a special key Kustomize uses for the hash

What __data Means

The __data key in configMapKeyRef (or secretKeyRef if you were referencing a Secret directly, though configMapKeyRef is more common for this pattern) is a Kustomize convention. When Kustomize sees this, it doesn’t look for a literal key named __data in your Secret. Instead, it takes all the data within the specified Secret (in this case, my-app-secret), calculates a SHA256 hash of that combined data, and injects that hash as the SECRET_HASH environment variable’s value.

How it Works in Practice

  1. Initial Deployment: When you first apply kustomize build . | kubectl apply -f -, Kustomize processes my-secret.yaml and deployment.yaml along with the patch. It calculates the hash of my-app-secret’s data ({"API_KEY": "c29tZS1zZWNyZXQtdmFsdWUgMQ=="}). Let’s say this hash is a1b2c3d4e5f6.... The my-app Deployment is created with a Pod template that includes env: [{name: SECRET_HASH, value: "a1b2c3d4e5f6..."}].

  2. Secret Update: You modify my-app-secret. For example, you update API_KEY to c29tZS1zZWNyZXQtdmFsdWUgMg==.

  3. Re-application: You run kustomize build . | kubectl apply -f - again. Kustomize re-reads my-secret.yaml, calculates the new hash of the updated secret data. This new hash will be different, e.g., f6e5d4c3b2a1....

  4. Pod Spec Change: Kustomize applies the patch to the Deployment’s Pod template. The SECRET_HASH environment variable’s value is updated to the new hash. Because the Pod template has changed (even if only an environment variable’s value changed), Kubernetes sees this as a change to the Deployment’s spec.template.

  5. Rolling Update: Kubernetes initiates a rolling update for the my-app Deployment. New Pods are created with the updated SECRET_HASH environment variable, and old Pods are terminated. The application inside the Pods can then read this SECRET_HASH variable to determine if it needs to re-fetch configuration or secrets from the API server.

Important Considerations:

  • Secret vs. ConfigMap: While the example uses a Secret, this pattern works identically for ConfigMaps. The valueFrom.configMapKeyRef points to the ConfigMap whose data will be hashed.

  • Single Hash: Kustomize generates one hash for all data within the specified Secret or ConfigMap. If you have multiple keys in a Secret and only want to trigger an update based on one, this direct approach won’t work. You’d need a more complex patching strategy or a dedicated tool.

  • "Phantom" Key: The __data key is purely a Kustomize construct for this hashing mechanism. It does not exist as a literal key in your Secret or ConfigMap.

  • Application Logic: Your application must be designed to use this SECRET_HASH environment variable. The typical pattern is for the application to periodically check the value of SECRET_HASH. If it’s different from the last known value, the application re-reads the actual Secret/ConfigMap from the Kubernetes API.

  • Alternative (configMapRef / secretRef in env): You can directly reference a Secret or ConfigMap key into an environment variable like this:

    # Alternative, but doesn't provide a hash for updates
    env:
    - name: MY_API_KEY
      valueFrom:
        secretKeyRef:
          name: my-app-secret
          key: API_KEY
    

    This injects the value directly. If the secret changes, the value in the Pod will not update automatically. This is why the hashing method is crucial for forcing restarts.

This Kustomize feature is a powerful, declarative way to manage the lifecycle of secrets and configuration that your applications depend on, ensuring they always run with the latest available data without manual intervention.

Want structured learning?

Take the full Kustomize course →