3. Helm 基础回顾:Chart 结构、模板引擎、Values 文件、Release 管理

在集成 OPA 策略引擎之前,必须牢固掌握 Helm 的核心概念。Helm 是 Kubernetes 的包管理器,它将应用及其依赖打包为 Chart,通过 模板引擎 动态生成 Kubernetes 资源清单,利用 Values 文件 实现配置分离,并通过 Release 管理部署的生命周期。本节将逐一拆解这些基础组件,为后续的合规治理奠定技术基础。

3.1 Chart 目录结构

一个标准的 Helm Chart 是一个遵循特定布局的目录集合。理解其结构是创建和修改 Chart 的前提。

标准 Chart 结构示例:
my-app/
├── Chart.yaml          # Chart 元数据(名称、版本、描述等)
├── values.yaml         # 默认配置值
├── values.schema.json  # (可选)Values 的 JSON Schema 校验文件
├── charts/             # 子 Chart 依赖(手动或通过 helm dependency 管理)
├── templates/          # Go 模板文件,生成 Kubernetes 资源清单
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── _helpers.tpl    # 可复用的模板片段(命名模板)
│   └── tests/          # 测试连接的文件
│       └── test-connection.yaml
├── templates/NOTES.txt # 安装后显示的提示信息
├── README.md           # Chart 使用说明
└── .helmignore         # 打包时忽略的文件模式
文件/目录 作用 合规治理关注点
Chart.yaml 定义 Chart 名称、版本、API 版本、应用版本等 版本号策略、annotations 可携带合规标签
values.yaml 提供所有可配置参数的默认值 默认值必须符合基线安全策略
templates/ 存放 Go 模板,渲染后生成 YAML 模板中禁止硬编码敏感信息,必须引用 Values
charts/ 存放子 Chart 或依赖的 Chart 包 依赖的 Chart 也需要通过合规扫描
values.schema.json 对 values.yaml 进行结构校验 可强制要求某些字段必须存在且合规
💡 合规提示: 在 Chart.yaml 的 annotations 字段中,可以添加自定义合规元数据,例如 compliance/standard: "pci-dss",便于 OPA 策略在发布时进行匹配和审计。
Helm Chart 核心结构关系 my-app/ (Chart 根目录) Chart.yaml values.yaml templates/ charts/ (依赖) deployment.yaml service.yaml _helpers.tpl 说明:templates/ 目录是 Helm 模板引擎的核心工作区,所有 Kubernetes 资源清单均由此生成。

3.2 模板引擎与模板函数

Helm 使用 Go 的 text/template 引擎,并扩展了 60+ 个模板函数(来自 Sprig 库和内置函数)。模板引擎将 templates/ 目录下的文件与 values.yaml 及命令行传入的值结合,渲染出最终的 Kubernetes YAML。

3.2.1 核心模板语法

语法 说明 示例
{{ .Values.key }} 引用 Values 中的值 image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
{{- if condition -}} ... {{- end -}} 条件判断(- 用于消除空白) {{- if .Values.ingress.enabled }} ... {{- end }}
{{- range $i, $v := .Values.list -}} ... {{- end }} 遍历列表或字典 {{- range .Values.ports }} - port: {{ . }} {{- end }}
{{ include "chart.name" . }} 引用 _helpers.tpl 中定义的命名模板 name: {{ include "my-app.fullname" . }}
{{ .Chart.Name }} 内置对象,访问 Chart.yaml 中的字段 app.kubernetes.io/name: {{ .Chart.Name }}
{{ .Release.Name }} 内置对象,访问 Release 名称 app.kubernetes.io/instance: {{ .Release.Name }}
⚠️ 安全警告: 模板中禁止直接使用 {{ .Values.rawYaml | nindent 4 }} 这类将用户输入直接注入 YAML 的写法,这可能导致 YAML 注入攻击。OPA 策略应检查模板中是否存在 toYaml、fromYaml 等危险函数的不当使用。

3.2.2 管道与函数链

Helm 模板支持 Unix 风格的管道操作,将前一个函数的输出作为后一个函数的输入,实现数据转换。

# 将 Values 中的字符串转为大写并添加引号
{{ .Values.environment | upper | quote }}

# 默认值处理:如果 .Values.replicas 未定义,则使用 3
replicas: {{ .Values.replicas | default 3 }}

# 缩进控制:将多行字符串缩进 4 个空格
{{ .Values.annotations | toYaml | nindent 4 }}

