3、Helm Chart项目结构:标准Chart目录结构、templates/NOTES.txt/Chart.yaml/values.yaml的作用
一个规范的 Helm Chart 是 Helm 打包、分发和部署应用的基础单元。理解标准 Chart 目录结构以及核心文件的作用,是编写可维护、可测试 Chart 模板的前提。本章将系统梳理标准目录布局,并深入解析 templates/、NOTES.txt、Chart.yaml 和 values.yaml 四个关键组件的职责与最佳实践。
3.1 标准 Chart 目录结构
Helm 社区推荐的标准 Chart 目录结构如下,每个文件和目录都有明确的语义。创建新 Chart 时,可使用 helm create <chart-name> 命令自动生成此骨架。
my-chart/
├── Chart.yaml # Chart 元数据(名称、版本、描述等)
├── values.yaml # 默认配置值
├── values.schema.json # (可选)values.yaml 的 JSON Schema 校验文件
├── charts/ # 子 Chart 依赖(手动或通过 helm dependency 管理)
├── crds/ # 自定义资源定义(CRD),优先于 templates 安装
├── templates/ # Go 模板文件,渲染后生成 Kubernetes 资源清单
│ ├── NOTES.txt # 安装成功后的使用提示文本
│ ├── _helpers.tpl # 模板辅助函数(命名模板)
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ └── ...
└── README.md # (可选)Chart 使用说明
关键原则:
templates/ 目录下的所有文件都会被 Helm 引擎解析并渲染;非 .yaml、.tpl、.txt 后缀的文件会被忽略。单元测试文件(如 deployment_test.yaml)通常放在 templates/tests/ 子目录中,避免与正式资源混淆。
3.2 核心文件作用详解
3.2.1 Chart.yaml — Chart 的身份证
Chart.yaml 是每个 Chart 必须存在的元数据文件,定义了 Chart 的名称、版本、API 版本、描述、关键字、依赖等信息。Helm 在安装、打包、发布时都会读取此文件。
| 字段 | 是否必填 | 说明 | 示例 |
|---|---|---|---|
apiVersion |
是 | Chart API 版本,v2 为当前标准 | v2 |
name |
是 | Chart 名称,必须符合 DNS 标签规范 | my-app |
version |
是 | Chart 语义化版本(SemVer 2) | 1.2.3 |
description |
否 | Chart 简短描述 | A Helm chart for Kubernetes |
type |
否 | Chart 类型:application 或 library |
application |
dependencies |
否 | 子 Chart 依赖列表 | 见下方代码块 |
appVersion |
否 | 应用版本号,与 Chart 版本独立 | 1.0.0 |
# Chart.yaml 典型示例
apiVersion: v2
name: my-app
description: A Helm chart for deploying my-app on Kubernetes
type: application
version: 1.2.3
appVersion: "1.0.0"
keywords:
- web
- microservice
dependencies:
- name: redis
version: "17.0.0"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
maintainers:
- name: DevOps Team
email: devops@example.com
测试关注点: 单元测试和集成测试中,
Chart.yaml 的 version 和 appVersion 字段常被用于生成资源标签(如 app.kubernetes.io/version)。测试应验证这些字段是否正确传递到模板输出中。
3.2.2 values.yaml — 默认配置的单一事实来源
values.yaml 是 Chart 的默认配置值文件,定义了所有可配置参数的默认值。用户在安装或升级时可以通过 --set 或自定义 values 文件覆盖这些值。它是模板渲染的输入数据源。
# values.yaml 典型结构
replicaCount: 3
image:
repository: nginx
tag: "1.25.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: false
host: my-app.example.com
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
nodeSelector: {}
tolerations: []
affinity: {}
| 设计原则 | 说明 |
|---|---|
| 扁平化优先 | 避免过度嵌套,通常不超过 3 层,便于 --set 覆盖 |
| 默认值合理 | 默认值应能直接 helm install 成功,无需用户额外配置 |
| 类型明确 | 字符串、数字、布尔值、列表、字典类型清晰,避免隐式转换 |
| 注释完整 | 每个字段上方添加 # 注释,说明用途和可选值 |
| 可测试性 | 为单元测试提供最小化测试值集,避免依赖外部环境 |
3.2.3 templates/ — 模板渲染引擎
templates/ 目录是 Chart 的核心,存放所有 Go 模板文件。Helm 会将这些文件与 values.yaml 及内置对象(如 .Release、.Chart、.Files)结合,渲染出最终的 Kubernetes 资源清单。
- 模板文件命名: 通常以资源类型命名,如
deployment.yaml、service.yaml、ingress.yaml。测试文件建议放在templates/tests/子目录。 - 辅助模板:
_helpers.tpl用于定义可复用的命名模板(define),通过{{ include "chart-name.labels" . }}调用。 - 渲染规则: 所有
.yaml、.tpl、.txt文件都会被处理;其他后缀文件被忽略。空文件或仅含注释的文件不会产生输出。
{{- /* templates/_helpers.tpl 示例 */ -}}
{{- define "my-app.labels" -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}
3.2.4 NOTES.txt — 安装后的用户指引
NOTES.txt 是一个特殊的模板文件,在 helm install 或 helm upgrade 成功后,Helm 会将其渲染并输出到终端。它通常用于向用户展示如何访问应用、获取密码、查看状态等操作指引。
# templates/NOTES.txt 示例
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
http://{{ .Values.ingress.host }}
{{- else }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ .Chart.Name }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:{{ .Values.service.port }}
{{- end }}
测试注意事项:
NOTES.txt 也是模板文件,同样会被渲染。单元测试应覆盖 NOTES.txt 的渲染结果,确保在不同 values 组合下输出正确的指引信息。集成测试中,NOTES.txt 的内容可作为验证部署成功的辅助依据。
3.3 文件职责对比表
| 文件/目录 | 核心职责 | 是否参与渲染 | 测试验证点 |
|---|---|---|---|
Chart.yaml |
定义 Chart 元数据、版本、依赖 | 是(作为 .Chart 对象) |
版本号、依赖条件、类型字段正确传递 |
values.yaml |
提供默认配置值 | 是(作为 .Values 对象) |
默认值完整性、类型正确性、覆盖行为 |
templates/ |
存放 Go 模板,渲染为 K8s 资源 | 是(核心渲染单元) | 模板语法、资源结构、标签/注解、条件逻辑 |
NOTES.txt |
安装成功后的用户提示 | 是 | 提示信息正确性、条件分支渲染 |
charts/ |
子 Chart 依赖包 | 是(子 Chart 独立渲染) | 依赖版本、子 Chart 配置合并 |
crds/ |
自定义资源定义 | 否(直接安装,不经过模板引擎) | CRD 语法正确性、集群兼容性 |
3.4 目录结构对测试的影响
理解标准目录结构后,可以更高效地组织测试文件:
- 单元测试文件位置: 推荐在
templates/tests/下创建<resource>_test.yaml,使用helm test或helm unittest插件执行。 - 测试 values 文件: 在 Chart 根目录创建
ci/目录(如ci/test-values.yaml),用于集成测试的特定配置组合。 - 依赖管理: 子 Chart 的 values 合并行为需要在集成测试中验证,确保覆盖顺序正确。
- CRD 测试:
crds/中的 CRD 不经过模板引擎,需单独使用kubectl apply --dry-run或kubeconform校验。
最佳实践: 使用
helm create 生成骨架后,立即在 templates/tests/ 下创建至少一个单元测试文件,并编写 ci/ 目录下的集成测试 values 文件。这能确保从项目初始化阶段就具备可测试性。