Helm 示例 Chart 结构解析:从helm create到helm install的完整实践指南
【免费下载链接】helmThe Kubernetes Package Manager项目地址: https://gitcode.com/GitHub_Trending/hel/helm
Helm(The Kubernetes Package Manager)中的helm create命令用于快速生成一个完整的 Chart 骨架,本文以 Helm 仓库internal/chart/v3/util/testdata/dependent-chart-with-all-in-requirements-yaml/charts/alpine/下的示例 Chart 为线索,从源码层面拆解一个由helm create alpine生成的 Chart 内部结构——包括templates/目录中的 Pod 模板、values.yaml默认值文件、Chart.yaml元数据文件,以及它们之间的取值与渲染关系。读完本文,你将掌握 Helm Chart 的目录规范、模板变量注入机制,并能够用helm install独立安装一个本地 Chart 进行验证。
示例的来龙去脉:testdata 中的 alpine Chart
该 README 位于 Helm 仓库的测试数据目录中:
internal/chart/v3/util/testdata/dependent-chart-with-all-in-requirements-yaml/charts/alpine/README.md
它隶属于一个名为dependent-chart-with-all-in-requirements-yaml("所有依赖都写在 requirements.yaml 中的依赖 chart")的父 Chart 测试数据。从该父 Chart 的 Chart.yaml 可以看到它声明了两个依赖:
apiVersion: v3 name: frobnitz description: This is a frobnitz. version: "1.2.3" dependencies: - name: alpine version: "0.1.0" repository: https://example.com/charts - name: mariner version: "4.3.2" repository: https://example.com/charts而在实际的charts/目录中,alpine/以目录形式存在(内含mast1、mast2-0.1.0.tgz两级子依赖),mariner则以打包后的 mariner-4.3.2.tgz 形式存在。这段 README 正是 Helm 在加载、解析该依赖树时随 Chart 一并读取的文档文件——它同时承担了"示例说明"与"测试语料"的双重角色。
该 README 全文如下:
This example was generated using the command
helm create alpine.The
templates/directory contains a very simple pod resource with a couple of parameters.The
values.tomlfile contains the default values for thealpine-pod.yamltemplate.You can install this example using
helm install ./alpine.
短短四句话,却完整交代了一个 Helm 示例 Chart 的四个核心要素:生成方式(helm create)、模板目录(templates/)、默认值文件(values)、安装方式(helm install)。下面逐一展开并结合源码深入剖析。
注:README 中提到的
values.toml在 Helm v3 的现行规范中已由values.yaml取代,实际 testdata 目录中保存的也正是values.yaml文件,下文以仓库实际内容为准。
第一步:helm create是如何生成 Chart 骨架的
CLI 层:pkg/cmd/create.go
helm create的 CLI 入口位于 pkg/cmd/create.go,它接收 chart 名称与目标目录,最终调用底层chartutil.Create完成骨架生成。
实现层:chartutil.Create
核心实现在 internal/chart/v3/util/create.go 的Create(name, dir string) (string, error)函数:
func Create(name, dir string) (string, error) { // Sanity-check the name of a chart so user doesn't create one that causes problems. if err := validateChartName(name); err != nil { return "", err } ... }从源码可以看出,Create的第一步是validateChartName(name)——先对 chart 名称做合法性校验(防止用户创建出会导致后续加载出问题的名称),随后才会在目标目录下创建Chart.yaml、values.yaml、.helmignore、ingress.yaml等骨架文件,并返回新建目录的绝对路径。
生成的默认 Chart.yaml 模板
defaultChartfile常量(internal/chart/v3/util/create.go)定义了helm create生成的 Chart.yaml 模板:
apiVersion: v3 name: %s description: A Helm chart for Kubernetes # A chart can be either an 'application' or a 'library' chart. # Application charts are a collection of templates that can be packaged into versioned archives # to be deployed. # Library charts provide useful utilities or functions for the chart developer... type: application version: 0.1.0 appVersion: "1.16.0"模板中的%s会被替换为用户传入的 chart 名称。测试数据中这份由helm create alpine生成的 Chart.yaml 正是这个模板的实例化结果(被精简过):
apiVersion: v3 name: alpine description: Deploy a basic Alpine Linux pod version: 0.1.0 home: https://helm.sh/helmapiVersion: v3声明该 Chart 遵循 Helm 3 的 Chart 规范;name、version是最核心的元数据,version 同时是依赖解析(dependency命令)和仓库索引(repo index)的重要依据。
生成的默认 values.yaml 模板
defaultValues常量(internal/chart/v3/util/create.go)定义了 values 文件的默认内容,包含replicaCount、image.repository、image.pullPolicy、image.tag、imagePullSecrets、nameOverride等常用占位配置。而本示例中的 values.yaml 被精简为只保留一个自定义参数:
# The pod name name: "my-alpine"这正是 README 所说的"couple of parameters"——values.yaml中的键值对会在渲染阶段注入模板,作为模板变量的取值来源。
第二步:templates/ 目录中的 Pod 资源模板
README 指出templates/目录包含一个非常简单的 Pod 资源。对应文件为 templates/alpine-pod.yaml:
apiVersion: v1 kind: Pod metadata: name: {{.Release.Name}}-{{.Chart.Name}} labels: app.kubernetes.io/managed-by: {{.Release.Service}} chartName: {{.Chart.Name}} chartVersion: {{.Chart.Version | quote}} spec: restartPolicy: {{default "Never" .restart_policy}} containers: - name: waiter image: "alpine:3.3" command: ["/bin/sleep","9000"]这份模板集中展示了 Helm 模板引擎的两类核心能力:
内置对象注入:
{{.Release.Name}}、{{.Release.Service}}、{{.Chart.Name}}、{{.Chart.Version}}分别来自 Helm 渲染时注入的Release和Chart内置对象。Release.Name是安装时指定的 release 名称,Release.Service恒为Helm,Chart.*则来自 Chart.yaml 元数据。默认值函数与管道:
{{default "Never" .restart_policy}}表示当restart_policy未被赋值时回退到"Never";{{.Chart.Version | quote}}则演示了 Go 模板的管道语法——将版本号通过quote函数转为带引号的字符串,确保 YAML 渲染时被识别为字符串类型。
注意:restart_policy、name这些变量在 values.yaml 中定义了默认值,Helm 渲染时会将 values 中的键值对作为顶层变量注入模板上下文——这正是"values 文件为模板提供默认参数"的机制。
模板渲染背后的引擎
模板渲染的实际执行者是 pkg/engine/engine.go 与 pkg/engine/funcs.go,后者注册了 Helm 模板中可用的全部函数(default、quote、include、tpl等)。渲染时 Chart 数据通过internal/chart/v3/loader加载(load.go),加载器会递归读取templates/目录下所有模板文件,以及charts/目录下的依赖 Chart。
测试中的佐证
internal/chart/v3/loader/load_test.go中专门对这类带依赖的 Chart 加载做了断言,例如:
assert.Equal(t, "templates/alpine-pod.yaml", dep.Templates[0].Name, ...)(见 internal/chart/v3/loader/load_test.go)——它验证了依赖 Chart 的模板文件会被正确加载进Templates列表,模板名称保留其在 Chart 内的相对路径。
第三步:依赖子 Chart 的嵌套结构
alpine自身也是一个父 Chart,它的charts/目录下还有两级依赖:
charts/alpine/ ├── charts/ │ ├── mast1/ # 目录形式子 Chart │ │ ├── Chart.yaml │ │ └── values.yaml │ └── mast2-0.1.0.tgz # 打包形式子 Chart ├── templates/ │ └── alpine-pod.yaml ├── Chart.yaml ├── README.md └── values.yamlmast1的 Chart.yaml 是helm create默认模板的原样产物:
apiVersion: v3 name: mast1 description: A Helm chart for Kubernetes version: 0.1.0 home: ""这种"目录 + 压缩包"混合存放的形式,正好覆盖了 Helm 依赖加载器的两种输入类型:目录形式的依赖通过internal/chart/v3/loader/directory.go的LoadDir加载,.tgz压缩包依赖则通过internal/chart/v3/loader/archive.go解压加载。依赖的递归解析与版本约束处理由internal/chart/v3/dependency.go与internal/chart/v3/util/dependencies.go共同完成。
第四步:用helm install安装并验证
README 给出的安装命令是:
helm install ./alpine该命令位于本地 Chart 所在目录的上级执行,./alpine指向 Chart 根目录。Helm 会先通过本地加载器读取Chart.yaml与values.yaml,渲染templates/下的所有模板,再将渲染结果提交给 Kubernetes API 完成部署。
实际使用中,命令通常需要补齐两个关键参数:
# 显式指定 release 名称与命名空间(推荐) helm install my-release ./alpine --namespace default # 覆盖默认值:将 values.yaml 中的 name 替换为新值 helm install my-release ./alpine --set name=my-custom-pod关于--set覆盖,其底层解析器位于 pkg/strvals/parser.go,它会把name=my-custom-pod这样的字符串逐段解析为键值对并合并进 values 数据。合并逻辑(子 Chart 与父 Chart 取值优先级的处理)位于 pkg/chart/v3/util/values.go 与 pkg/chart/v3/common/util/coalesce.go 中——Helm 遵循"父 Chart 的 values 可以覆盖子 Chart 的 values"这一取值优先级规则。
安装成功后可执行helm status my-release查看 release 状态,helm uninstall my-release清理资源。若只想预演渲染结果而不真正部署,可使用helm template my-release ./alpine或helm install --dry-run。
小结:一个示例 Chart 的完整生命周期
本文通过这份alpine示例 README,串联起了 Helm Chart 的完整生命周期:
- 生成:
helm create alpine调用chartutil.Create(internal/chart/v3/util/create.go),依据defaultChartfile、defaultValues等内置模板生成 Chart 骨架; - 结构:Chart 由
Chart.yaml(元数据)、values.yaml(默认值)、templates/(Go 模板资源)三大要素构成,可嵌套charts/目录承载依赖子 Chart; - 渲染:加载器(internal/chart/v3/loader)读取文件树,模板引擎(pkg/engine/engine.go)将
Release、Chart内置对象与 values 变量注入模板,产出最终的 Kubernetes 资源清单; - 安装:
helm install ./alpine将渲染结果提交到集群,配合--set实现参数化部署。
理解了这条链路,无论是阅读 Helm 仓库中其他 testdata 示例,还是编写自己的生产级 Chart,都能做到心中有数。
【免费下载链接】helmThe Kubernetes Package Manager项目地址: https://gitcode.com/GitHub_Trending/hel/helm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考