3.3 Values 文件与配置分层

Values 文件是 Helm 实现配置与模板分离的关键机制。Helm 支持多级 Values 合并,优先级从低到高为:Chart 内置的 values.yaml → 父 Chart 的 Values → helm install -f 指定的文件 → --set 命令行参数。

Values 文件分层示例:
# values.yaml(Chart 默认值)
replicaCount: 1
image:
  repository: nginx
  tag: latest
  pullPolicy: IfNotPresent
service:
  type: ClusterIP
  port: 80

# production-values.yaml(生产环境覆盖)
replicaCount: 3
image:
  tag: 1.25.0
service:
  type: LoadBalancer

# 部署命令:helm install my-release ./my-app -f production-values.yaml --set image.tag=1.25.1

最终渲染时,image.tag 的值为 1.25.1(--set 优先级最高),replicaCount 为 3,service.type 为 LoadBalancer。

3.4 Release 管理

Release 是 Helm 中一个 Chart 实例的部署运行态。每次 helm install 都会创建一个新的 Release,每次 helm upgrade 都会生成一个新的 Revision(修订版本)。

Helm 命令 作用 Release 状态变化
helm install 首次部署 Chart,创建 Release 从 pending-install → deployed
helm upgrade 升级 Release 到新版本 旧 Revision 变为 superseded,新 Revision 变为 deployed
helm rollback 回滚到之前的 Revision 目标 Revision 变为 deployed,当前变为 superseded
helm uninstall 删除 Release 及其所有资源 变为 uninstalled(默认保留历史记录)
helm list 列出所有 Release 显示名称、命名空间、Chart、状态、Revision 等
💡 合规治理切入点: OPA 策略可以在 helm install 和 helm upgrade 的 Webhook 中拦截请求,检查 Release 的 values 是否满足安全基线(如禁止 privileged: true、必须设置 resources.limits 等),从而在部署前阻断不合规的 Release。
Release 生命周期与 Revision 管理 pending-install deployed (v1) deployed (v2) uninstalled install upgrade uninstall rollback Helm 默认保留 Release 历史记录(可通过 --history-max 控制) 每个 Revision 包含完整的 Values 和渲染后的 Manifest,用于审计和回滚 合规审计点:OPA 可检查 Release 的 Revision 历史,确保每次升级都经过合规审批 禁止跳过合规检查的 --force 或 --atomic 操作

3.5 内置对象与作用域

Helm 模板中预置了多个内置对象,用于访问 Chart 元数据、Release 信息、Values 和文件内容。理解这些对象的作用域是编写复杂模板的基础。

内置对象 类型 常用字段
.Chart Chart.yaml 内容 .Name, .Version, .AppVersion, .Annotations
.Release 当前 Release 信息 .Name, .Namespace, .IsInstall, .IsUpgrade, .Revision
.Values 合并后的 Values 所有用户配置和默认值
.Files Chart 内文件访问 .Get "filename", .Glob "pattern"
.Capabilities Kubernetes 集群能力 .APIVersions.Has "apps/v1", .KubeVersion
.Template 当前模板信息 .Name, .BasePath
作用域与 $ 变量: 在 range 或 with 块内,当前上下文(.)会改变。要访问根作用域,使用 $.Values、$.Release.Name 等。例如:
{{- range .Values.containers }}
- name: {{ .name }}  # 这里的 . 是容器对象
  image: {{ $.Values.global.registry }}/{{ .image }}  # $.Values 访问根 Values
{{- end }}

3.6 依赖管理与子 Chart

大型应用通常拆分为多个子 Chart。Helm 通过 charts/ 目录或 Chart.yaml 中的 dependencies 字段管理依赖。

# Chart.yaml 中的依赖声明
dependencies:
  - name: postgresql
    version: "12.1.0"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled  # 条件控制是否安装
    tags:
      - database

子 Chart 的 Values 可以通过全局值(global 字段)共享配置,也可以被父 Chart 的 Values 覆盖。OPA 策略需要递归检查所有子 Chart 的合规性,因为子 Chart 中的不安全配置同样会引入风险。

⚠️ 依赖管理风险: 使用 helm dependency update 时,会从远程仓库下载 Chart 包。OPA 策略应要求所有依赖的 Chart 来源必须是经过审批的受信任仓库,并检查其 Chart.yaml 中的签名或摘要信息。