Every chart is configured through values; merge rules decide what your release actually gets.
A chart's values.yaml holds its defaults. You override them at install or upgrade time:
-f my-values.yaml(or--values): your overrides as a YAML file. Several-ffiles are merged in order, later ones winning: a common pattern is-f base.yaml -f prod.yaml.--set image.tag=1.5.0: a single value on the command line. Nested keys use dots, lists use indexes (--set ingress.hosts[0]=a.example.com), and--set-stringforces a string.--setbeats-f.--set-file key=pathreads a value from a file (certificates, scripts).
Merge rules: maps are deep-merged, so you only specify the keys you change. Lists are replaced wholesale, not merged, so overriding one element of a list means repeating the whole list. Setting a key to null removes a default.
Keep values files in git and prefer them to long --set chains: they are reviewable and reproducible.
On upgrade, helm upgrade without values resets to chart defaults. Helm 3 had --reuse-values and --reset-then-reuse-values to carry previous values over, but they hide drift between releases and git; passing the same values files every time is the clear, repeatable approach.
helm get values <release> --all shows the merged result.
Example
# prod.yaml
replicaCount: 3
image:
tag: "1.5.0" # deep-merged: image.repository keeps its default
resources:
requests: {cpu: 250m, memory: 256Mi}
ingress:
enabled: true
hosts: # lists are replaced entirely
- host: shop.example.com
paths: [{path: /, pathType: Prefix}]
# helm upgrade --install shop ./shop -n shop -f values-base.yaml -f prod.yaml \
# --set image.tag=1.5.1 # --set wins over both files
# helm get values shop -n shop --allRemember
- -f files merge in order; --set overrides them
- Maps deep-merge, lists are replaced
- Pass the same values files on every upgrade instead of relying on reuse
Watch out for
- Overriding one entry of a list in values and silently losing the other default entries.