3. Chart 目录结构:核心文件作用与规范
一个标准的 Helm Chart 遵循固定的目录布局。理解每个文件和目录的职责,是进行 Chart 开发、治理与运维的基础。本章将详细拆解 Chart 目录结构,并明确各核心文件的编写规范。
核心原则: Helm Chart 的目录结构是约定优于配置的体现。严格遵循官方规范,可以确保 Chart 的可移植性、可维护性以及被 Helm 工具链正确解析。
3.1 标准 Chart 目录全景
一个典型的 Chart 包(如 my-app-1.0.0.tgz)解压后,其内部目录结构如下所示。所有文件均位于以 Chart 名称命名的顶级目录下。
my-app/
├── Chart.yaml # Chart 元数据定义文件(必需)
├── values.yaml # 默认配置值文件(必需)
├── values.schema.json # values.yaml 的 JSON Schema 校验文件(可选)
├── charts/ # 子 Chart 依赖目录(可选)
│ └── redis-17.3.0.tgz
├── templates/ # Kubernetes 资源模板目录(必需)
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── _helpers.tpl # 模板辅助函数(可选)
│ └── tests/
│ └── test-connection.yaml
├── templates/NOTES.txt # 部署后的使用说明模板(可选)
├── README.md # Chart 的说明文档(推荐)
├── LICENSE # 许可证文件(可选)
└── .helmignore # 打包时忽略的文件列表(可选)
运维提示: 在 CI/CD 流水线中,应使用
helm lint 命令对 Chart 目录结构进行静态检查。该命令会验证必需文件是否存在、YAML 语法是否正确以及模板是否能被正常渲染。
3.2 核心文件作用与规范
下表详细列出了每个核心文件的作用、规范要求以及常见治理检查点。
| 文件/目录 | 必需性 | 核心作用 | 关键规范与治理要点 |
|---|---|---|---|
Chart.yaml |
必需 | 定义 Chart 的名称、版本、API 版本、描述、关键字等元数据。 |
|
values.yaml |
必需 | 提供所有可配置参数的默认值,是 Chart 的配置接口。 |
|
templates/ |
必需 | 存放 Go 模板文件,用于渲染 Kubernetes 资源清单。 |
|
charts/ |
可选 | 存放子 Chart 的打包文件(.tgz),用于管理依赖。 |
|
templates/NOTES.txt |
推荐 | 在 helm install 或 helm upgrade 成功后,向用户打印使用说明。 |
|
3.3 文件依赖与数据流关系
下图展示了 Chart 在渲染过程中,各核心文件之间的数据流与依赖关系。理解此流程有助于定位配置问题。
3.4 关键文件编写规范详解
3.4.1 Chart.yaml:Chart 的身份证
Chart.yaml 是 Helm 识别一个 Chart 的首要文件。其内容必须遵循严格的格式和字段要求。
apiVersion: v2
name: my-app
description: A Helm chart for deploying my-app on Kubernetes
type: application
# Chart 版本,每次发布新 Chart 包时必须递增
version: 1.2.3
# 被部署应用的版本,可独立于 Chart 版本更新
appVersion: "3.0.0"
# 关键字,用于 helm search 索引
keywords:
- web
- application
# 维护者信息
maintainers:
- name: DevOps Team
email: devops@example.com
# 依赖声明
dependencies:
- name: redis
version: "~17.3.0"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
tags:
- cache
治理红线:
- 版本不可变: 一旦 Chart 被发布到仓库,其
version字段对应的包内容就不可再修改。任何变更都必须通过递增version来发布新版本。 - 依赖版本锁定: 在
Chart.yaml中使用~或^等范围约束时,必须配合Chart.lock文件锁定具体版本,确保可重复构建。
3.4.2 values.yaml:配置的单一入口
values.yaml 是 Chart 与用户交互的核心界面。良好的 values.yaml 设计能极大降低使用复杂度。
# 全局配置
global:
imageRegistry: ""
# 应用副本数
replicaCount: 3
# 镜像配置
image:
repository: nginx
tag: "1.25.3"
pullPolicy: IfNotPresent
# 服务配置
service:
type: ClusterIP
port: 80
# 资源限制
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
# 是否启用 ingress
ingress:
enabled: false
className: ""
hosts:
- host: my-app.local
paths:
- path: /
pathType: Prefix
# 子 Chart 控制
redis:
enabled: true
architecture: standalone
最佳实践:
- 为每个参数添加
# -- 描述注释,便于生成文档。 - 使用
values.schema.json对参数类型、取值范围进行强制校验,防止错误配置导致部署失败。 - 将敏感参数(如密码)的默认值设为空字符串
"",并在NOTES.txt中提示用户必须通过--set或外部 Secret 提供。
3.4.3 templates/ 目录:资源模板的规范
templates/ 目录下的每个文件都应遵循以下规范,以确保模板的可读性和可维护性。
{{- /* 文件头:声明 API 版本和资源类型 */ -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-app.fullname" . }}
labels:
{{- include "my-app.labels" . | nindent 4 }}
spec:
{{- /* 使用 values.yaml 中的配置 */}}
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "my-app.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "my-app.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.port }}
模板治理清单:
- 标签标准化: 所有资源必须包含
app.kubernetes.io/name、app.kubernetes.io/instance、app.kubernetes.io/version等推荐标签。 - 命名空间隔离: 模板中不应硬编码
namespace,应使用{{ .Release.Namespace }}动态获取。 - 辅助函数复用: 将重复的标签、名称定义提取到
_helpers.tpl中,通过include引用。 - 条件渲染: 使用
{{- if .Values.ingress.enabled }}控制可选资源的生成。
3.4.4 templates/NOTES.txt:部署后的用户手册
NOTES.txt 是 Helm 与用户交互的最后一个环节。一个优秀的 NOTES.txt 能显著提升用户体验。
Thank you for installing {{ .Chart.Name }}.
Your release is named {{ .Release.Name }}.
To access the application from outside the cluster, follow these steps:
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
http://{{ (index .Values.ingress.hosts 0).host }}{{ (index (index .Values.ingress.hosts 0).paths 0).path }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "my-app.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "my-app.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- end }}
2. Default credentials (if applicable):
Username: admin
Password: {{ .Values.adminPassword | default "NOT SET - please set adminPassword" }}
安全警告: 不要在
NOTES.txt 中直接输出明文密码。如果必须提供默认凭据,应使用 {{ .Values.adminPassword | default "请通过 --set 设置 adminPassword" }} 的方式提示用户。3.5 目录结构治理检查清单
在 Chart 发布前,运维团队应使用以下清单进行自动化检查。
- 必需文件完整性: 确认
Chart.yaml、values.yaml、templates/目录存在且非空。 - YAML 语法校验: 使用
helm lint检查所有 YAML 文件的语法正确性。 - 模板渲染测试: 使用
helm template --debug检查模板是否能正确渲染,且输出符合 K8s 资源规范。 - 依赖完整性: 检查
Chart.lock文件是否存在,且与Chart.yaml中的依赖声明一致。 - 敏感信息扫描: 扫描
values.yaml和templates/中是否包含硬编码的密码、密钥或 。 - NOTES.txt 可读性: 确认
NOTES.txt模板语法正确,且不输出未定义的变量。
自动化集成: 将上述检查清单集成到 CI/CD 流水线的
pre-commit 钩子或 chart-testing 工具中,实现 Chart 质量的左移。