5. 核心模块:从 Chart 到 Release 的每个零件
一句话理解:本章把 Helm 拆成可独立理解的模块——Chart 仓库/OCI(分发)、依赖解析(组合)、模板引擎(渲染)、values 合并(参数)、Release 存储(版本记录)、CLI(入口)、Hook/Test(一次性动作与测试)、post-renderer(逃生舱)、Chart Signing(完整性),并辨析
lookup/tpl/required等易错函数。
5.1 Chart 仓库与 OCI registry(分发层)
传统 Chart 仓库
一个 Chart 仓库 = 一个 HTTP server + 根目录 index.yaml。index.yaml 是所有 chart 的索引:
apiVersion: v1
generated: "2026-07-04T..."
entries:
gpu-operator:
- version: v24.6.0
appVersion: "24.6.0"
urls:
- https://nvidia.github.io/gpu-operator/charts/gpu-operator-v24.6.0.tgz
digest: 9f2b... # .tgz 的 SHA256
created: "2026-06-01T..."
gpu-operator:
- version: v23.9.0
...helm repo add nvidia https://nvidia.github.io/gpu-operator → helm repo update(拉最新 index)→ helm search repo gpu-operator(在 index 里搜)→ helm install gpu-op nvidia/gpu-operator。
OCI registry(当前推荐)
把 Chart 当 OCI 制品(image manifest,mediaType application/vnd.cncf.helm.chart.content.v1.tar+gzip)推到任意 OCI registry:
# 推
helm package mychart/ # 生成 mychart-1.4.2.tgz
helm push mychart-1.4.2.tgz oci://registry.example.com/charts
# 拉/装(按版本 tag)
helm pull oci://registry.example.com/charts/mychart --version 1.4.2
helm install myrelease oci://registry.example.com/charts/mychart --version 1.4.2
# Helm 4 新增:按 digest 安装(内容寻址,防 tag 被篡改,供应链推荐)
helm install myrelease oci://registry.example.com/charts/mychart@sha256:9f2b...OCI 的优势(相对传统 repo):
- 复用现有 registry(Harbor/ACR/ECR/GHCR/自建 distribution),统一镜像与 chart 的存储/权限/复制/扫描/签名。
- 内容寻址 + 可复制:registry 间的复制、签名(cosign/Sigstore)、漏洞扫描都现成;Helm 4 的 digest 安装让"按内容寻址引用 chart"成为一等能力。
- 更好的多租户/权限:registry 的 RBAC 直接管 chart 访问。
- 更稳定:不依赖一个
index.yaml大文件,按 chart/版本分片。
helm registry login 鉴权,helm push/pull 推拉。官方已把 OCI 作为推荐分发方式,传统 Chart 仓库仍支持但不再获得新能力;2025 年以来生态加速向 OCI 迁移(ACR 下架传统 chart 仓库、Harbor 弃用 ChartMuseum、Istio chart 迁 GHCR,见第 2 章 2.5)。
Helm 4 迁移坑:
helm registry login在 Helm 4 里只接受纯域名(helm registry login registry.example.com,不再接受https://registry.example.com/charts这种带 scheme/path 的 URL)——CI 脚本里凡是传完整 URL 的登录命令都要改。
生态导航:搜现成 Chart 用 Artifact Hub(CNCF 的包中心,聚合各 repo/OCI 的 chart;已支持 OCI 仓库索引与 Verified Publisher 认证)。Bitnami 许可证变更后,社区出现了 MIT 协议的 HelmForge 作为替代 chart 源(OCI 发布 + cosign 签名,见 Portainer 社区的讨论)。
5.2 依赖解析(组合层)
Chart.yaml 声明依赖:
dependencies:
- name: redis
version: 18.x.x
repository: https://charts.bitnami.com/bitnami
condition: redis.enabled # 父 values 的 redis.enabled=false 则不装
alias: cache # 在父 values 里用 cache: {...} 而非 redis: {...}
import-values: # 把子的某值导出到父
- child: service.port
parent: redisPort
tags: [cache] # 可用 --tags cache 启/禁helm dependency update:读 dependencies,下载到 charts/ 目录,生成 Chart.lock(锁定版本,类比 package-lock)。安装父 chart 时子 chart 一起渲染安装。
父子 values 隔离:
- 父不能直接
{{ .Values.redis.x }}(那是父自己的 values)。 - 父给子传值:在父
values.yaml里用子 chart 名(或 alias)做键:yaml# 父 values.yaml redis: # 子 chart 名 architecture: replication auth: password: "secret" - 子 chart 内部读到的是它自己的
.Values.architecture(合并了子的 values.yaml + 父传来的)。 - 跨父子共享用
global:父和所有子都能读.Values.global.x。
5.3 模板引擎(渲染层)
pkg/engine 渲染流程:
- 遍历
templates/(递归),跳过_*.tpl(只define不产文档)。 - 对每个文件,以 Go
text/template+ Sprig + Helm 扩展函数渲染,上下文对象 ={ Values, Release, Chart, Files, Capabilities, Template }。 - 对渲染结果做 YAML 文档拆分(
---分隔),校验语法。 - 把 NOTES.txt、tests/、hook 资源分类标记。
- 普通资源按"资源类型优先级"排序(CRD 最先、workloads 较后),hook 按 weight。
易错函数辨析
| 函数 | 作用 | 易错点 |
|---|---|---|
{{ .Values.x | default "y" }} | x 为空时用 "y" | default 对 0/false/""/nil 都判空——数字 0 会被当空 |
{{ .Values.x | required "必须填" }} | x 为空则渲染报错中止 | 强制必填字段用它,避免 <no value> |
{{ .Values.x | quote }} | 加引号 | 字符串里含特殊字符(:、#、{})必须 quote,否则 YAML 解析错 |
{{ toYaml .Values.x | nindent 8 }} | 对象转 YAML + 缩进 | 缩进必须对齐,差一个空格就 YAML 错 |
{{ include "name" . }} | 调命名模板 | 传 .(整个上下文),不是 .Values |
{{ tpl .Values.tplStr . }} | 把字符串当模板再渲染 | 用户提供的 values 字符串里能嵌 {{ }},慎防注入 |
{{ lookup "v1" "ConfigMap" "ns" "name" }} | 渲染时实时查集群 | 见下,GitOps 慎用 |
lookup:延迟绑定(双刃剑)
lookup 让模板在渲染时查询目标集群的实时状态:
{{- $existing := lookup "v1" "Secret" .Release.Namespace "tls-cert" -}}
{{- if $existing -}}
tls.crt: {{ $existing.data["tls.crt"] }}
{{- else -}}
# 首次安装时还没证书,先生成占位或调用 cert-manager
{{- end -}}用途:让 chart 自适应集群现状(已存在证书就复用、按节点数算副本)。但风险:
- 渲染结果依赖集群状态 → 同一份 chart+values 在不同集群渲染出不同清单 → 破坏 GitOps 的"Git 是唯一真相"(Git 里存的不等于集群里跑的)。
helm template(离线渲染)没有集群,lookup返回空,渲染结果与真实 install 不一致。- 建议:GitOps 场景尽量不用
lookup;必须用时,文档明确说明它的副作用,并在 values 里提供开关。
5.4 values 合并算法(参数层)
合并不是简单的"字典覆盖",而是深合并(deep merge):
- map:递归合并(子键被父的同名键深合并,不是整体替换)。
- list:整体替换(不按 index 合并)。这是最易踩的点——你想"给现有 env 列表加一个变量",必须用
+拼接或 Helm 的mergeOverwrite,而不是靠 values 覆盖(会替换整个列表)。
优先级(低 → 高):
- 子 chart 自己的
values.yaml。 - 父 chart 的
values.yaml(含父对子的段)。 -f extra.yaml(可多个,后者覆盖前者)。--set a.b=c(可多个)。--set-string a.b=c(强制字符串,防--set port=8080被当数字/--set enabled=true当布尔——其实--set会按字面量推断类型,8080当数字、true当布尔,要纯字符串必须--set-string)。
--set语法:--set a.b.c=v(嵌套)、--set list[0]=v(列表下标)、--set list={a,b,c}(列表)、--set 'a.b\=c=d'(值里含等号/逗号要转义)。复杂结构优先用-f,--set只用于少量覆盖。
5.5 Release 存储(版本记录层)
如第 3 章所述,每个 revision = 一个 Secret:
Name: sh.helm.release.v1.myrelease.v1
Type: helm.sh/release.v1
Namespace: prod
Annotations:
modifiedAt: "1719..."
version: "1"
Data:
release: <gzip+base64 of protobuf Release{ name, namespace, chart, config(values), info(status, ...), version }>pkg/storage/driver 抽象了存储后端(Secret/ConfigMap/Memory),pkg/storage 之上是 release 的 CRUD。helm history/list/get/status 都从这里读。
历史上限:helm upgrade --history-max 10(v3.5+,或在环境变量/配置里设)——超过上限自动删最旧 revision Secret,防止 etcd 膨胀。生产必设。
5.6 CLI(入口层)
pkg/cli + cobra 子命令。常用:
| 命令 | 用途 |
|---|---|
helm create NAME | 生成一个标准 Chart 骨架(带 deployment/service/hpa/ingress 模板) |
helm lint CHART | 静态检查 Chart(模板语法、必填字段、命名) |
helm template [NAME] CHART | 离线渲染,打印清单不 apply(GitOps/CI 必备) |
helm install/upgrade/rollback/uninstall | Release 生命周期(第 4 章) |
helm package / push / pull | 打包/推/取 |
helm dependency build/update | 依赖管理 |
helm repo add/update/list/remove/index | Chart 仓库管理 |
helm registry login/logout | OCI registry 鉴权 |
helm history/list/status/get(values/manifest/all) | 查 release |
helm test | 跑 Chart 的 tests/(见下) |
helm search repo/hub | 搜 chart |
helm upgrade --install | "存在则升级,不存在则装"(CI/CD 幂等) |
helm diff upgrade ...(helm-diff 插件) | 渲染并 diff 两个版本清单(发布前 review 必备) |
Helm 4 标志变更(旧标志在 4.0 仍可用但打印弃用警告,计划在后续小版本移除,CI 脚本尽快迁移):
| Helm 3 标志 | Helm 4 新名 | 说明 |
|---|---|---|
--atomic | --rollback-on-failure | 失败/超时自动回滚 |
--force | --force-replace | 删除重建而非 patch |
另外 Helm 4 新增 --server-side(对老 release 一次性切换到 SSA apply)与 --force-conflicts(SSA 冲突时强制接管字段所有权),见第 3 章 3.4.1。
5.7 Hook 与 helm test(一次性动作与测试)
Hook
注解驱动的时序动作(第 3、4 章已述):
| Hook | 时机 |
|---|---|
pre-install/post-install | install 前后 |
pre-upgrade/post-upgrade | upgrade 前后 |
pre-rollback/post-rollback | rollback 前后 |
pre-delete/post-delete | uninstall 前后 |
test | 仅 helm test 时跑 |
配套注解:helm.sh/hook-weight(顺序,数字小先)、helm.sh/hook-delete-policy(hook-succeeded/hook-failed/before-hook-creation,控制 Job 是否清理)。
helm test
templates/tests/ 下的资源(通常是 Pod)标 helm.sh/hook: test,helm test myrelease 会运行它们。典型用法:装完服务后跑一个 curl Pod 验证 /health:
# templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "mychart.fullname" . }}-test"
annotations:
"helm.sh/hook": test
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
restartPolicy: Never
containers:
- name: wget
image: busybox
command: ['wget', '--spider', '--timeout=10', '{{ include "mychart.fullname" . }}:{{ .Values.service.port }}/health']helm test 是"安装后冒烟测试"的官方机制,CI 里 helm install --wait && helm test 很常见。
5.8 post-renderer(逃生舱)
helm install/upgrade --post-renderer CMD:Helm 渲染完清单文本后,通过 stdin 把全部清单喂给 CMD,取回 stdout 作为最终 apply 的清单。典型:
--post-renderer kustomize:套一层 Kustomize patch(注入 sidecar、改 label)。- 自写脚本:按集群注入 OPA 注解、套 NetworkPolicy、把镜像 digest 补上。
它是"模板引擎做不到时的逃生舱",但也让发布流程更难审计(多了一步外部逻辑),生产用要纳入 review。
Helm 4 重大变化:post-renderer 不再接受可执行文件路径,必须实现为 Wasm 插件(插件类型
post-renderer),--post-renderer传的是插件名。这是 Helm 4 插件系统重建的一部分(见下节 5.8.1)——动机是安全:旧机制等于"让 chart 调用方在本机执行任意程序",Wasm 沙箱把这一步隔离起来。
5.8.1 Helm 4 的 Wasm 插件系统
Helm 4 把插件机制重建为 WebAssembly 沙箱(基于 Extism 运行时),启动时可选启用,三类插件:
| 类型 | 作用 | 例子 |
|---|---|---|
| CLI 插件 | 给 helm 加子命令 | helm diff、helm unittest 类工具 |
| getter 插件 | 自定义 chart 来源协议 | 从内部制品系统拉 chart |
| post-renderer 插件 | 渲染后处理清单 | 注入 sidecar、套 Kustomize |
legacy(Helm 3 时代的脚本)插件在 Helm 4 中仍兼容,但生态正在向 Wasm 插件迁移——对平台团队而言,自研 post-renderer/插件应尽快改成 Wasm 形式,别等旧机制退役。
5.9 Chart Signing(完整性)
两种机制:
Helm 原生 provenance(传统,渐成遗留):
helm package --sign --key KEY生成.prov文件( detached PGP 签名),helm verify校验。--verify安装时校验。传统 repo 时代的方案,依赖 GPG key 分发,灵活性和生态都弱于 cosign。OCI + cosign/Sigstore(当前推荐):OCI chart 用 cosign 签名——2026 年的主流做法是 keyless 签名:CI(如 GitHub Actions OIDC)自动获取短期证书(Fulcio)并记录到透明日志(Rekor),无需管理长期私钥:
bashhelm push mychart-1.4.2.tgz oci://registry.example.com/charts cosign sign registry.example.com/charts/mychart:1.4.2 # 消费侧(人或准入控制器)校验: cosign verify registry.example.com/charts/mychart:1.4.2 \ --certificate-identity-regexp "https://github.com/myorg/.*" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com"配合 SBOM / SLSA provenance attestation(
cosign attest/cosign verify-attestation)与 digest 钉版(第 8 章),并在部署侧用准入控制器(Sigstore Policy Controller / Kyverno / Flux 的verify配置)强制"只许运行已签名 chart"——这是 Helm 供应链安全的当前标准姿势(第 8 章 8.3 的 CI 流水线即按此组织)。
5.10 模块全景对照
入口: helm CLI (cobra, pkg/cli)
│
分发: Repository(index.yaml) / OCI registry ── helm pull/push
│
组合: 依赖解析 (Chart.yaml deps, charts/, Chart.lock)
│
参数: values 合并 (深合并: map递归 / list替换, 优先级 yaml<f<--set<--set-string)
│
渲染: 模板引擎 (pkg/engine: Go template + Sprig + lookup/required/tpl)
│
扩展: Hook (注解时序) / post-renderer (渲染后管道) / Library Chart (模板复用)
│
发布: install/upgrade(三方合并)/rollback/uninstall ── pkg/action + pkg/kube
│
记录: Release 存储 (pkg/storage, Secret 驱动, history-max)
│
完整性: provenance(.prov) / OCI+cosign本章小结
Helm 的核心模块按"分发→组合→参数→渲染→扩展→发布→记录→完整性"分层:Chart 仓库/OCI registry 分发(OCI 已是事实标准——ACR 下架传统仓库、Harbor 弃用 ChartMuseum;Helm 4 支持按 digest 安装、registry login 只收域名),依赖解析用 Chart.yaml dependencies 组合子 chart(父子 values 隔离、global 共享、condition 开关、import-values 导出),模板引擎是 Go template + Sprig + Helm 扩展(注意 default/quote/required/lookup/tpl 的易错语义,lookup 会破坏 GitOps 纯净需慎用),values 合并是深合并(map 递归、list 整体替换,优先级 yaml < -f < --set < --set-string),Release 存储是 Secret(history-max 防膨胀),CLI 提供 lint/template/install/upgrade/rollback/test 等子命令(Helm 4 更名 --rollback-on-failure/--force-replace),Hook/test 注解驱动时序动作与冒烟测试,post-renderer 是渲染后逃生舱(Helm 4 起必须为 Wasm 插件,插件系统重建为 CLI/getter/post-renderer 三类沙箱扩展),Chart Signing 从 PGP provenance 演进到 OCI + cosign keyless 签名 + SBOM/attestation + 准入校验。把这十个模块的功能与边界记牢,遇到任何 Helm 行为都能定位到对应模块。
参考来源