values 按什么顺序合并
一句话总结
-f 可以使用多次,而且后面的值会胜出。--set 的优先级又高于所有 -f。不了解这个顺序,就可能为“明明设置了值,为什么没有生效”白白耗上一整天。
为什么需要理解优先级
生产部署中的 values 文件通常有两三层:Chart 默认值、各环境的值,以及 CI 注入的镜像标签。如果混淆了谁会覆盖谁,预发布环境的值就可能泄漏到生产环境。
优先级按从低到高排列如下。
- Chart 中的
values.yaml - 父 Chart 传给子 Chart 的值
-f a.yaml(先出现)-f b.yaml(后出现——覆盖 a)--set/--set-string/--set-file
它是如何工作的
不要猜测合并结果,应该直接进行确认。
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 是最先执行的命令。它是回答“当时究竟用了哪些值启动”的唯一事实来源。
常见误解
映射会合并,但数组会被整体替换。 如果两个 -f 文件中各自包含列表,它们不会合并,而是由后一个完整覆盖前一个。因此,把 extraEnv 之类的列表拆到不同环境文件中,最终只会剩下一份。如果确实需要合并列表,标准做法是把数据结构设计成映射。
--set 中的逗号与点。 --set a.b=1,a.c=2 表示两个值。如果值本身包含逗号,就必须使用 \, 转义。忽略这一点而截断镜像标签,是一种常见事故。值比较复杂时,使用 --set-string 或临时 values 文件更加安全。
锁定依赖才能保证可复现
Chart.yaml 的 dependencies 中填写的版本是一个范围。
dependencies:
- name: postgresql
version: "15.x.x" # 15.5.0 도, 15.9.2 도 이 범위다
repository: https://charts.bitnami.com/bitnami
每次运行 helm dependency update 时,都可能选中不同版本。解析结果会写入
Chart.lock,而且必须把这个文件提交到仓库,其他人和 CI 才能获取同样的
内容。如果把它放进 .gitignore,“明明在我的电脑上可以运行”的问题就会开始出现。
helm dependency build # Chart.lock 대로 받는다 (재현된다)
helm dependency update # 범위를 다시 풀어 lock 을 갱신한다 (의도할 때만)
CI 中应使用 build。如果使用 update,每次部署都可能获取到不同的依赖版本。
通过条件与标签启用或禁用
有时需要根据环境排除某个子 Chart。例如,开发环境使用 Chart 附带的 PostgreSQL, 而生产环境使用托管数据库。
# 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 根据单个值进行判断,而 tags 可以用一个开关控制多个子 Chart。
条件为假时,该子 Chart 根本不会渲染,因此即使其中的值有误,部署也可能通过——
直到重新启用它时,问题才会首次暴露。
分三步查明值为什么没有生效
# 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
第二步经常发现的原因是拼写错误。即使把 imagePullSecrets 写成 imagePullSecret,
Helm 也不会报错——这个值只会静静地不被使用。
因此,在 Chart 中提供 values.schema.json,就能在部署前发现未知键。
实际工作中真正重要的事
子 Chart 的值必须在父 Chart 中以子 Chart 名称作为键来指定。
# 부모 차트의 values.yaml
postgresql:
auth:
database: labhub
只有放在 global: 下的值,才能由所有子 Chart 共同读取。不了解这个区别,就会一直困惑于“为什么子 Chart 没有读取这个值”。