3. Helm 基础回顾:Chart 结构、模板引擎、Values 与依赖管理

在深入 OPA 策略与 Helm 集成之前,必须牢固掌握 Helm 的核心基础。Helm 是 Kubernetes 的包管理工具,它将应用的所有 Kubernetes 资源定义、配置参数和部署逻辑打包为一个标准化的 Chart。本章将系统回顾 Chart 的目录结构、模板引擎的工作机制、Values 的传递与覆盖,以及依赖管理的最佳实践。

3.1 Chart 标准目录结构

一个标准的 Helm Chart 遵循固定的目录布局,每个文件和文件夹都有明确的职责。理解这一结构是编写可维护 Chart 的前提。

路径 / 文件 必需 说明
Chart.yaml 是 Chart 的元数据文件,包含名称、版本、API 版本、描述等。
values.yaml 是 默认配置值文件,模板引擎从这里读取变量。
templates/ 是 存放 Go 模板文件,渲染后生成 Kubernetes 资源清单。
charts/ 否 存放子 Chart(依赖 Chart)的压缩包或目录。
crds/ 否 自定义资源定义(CRD),在模板渲染前安装。
README.md 否 Chart 的使用说明文档。
.helmignore 否 打包时忽略的文件模式列表,类似 .gitignore。
关键原则: templates/ 目录下的所有文件都会被 Helm 模板引擎处理。非 .yaml 或 .tpl 文件会被原样复制,但通常建议只放置模板文件。

3.2 模板引擎核心机制

Helm 使用 Go 的 text/template 包作为模板引擎,并扩展了 sprig 函数库。模板引擎将 templates/ 中的文件与 values.yaml 及用户提供的值合并,生成最终的 Kubernetes 清单。

3.2.1 模板语法速览

  • 取值: {{ .Values.replicaCount }} — 从 Values 对象中读取 replicaCount。
  • 内置对象: .Values、.Release(发布信息)、.Chart(Chart 元数据)、.Files(文件访问)、.Capabilities(集群能力)。
  • 控制结构: {{- if .Values.service.enabled -}} … {{- end -}},{{- range .Values.containers -}} … {{- end -}}。
  • 管道与函数: {{ .Values.image.tag | default "latest" | quote }} — 使用 default 和 quote 函数。
  • 命名模板: 在 templates/_helpers.tpl 中定义,使用 {{- define "myapp.labels" -}},调用时使用 {{ include "myapp.labels" . }}。

3.2.2 模板渲染流程

Helm 模板渲染流程 values.yaml 用户 --set / -f templates/*.yaml _helpers.tpl Go text/template + Sprig 函数引擎 Kubernetes YAML 清单
调试技巧: 使用 helm template . 在本地渲染模板并输出 YAML,无需实际安装。使用 helm lint . 检查 Chart 语法和最佳实践。

3.3 Values 的层级与覆盖策略

Values 是 Helm 配置的核心。理解其层级结构和覆盖顺序,对于在多环境(开发、测试、生产)中复用同一 Chart 至关重要。

3.3.1 Values 来源与优先级(从低到高)

  1. Chart 内 values.yaml — 默认值,优先级最低。
  2. 父 Chart 的 values.yaml — 当 Chart 作为子 Chart 被依赖时,父 Chart 的值可以覆盖子 Chart 的默认值。
  3. 用户提供的 -f / --values 文件 — 可以指定多个文件,后指定的文件优先级更高。
  4. 命令行 --set 参数 — 直接传递键值对,优先级最高。

3.3.2 全局 Values 与子 Chart 值传递

当 Chart 包含子 Chart 时,可以通过 global 字段共享全局配置:

# 父 Chart 的 values.yaml
global:
  registry: "my-registry.cn"
  environment: "production"

# 子 Chart 模板中通过 .Values.global.registry 访问
注意: 子 Chart 默认无法直接访问父 Chart 的非 global 值。必须显式通过 global 或使用 --set 的层级语法(如 --set subchart.key=value)来传递。

3.4 依赖管理

Helm 支持通过 Chart.yaml 中的 dependencies 字段声明对其他 Chart 的依赖。依赖管理使得复杂应用可以拆分为多个可复用的组件。

3.4.1 声明依赖

# Chart.yaml
dependencies:
  - name: postgresql
    version: "12.1.0"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled   # 条件控制,当 postgresql.enabled 为 true 时安装
    tags:
      - database
  - name: redis
    version: "17.0.0"
    repository: "https://charts.bitnami.com/bitnami"
    tags:
      - cache

3.4.2 依赖管理命令

命令 作用
helm dependency update 根据 Chart.yaml 中的依赖声明,下载 Chart 包到 charts/ 目录,并生成 Chart.lock 锁定版本。
helm dependency build 基于 Chart.lock 文件重新下载依赖,确保可复现的构建。
helm dependency list 列出当前 Chart 的所有依赖及其状态。

3.4.3 子 Chart 的 Values 覆盖

在父 Chart 的 values.yaml 中,可以通过与子 Chart 同名的键来覆盖子 Chart 的默认值:

# 父 Chart values.yaml
postgresql:
  image:
    tag: "14.5"
  auth:
    database: "myapp"
    username: "appuser"

redis:
  architecture: "standalone"
  auth:
    enabled: false
最佳实践: 始终使用 helm dependency update 生成 Chart.lock 文件,并将其纳入版本控制。这可以确保团队和 CI/CD 流水线使用完全相同的依赖版本,避免“在我机器上能跑”的问题。

3.5 本章小结

Helm 的 Chart 结构、模板引擎、Values 层级和依赖管理共同构成了云原生应用打包与部署的基础。掌握这些概念后,你将能够设计出高度可配置、可复用的 Helm Chart。在下一阶段,我们将在此基础上引入 OPA 策略,在模板渲染和发布执行的关键节点注入合规校验,实现自动化治理。