Helm lets you override default chart values using multiple -f flags, but the order matters, and it’s not always obvious how they interact.
Imagine you’re deploying a web application with Helm. The default chart has a replicaCount of 1. You want 3 replicas, so you create a my-values.yaml file:
replicaCount: 3
And run:
helm install my-release ./my-chart -f my-values.yaml
This works. Now, let’s say you have a production environment where you need even more replicas, say 5. You create prod-values.yaml:
replicaCount: 5
And try:
helm install my-release ./my-chart -f my-values.yaml -f prod-values.yaml
Which one wins? The last one specified on the command line. Helm merges these files sequentially, with later files overriding earlier ones. So, replicaCount will be 5.
What if you also want to set a specific resource limit, but only for a staging environment, and you want that to be overridden by your production settings?
staging-values.yaml:
resources:
limits:
cpu: 500m
memory: 512Mi
prod-values.yaml:
replicaCount: 5
resources:
limits:
cpu: 1000m
memory: 1024Mi
Running helm install my-release ./my-chart -f my-values.yaml -f staging-values.yaml -f prod-values.yaml will result in:
replicaCount: 5 (fromprod-values.yaml, overridingmy-values.yaml)resources.limits.cpu: 1000m (fromprod-values.yaml, overridingstaging-values.yaml)resources.limits.memory: 1024Mi (fromprod-values.yaml, overridingstaging-values.yaml)
This sequential override behavior is key. Helm doesn’t do a deep merge where it combines all values; it’s a last-write-wins approach for any given path in the YAML structure.
Consider a more complex scenario where you have a base configuration, environment-specific overrides, and then a final, truly custom override for a specific deployment.
base-values.yaml:
image:
repository: nginx
tag: latest
service:
type: ClusterIP
port: 80
replicaCount: 1
dev-values.yaml:
replicaCount: 2
image:
tag: dev
service:
port: 8080
prod-values.yaml:
replicaCount: 5
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 800m
memory: 800Mi
If you run helm install my-release ./my-chart -f base-values.yaml -f dev-values.yaml -f prod-values.yaml, the final values will be:
image.repository: nginx (frombase-values.yaml, not overridden)image.tag: dev (fromdev-values.yaml, overridesbase-values.yaml)service.type: ClusterIP (frombase-values.yaml, not overridden)service.port: 8080 (fromdev-values.yaml, overridesbase-values.yaml)replicaCount: 5 (fromprod-values.yaml, overridesbase-values.yamlanddev-values.yaml)resources.requests.cpu: 200m (fromprod-values.yaml)resources.requests.memory: 256Mi (fromprod-values.yaml)resources.limits.cpu: 800m (fromprod-values.yaml)resources.limits.memory: 800Mi (fromprod-values.yaml)
Notice how dev-values.yaml’s replicaCount of 2 is completely lost because prod-values.yaml specifies it again. This is the core behavior to grasp: each subsequent -f file merges its contents into the combined values from previous files, with its own values taking precedence.
The order of -f flags is crucial for managing configuration across different environments or for applying specific, targeted overrides. You can also use the --set flag, which is applied after all -f files, giving it the highest precedence.
This sequential merging is also how Helm resolves values when using --reuse-values or when upgrading. The existing values are treated as the "base" and new values are merged on top in the order they appear.
The most surprising thing about this mechanism is that it doesn’t perform any intelligent merging for lists. If a list is defined in an earlier file and then redefined in a later file, the entire list from the later file replaces the list from the earlier file, rather than appending or merging elements. For instance, if you have tolerations in two files, the one from the last file specified will be the only one applied, not a combined list.
Understanding this last-write-wins strategy for all value types, including nested maps and lists, is fundamental to mastering Helm value overrides.
The next concept you’ll likely grapple with is how to manage secrets effectively using Helm.