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

Helm 是 Kubernetes 生态中事实上的包管理标准。一个 Helm Chart 本质上是一个预配置的 Kubernetes 资源模板集合,通过参数化实现环境间复用。本节从四个核心维度系统回顾 Chart 的基础知识,为后续跨集群调度与安全审计奠定技术基础。

4.1 Chart 目录结构与核心文件

一个标准 Chart 遵循固定目录布局,Helm CLI 通过该结构识别元数据、模板、依赖和资源文件。下表列出核心文件及其职责:

文件/目录 必需 说明
Chart.yaml 是 Chart 元数据:名称、版本、API 版本、描述、关键字等
values.yaml 是 默认配置值,模板引擎的输入数据源
templates/ 是 Go 模板文件目录,渲染后生成 Kubernetes 清单
charts/ 否 子 Chart 或依赖 Chart 的打包文件(.tgz)存放目录
crds/ 否 自定义资源定义(CRD),在模板渲染前安装
templates/NOTES.txt 否 安装成功后输出的使用说明文本
templates/_helpers.tpl 否 模板命名片段定义,供其他模板复用
安全审计要点: 在变更门禁场景中,Chart.yaml 中的 apiVersion 字段必须为 v2(Helm 3+),禁止使用已废弃的 v1。同时需检查 templates/ 目录下是否存在非 Kubernetes 资源文件(如 shell 脚本、敏感配置文件),防止模板注入风险。
Helm Chart 标准目录结构 mychart/ Chart.yaml values.yaml templates/ charts/ deployment.yaml service.yaml _helpers.tpl NOTES.txt 说明: templates/ 目录下的所有 .yaml/.tpl 文件都会经过 Go 模板引擎渲染;charts/ 目录存放已解析的依赖包;crds/ 目录在模板渲染前安装。

4.2 模板引擎(Go Template)核心机制

Helm 使用 Go 标准库 text/template 作为模板引擎,并扩展了 Sprig 函数库(超过 70 个字符串、数学、列表、字典操作函数)。模板引擎将 values.yaml 中的值注入到 templates/ 目录下的模板文件中,最终生成完整的 Kubernetes 清单。

4.2.1 基本语法与数据注入

# values.yaml
replicaCount: 3
image:
  repository: nginx
  tag: "1.25"
service:
  port: 80
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-nginx
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Chart.Name }}
  template:
    metadata:
      labels:
        app: {{ .Chart.Name }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          ports:
            - containerPort: {{ .Values.service.port }}
内置对象速查: .Values 指向 values.yaml 及用户传入的自定义值;.Release 包含 Release 名称、命名空间、版本号等元数据;.Chart 提供 Chart.yaml 中的字段;.Files 允许访问 Chart 内的非模板文件。

4.2.2 流程控制与函数

模板引擎支持 if/else、range(循环)、with(作用域切换)等控制结构。以下示例展示条件判断与默认值函数:

{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ .Release.Name }}-ingress
spec:
  rules:
    - host: {{ .Values.ingress.host | default "example.com" }}
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: {{ .Release.Name }}-service
                port:
                  number: {{ .Values.service.port }}
{{- end }}
安全审计红线: 模板中禁止直接使用 tpl 函数渲染用户输入字符串,防止模板注入攻击。所有用户提供的值必须经过 quote、squote 或 toYaml 等安全函数转义。在变更门禁中,应扫描模板文件中的 tpl、include 调用链,确保无未过滤的外部输入。

4.3 Values 文件管理与优先级

Helm 支持多层 Values 覆盖机制,理解优先级顺序对跨集群配置管理至关重要。以下为完整的 Values 优先级链(从低到高):

  1. Chart 内置 values.yaml —— 默认值,最低优先级
  2. 父 Chart 的 values.yaml —— 当 Chart 作为子 Chart 被引用时,父 Chart 的值可覆盖子 Chart 默认值
  3. helm install -f 或 helm upgrade -f 指定的外部 YAML 文件 —— 可指定多个文件,后出现的文件优先级更高
  4. --set 命令行参数 —— 覆盖单个键值对,支持 key=value 和 JSON 路径语法
  5. --set-string 命令行参数 —— 强制将值视为字符串,避免自动类型推断
