Prepending Environment Variables with Kyverno: Finding the Right Approach

We needed to inject CA certificate configuration into Kubernetes pods using Kyverno, but with a critical requirement: prepend environment variables without overwriting existing ones. Our use case involved dynamically adding SSL_CERT_FILE, REQUESTS_CA_BUNDLE, and similar variables to containers that might already have their own environment configurations.

The key constraint? If a container already defines these variables, we don't want to lose that configuration. We want our injected variables to be inserted before (allowing others to overwrite it).

Approach 1: patchStrategicMerge (Didn't Work)

Our first attempt used Kyverno's patchStrategicMerge strategy:

mutate:
  patchStrategicMerge:
    spec:
      containers:
        - (name): "*"
          env:
            - name: SSL_CERT_FILE
              value: /certs/ca.crt

patchStrategicMerge

This approach seemed elegant and readable, but it has a fundamental limitation: patchStrategicMerge appends to arrays, not prepends. More importantly, it doesn't provide fine-grained control over array positioning or conditional logic to skip existing entries.

While this works for simple cases where order doesn't matter, it fails when you need guaranteed precedence without overwriting.

Approach 2: patchesJson6902 with Index 0 (Success!)

The solution was switching to patchesJson6902 with JSON Patch operations, specifically using the add operation at index 0:

mutate:
  foreach:
    - list: "request.object.spec.containers[]"
      patchesJson6902: |-
        - op: add
          path: /spec/containers/{{elementIndex}}/env/0
          value:
            name: SSL_CERT_FILE
            value: /certs/ca.crt

patchesJson6902

Why this works:

  • The add operation at path /env/0 inserts at the beginning of the array
  • Existing environment variables shift down but remain intact
  • We iterate over environmentVariables configuration to inject multiple vars dynamically
  • Each variable is prepended, ensuring existing container configuration would not be overwritten by us.

This approach gives us:

✅ Dynamic enumeration over configured environment variables

✅ Prepending to preserve existing configurations

✅ Clean separation between array manipulation and object merging

✅ Flexible, values-driven configuration

Key Takeaway

When working with Kyverno mutations, choose your patch strategy based on your requirements:

  • Use patchStrategicMerge for simple merges and appending
  • Use patchesJson6902 when you need precise array positioning, prepending, or conditional logic