Prepending Environment Variables with Kyverno: Finding the Right Approach
Injecting environment variables into Kubernetes pods with Kyverno requires careful strategy. While `patchStrategicMerge` only appends to arrays, `patchesJson6902` with `add` operation at index `0` successfully prepends variables, preserving existing configurations.
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.crtpatchStrategicMerge
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.crtpatchesJson6902
Why this works:
- The
addoperation at path/env/0inserts at the beginning of the array - Existing environment variables shift down but remain intact
- We iterate over
environmentVariablesconfiguration 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
patchStrategicMergefor simple merges and appending - Use
patchesJson6902when you need precise array positioning, prepending, or conditional logic