3. Helm Chart 基础:Chart 结构、Values.yaml 设计原则、模板函数与作用域、依赖管理
在构建 CSI 存储变更门禁系统时,Helm Chart 是定义、打包和部署存储插件的标准载体。理解 Chart 的内部结构、Values 设计模式、模板引擎机制以及依赖管理方式,是编写可维护、可测试的存储变更门禁策略的前提。本节将围绕这四个核心维度展开。
3.1 Chart 标准目录结构
一个标准的 Helm Chart 遵循固定的目录布局,CSI 存储插件的 Chart 通常包含以下关键文件和目录:
| 路径 / 文件 | 用途说明 | CSI 场景示例 |
|---|---|---|
Chart.yaml |
Chart 元数据:名称、版本、API 版本、描述 | 定义 CSI 驱动名称、门禁策略版本号 |
values.yaml |
默认配置值,用户可覆盖 | 存储后端地址、卷挂载参数、性能阈值 |
templates/ |
Go 模板文件,生成 Kubernetes 资源清单 | Deployment、DaemonSet、StorageClass、CSIDriver |
charts/ |
子 Chart 或依赖 Chart 的存放目录 | 依赖的外部 CSI sidecar 容器 Chart |
crds/ |
自定义资源定义(CRD),Helm 3 特殊处理 | 存储变更门禁的 CRD:StorageGatePolicy |
templates/NOTES.txt |
安装成功后输出的使用说明 | 提示用户如何验证 CSI 驱动就绪状态 |
实践要点:CSI 存储插件的
templates/ 目录应保持扁平化,避免嵌套过深。建议按资源类型拆分文件,例如 csi-controller.yaml、csi-node.yaml、storageclass.yaml,便于 SRE 在回滚时快速定位问题模板。
3.2 Values.yaml 设计原则
values.yaml 是 Chart 的配置接口,其设计质量直接影响 CSI 存储门禁的可配置性和回滚安全性。以下是针对存储场景的四个核心原则:
- 扁平化优先,嵌套不超过三层:存储配置参数(如
storageClass.name、csiDriver.name)应放在顶层或一层命名空间下,避免深层嵌套导致模板取值混乱。 - 类型明确,提供默认值:所有字段必须标注类型注释,CSI 相关参数(如
volumeExpansion.enabled)必须提供安全的默认值。 - 敏感信息分离:存储后端密钥、认证凭据不应硬编码在 values.yaml 中,应通过
--set或外部 Secret 引用。 - 版本化与兼容性标记:在 values.yaml 顶部使用
# @schema注释标记兼容的 Chart 版本范围,辅助 Helm 在升级时进行校验。
CSI 存储门禁 Values 示例片段:
# values.yaml — CSI 存储变更门禁默认配置
# Chart 版本: 1.2.0
# 兼容 CSI 规范: v1.6+
global:
clusterName: "production-cluster"
csiDriver:
name: "csi.storage.gate.io"
version: "3.0.0"
attachRequired: true
podInfoOnMount: true
storageClass:
name: "fast-ssd-gate"
provisioner: "csi.storage.gate.io"
reclaimPolicy: "Delete"
volumeExpansion:
enabled: false # 默认关闭卷扩展,防止误操作
maxSize: "1Ti"
gatePolicy:
performanceBaseline:
iopsThreshold: 5000 # IOPS 门禁阈值
latencyThresholdMs: 10 # 延迟门禁阈值(毫秒)
rollbackStrategy:
maxRetries: 3
cooldownSeconds: 30
# 敏感信息不在此处定义,通过 --set 或外部 Secret 注入
# storageBackend:
# : ""
3.3 模板函数与作用域
Helm 使用 Go 模板引擎扩展 Kubernetes 资源清单的灵活性。在 CSI 存储门禁场景中,模板函数主要用于条件渲染、数据转换和作用域控制。
3.3.1 常用模板函数
| 函数 / 管道 | 作用 | CSI 存储示例 |
|---|---|---|
default |
为缺失值提供默认值 | default "Delete" .Values.storageClass.reclaimPolicy |
quote |
将值转为字符串并加引号 | quote .Values.csiDriver.name |
include |
调用命名模板并返回字符串 | include "csi.labels" . |
toYaml |
将结构体转为 YAML 字符串 | toYaml .Values.gatePolicy | nindent 4 |
hasKey |
检查字典中是否存在指定键 | hasKey .Values "storageBackend" |
3.3.2 作用域控制:$ 与 .
在 range 或 with 块中,当前上下文 . 会被重置为迭代元素。要访问全局 Values,必须使用 $ 根作用域:
{{- range .Values.storageClasses }}
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: {{ .name }} # 当前迭代元素的 name
labels:
app: {{ $.Values.global.appName }} # 通过 $ 访问根 Values
provisioner: {{ $.Values.csiDriver.name }}
{{- end }}
常见陷阱:在
range 块内忘记使用 $ 访问全局变量,会导致模板渲染为空或错误。CSI 场景中,StorageClass 的 provisioner 字段通常来自全局 csiDriver.name,必须显式使用 $.Values.csiDriver.name。
3.4 依赖管理
CSI 存储插件通常依赖多个 sidecar 容器(如 csi-provisioner、csi-attacher、csi-resizer)。Helm 通过 Chart.yaml 中的 dependencies 字段管理这些外部 Chart。
3.4.1 声明依赖
# Chart.yaml
apiVersion: v2
name: csi-storage-gate
version: 1.2.0
dependencies:
- name: csi-provisioner
version: "3.5.0"
repository: "https://kubernetes-csi.github.io/charts"
condition: csi-provisioner.enabled # 条件控制,默认启用
- name: csi-attacher
version: "4.0.0"
repository: "https://kubernetes-csi.github.io/charts"
condition: csi-attacher.enabled
- name: csi-resizer
version: "1.8.0"
repository: "https://kubernetes-csi.github.io/charts"
condition: csi-resizer.enabled
3.4.2 依赖管理命令
| 命令 | 说明 | 使用时机 |
|---|---|---|
helm dependency update |
根据 Chart.yaml 下载依赖到 charts/ 目录 |
首次构建或依赖版本变更时 |
helm dependency build |
从 Chart.lock 锁定版本重建依赖 |
确保可复现的构建环境 |
helm dependency list |
列出当前依赖状态 | 调试依赖缺失或版本冲突 |
3.4.3 子 Chart 的值覆盖
在父 Chart 的 values.yaml 中,可以通过与子 Chart 同名的键覆盖其默认值:
# 父 Chart values.yaml
csi-provisioner:
enabled: true
replicaCount: 2
resources:
limits:
cpu: "500m"
memory: "512Mi"
csi-attacher:
enabled: false # 在本次部署中禁用 attacher
依赖管理最佳实践:在 CSI 存储门禁场景中,建议将 sidecar 依赖的版本锁定在
Chart.lock 中,并在 CI/CD 流水线中执行 helm dependency build,避免因上游 Chart 非预期更新导致门禁策略失效。
3.5 本节要点总结
- Chart 结构:
templates/按 CSI 资源类型拆分,crds/存放门禁 CRD,charts/管理 sidecar 依赖。 - Values 设计:扁平化、类型明确、敏感信息分离、版本兼容标记。
- 模板函数:
default、include、toYaml是 CSI 模板高频函数;$用于range块内访问根作用域。 - 依赖管理:使用
Chart.yaml声明依赖,helm dependency build锁定版本,父 Chart 通过同名键覆盖子 Chart 值。