bigywater.tech
微服务 · 90

Helm 的模板渲染与值覆盖,以及与 Kustomize 的取舍

Helm 的模板和 Kustomize 的叠加层怎么选?各自表达环境差异的方式在哪些地方会出问题?这篇用 Helm 4.3.1 和 kubectl 内置的 Kustomize 5.8.1,把同一个小应用的三个环境渲染出来逐字段比较,再逐项试字段没留口子、类型陷阱、写错字段名和配置变更不滚动这几种情形。

0
三个环境下 Helm 与 Kustomize 渲染结果逐字段不同的地方
1.10 → 1.1
values 文件里镜像 tag 不加引号时渲染出的值(Helm 不报错)
1 → 2
改 ConfigMap 后 ReplicaSet 数:没有 checksum 注解是 1(没滚动),加上之后是 2

渲染结果与配置量

实测 · 本机执行输出
环境        Helm 的资源数   Kustomize 的资源数   逐字段不同的地方   详情
dev       3           3                0          -
staging   4           4                0          -
prod      4           4                0          -
  配置行数:Helm chart(Chart.yaml + values.yaml + 4 个模板)73 行 + 三个环境的 values 文件 11 行 = 84 行;Kustomize base 35 行 + 三个 overlay 48 行 = 83 行。两种写法渲染出的资源逐字段相同(上表),所以差别不在结果,在于怎么表达差异;行数只是这个小例子的数字,不能推广

同一个应用三个环境两种写法渲染出的资源逐字段相同,配置行数 84 对 83,渲染耗时 28 ms 对 32 ms,没有明显差别。

渲染速度

实测 · 本机执行输出
  helm template:中位数 28 ms,p90 31 ms
  kubectl kustomize:中位数 32 ms,p90 34 ms
  两者都在几十毫秒量级(进程启动占大头),发布流程里这点时间可以忽略;差别不在速度

都是几十毫秒量级,不是选择依据。

没预留的字段

实测 · 本机执行输出
  Helm --set terminationGracePeriodSeconds=45:退出码 0,渲染出的 Pod spec 里 terminationGracePeriodSeconds = (没有这个字段)
  Helm --set-string terminationGracePeriodSeconds=45:退出码 0,渲染出的 Pod spec 里 terminationGracePeriodSeconds = (没有这个字段)
  Kustomize 加一条 JSON patch:退出码 0,渲染出的 Pod spec 里 terminationGracePeriodSeconds = 45
  Helm 的 --set 对模板里没有引用的键没有任何作用,而且不报错;chart 里没做成 value 的字段,使用者只能改模板(fork)或者在渲染结果上再处理。Kustomize 的补丁可以改任意字段,不需要上游预先留口子

Helm 的 --set 对模板里没引用的键静默无效;Kustomize 补丁可以改任意字段。

类型陷阱

实测 · 本机执行输出
写法                                 退出码   渲染出的镜像(或错误)
helm --set image.tag=1.10          0     busybox:1.10
helm --set-string image.tag=1.10   0     busybox:1.10
values 文件 tag: 1.10(不加引号)          0     busybox:1.1
values 文件 tag: "1.10"              0     busybox:1.10
Kustomize newTag: 1.10(不加引号)       1     error: invalid Kustomization: json: cannot unmarshal number into Go struct field Image.images.newTag of type string
Kustomize newTag: "1.10"           0     busybox:1.10
  YAML 文件里没加引号的 1.10 是个浮点数,值 1.1,渲染出的镜像变成 busybox:1.1(Helm 不报错);这次测到 --set image.tag=1.10 得到的是 1.10,和 --set-string 一样,没有被当成浮点数。Kustomize 的 newTag 不加引号直接报类型错误。版本号这类看起来像数字的值,在 values 文件里要加引号

values 文件里没加引号的 1.10 渲染成 1.1;Kustomize 的 newTag 不加引号直接报错。

写错字段名

实测 · 本机执行输出
  (a)Helm 无 schema:退出码 0,渲染出的副本数 1(想要 9,拿到的是默认值)
  (b)Helm 加 schema:退出码 1;- at '': additional properties 'replicaCnt' not allowed
  (c)Kustomize:退出码 0,输出里带着拼错的字段 replicass: True
  (c)提交给集群(--dry-run=server --validate=strict):退出码 1;Error from server (BadRequest): error when creating "STDIN": Deployment in version "v1" cannot be handled as a Deployment: strict decoding error: unknown field "spec.replicass"
  Helm 对 values 里的未知键默认静默忽略,拿到的是默认值;加 values.schema.json 之后会报错。Kustomize 不认识字段的含义,拼错的字段会原样输出,到集群的 schema 校验才会被发现

Helm 默认静默忽略未知键,加 values.schema.json 才会报错;Kustomize 会原样输出拼错的字段,到集群校验才发现。

配置变更与滚动

实测 · 本机执行输出
写法                                ReplicaSet 数   Pod 重建了吗   容器里的 LOG_LEVEL
(a)Helm,没有 checksum 注解            1              否          info
(b)Helm,checksumConfig=true       2              是          debug
(c)Kustomize configMapGenerator   2              是          debug
  ConfigMap 改了,但 Deployment 的 Pod 模板没变就不会触发滚动更新:Pod 里还是旧值。Helm 的惯用法是把 ConfigMap 内容的哈希写进 Pod 模板注解(checksum/config);Kustomize 的 configMapGenerator 给 ConfigMap 名字加内容哈希,Deployment 里的引用被自动改写,模板变了就滚动
说明(哪些是测到的,哪些没有测)
  渲染比较是离线的,第六节才用集群;只有一个小应用,三个环境,行数和耗时只代表这个例子;没有测:helm install / upgrade 的发布记录(见下一篇)、Helm hooks、子 chart 与 library chart、Kustomize 的 components 与 vars/replacements、helm 与 kustomize 叠加使用(kustomize --enable-helm、post-renderer)

改 ConfigMap 不会让 Pod 重启;Helm 靠 checksum 注解,Kustomize 靠 configMapGenerator 的哈希后缀。

分步演示

Helm 模板与 Kustomize
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.8 / Go / nginx / Envoy / etcd / Consul / Nacos / OpenTelemetry / Prometheus(按各篇注明用到哪些及版本);所有服务都是本机自己起的进程,端口 9150 以上,只监听 127.0.0.1,不连任何外部服务,不碰本机已有的实例;故障用 kill -9 进程、让连接断开或在代码里注入延迟与错误来制造;计时用 time.perf_counter,数字每次运行会有小幅抖动。Helm v4.3.1,kubectl 内置的 Kustomize v5.8.1;一个自己写的小应用(Deployment、ConfigMap、Service,staging 和 prod 多 Ingress),Helm chart 与 Kustomize base / overlay 的配置在 vtmp/v90 里生成;渲染比较是离线的,配置变更是否滚动在 kind 集群里实测(busybox:1.36);行数与渲染耗时只代表这个小例子,耗时每次运行有 1 到 2 ms 的波动
    • 没有验证:helm install / upgrade 的发布记录与回滚(见下一篇);Helm hooks、子 chart、library chart;Kustomize 的 components、replacements;Helm 与 Kustomize 叠加使用(kustomize --enable-helm、Helm 的 post-renderer);大型 chart(几十个资源)上的渲染耗时;Helm 3 与 Helm 4 的行为差异(这里只用了 4.3.1)
    京ICP备2026067502号-1京公网安备11010502063487号