Helm Deployment and Rollback Scenarios
In What Order Are values Merged
Summary in one line
-f can be used several times and the later one wins. --set beats every -f. If you do not know this order, you burn a whole day on "I definitely put the value in but it isn't taking effect."
Why this is needed
A production deployment usually has two or three layers of values files. The chart defaults, per-environment values, and the image tag that CI injects. If you get confused about which wins, staging values leak into production.
The precedence, from lowest, is as follows.
- The chart's
values.yaml - Values the parent chart gave to a subchart
-f a.yaml(the one that came first)-f b.yaml(the one that came later — it overrides a)--set/--set-string/--set-file
How it works
Do not guess the merged result; check it.
helm template demo ./chart -f prod.yaml --set image.tag=abc123 \
--show-only templates/deployment.yaml
helm get values demo # 배포된 릴리스에 실제로 들어간 값
helm get values demo --all # 기본값까지 합친 전체
helm get values is the first command you type in an incident investigation. It is the only fact about "what values did it come up with?"
Common misconceptions
Maps are merged, but arrays are replaced wholesale. If two -f files each have a list, they are not merged and the later one overrides the earlier one wholesale. So if you split a list like extraEnv per environment, only one remains. If you want to merge lists, designing them as maps is the standard approach.
Commas and dots in --set. --set a.b=1,a.c=2 is two values. If there is a comma inside a value, you must escape it with \,. Accidents where the image tag gets cut off because this was missed are common. If the value is complex, it is safer to use --set-string or a temporary values file.
Dependencies must be locked to be reproducible
The version written in dependencies in Chart.yaml is a range.
dependencies:
- name: postgresql
version: "15.x.x" # 15.5.0 도, 15.9.2 도 이 범위다
repository: https://charts.bitnami.com/bitnami
Each time you run helm dependency update, a different version may be picked. The result
is written to Chart.lock, and you have to commit this file to the repository for other people and CI to get the same
thing. If you put it in .gitignore, "it works on my machine" begins.
helm dependency build # Chart.lock 대로 받는다 (재현된다)
helm dependency update # 범위를 다시 풀어 lock 을 갱신한다 (의도할 때만)
In CI, use build. If you use update, a different dependency
can come in on every deployment.
Turning things on and off with conditions and tags
Sometimes you need to leave a subchart out depending on the situation. For example, in development you use the PostgreSQL that comes with the chart, and in production you use a managed DB.
# Chart.yaml
dependencies:
- name: postgresql
version: 15.5.0
repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled # 이 값이 false 면 통째로 빠진다
# values/prod.yaml
postgresql:
enabled: false
externalDatabase:
host: labhub-db-prod-rw.labhub-prod.svc
condition looks at one value, and tags bundle several subcharts under one switch.
If the condition is false, rendering does not happen at all, so even if that subchart's values are wrong,
the deployment passes — it shows up for the first time the moment you turn it on.
Finding why a value is not taking effect in three steps
# 1) 최종 값이 무엇인가 — 여기서 대개 끝난다
helm template demo ./chart -f prod.yaml --set image.tag=abc | grep -A2 image:
# 2) 값은 맞는데 템플릿이 안 쓰는가
helm template demo ./chart --debug 2>&1 | head -40 # 렌더 전 값이 보인다
# 3) 배포된 릴리스에 실제로 들어간 값
helm get values demo --all
A frequent cause in step 2 is a typo. Even if you write imagePullSecrets as imagePullSecret,
Helm says nothing — the value is simply not used.
That is why, if you put a values.schema.json in the chart, you can catch unknown keys before deployment.
What really matters in practice
Values for a subchart are specified in the parent chart with the subchart name as the key.
# 부모 차트의 values.yaml
postgresql:
auth:
database: labhub
Only values placed under global: are seen by all subcharts. If you do not know this distinction, you wander around with "the subchart doesn't read the value."