场景 命令示例 优先级说明
仅使用默认值 helm install myapp ./mychart 仅加载 values.yaml
覆盖单个值 --set image.tag=1.26 覆盖 values.yaml 中的 image.tag
多环境配置 -f prod-values.yaml -f region-override.yaml 后者覆盖前者,最终合并结果覆盖默认值
全局值传递 --set global.cluster=prod-eu 全局值可被子 Chart 通过 .Values.global 访问
跨集群调度实践: 在变更门禁审计中,建议将集群特定配置(如集群名称、区域、节点池标签)放入独立的 cluster-values.yaml 文件,并通过 -f 参数注入。审计规则应检查是否所有 --set 参数都对应 values.yaml 中已声明的键,防止未预期的配置漂移。

4.4 依赖管理与子 Chart

Helm 通过 Chart.yaml 中的 dependencies 字段声明子 Chart 依赖。依赖管理支持版本约束、仓库别名、条件启用等高级特性。

4.4.1 依赖声明与版本约束

# Chart.yaml
apiVersion: v2
name: myapp
version: 1.0.0
dependencies:
  - name: redis
    version: ">=17.0.0 < 18.0.0"
    repository: "https://charts.bitnami.com/bitnami"
    condition: redis.enabled
    alias: cache
  - name: postgresql
    version: "12.x"
    repository: "https://charts.bitnami.com/bitnami"
    tags:
      - database
      - production

依赖管理常用命令:

  • helm dependency update —— 根据 Chart.yaml 下载依赖到 charts/ 目录并生成 Chart.lock 锁定文件
  • helm dependency build —— 使用 Chart.lock 中的精确版本重建依赖,确保可复现
  • helm dependency list —— 显示当前依赖状态(已下载、缺失、版本不匹配)

4.4.2 子 Chart 的值传递与作用域

子 Chart 的 Values 通过父 Chart 的 values.yaml 中与子 Chart 同名的键传递。以下示例展示如何为 redis 子 Chart 传递配置:

# 父 Chart 的 values.yaml
redis:
  enabled: true
  architecture: standalone
  auth:
    enabled: false
  master:
    persistence:
      enabled: false

# 子 Chart 内部通过 .Values.architecture 访问上述值
全局值(global)机制: 所有子 Chart 均可通过 .Values.global 访问父 Chart 中 global 键下的值。该机制适用于跨子 Chart 共享的配置,如全局集群名称、公共标签、镜像仓库地址等。在安全审计中,应检查 global 值是否被意外覆盖或泄露。
Helm 依赖管理与子 Chart 值传递流程 父 Chart (myapp) 子 Chart: redis 子 Chart: postgresql 子 Chart: common 值传递规则: 父 Chart values.yaml 中 redis: { ... } 自动注入到 redis 子 Chart 的 .Values 中;global: { ... } 对所有子 Chart 可见。 helm dep update 生成 Chart.lock helm dep build

4.5 安全审计视角下的 Chart 基础检查清单

在变更门禁流水线中,对 Helm Chart 的基础审查应包含以下维度:

检查项 审计标准 风险等级
Chart.yaml API 版本 必须为 v2,禁止 v1 高
模板中 tpl 函数使用 禁止直接渲染用户输入;必须经过 quote 或白名单校验 严重
Values 文件敏感信息 密码、密钥、 必须通过 --set 或外部 Secret 管理,禁止硬编码 高
依赖版本锁定 必须存在 Chart.lock 且与 Chart.yaml 中的依赖声明一致 中
子 Chart 条件启用 使用 condition 字段控制子 Chart 启用,避免空依赖安装 低
全局值污染 global 键下的值不应被子 Chart 意外覆盖,建议使用唯一前缀 中
变更门禁阻断规则: 当检测到模板中包含 tpl .Values.* 且未使用 quote 或 squote 包裹时,流水线应直接阻断并返回安全告警。同时,Chart.lock 缺失或与 Chart.yaml 版本不匹配时,应触发警告但允许人工审批通过。