3. Helm 基础回顾:Chart 结构、模板渲染机制、Values 与依赖管理、Release 生命周期

在深入 Kyverno 与 Helm 的故障域隔离策略冲突排查之前,必须牢固掌握 Helm 的核心运行机制。Helm 作为 Kubernetes 的包管理工具,其 Chart 结构、模板渲染、Values 传递以及 Release 管理构成了策略冲突发生的底层土壤。本节将系统梳理这些基础概念,为后续分析策略注入点与冲突根因奠定基础。

3.1 Chart 目录结构

一个标准的 Helm Chart 是一个遵循特定布局的目录集合。每个 Chart 都包含描述自身元数据的 Chart.yaml 文件,以及用于生成 Kubernetes 资源的模板文件。

文件/目录 用途说明
Chart.yaml Chart 的元数据文件,包含名称、版本、描述、API 版本、依赖声明等。
values.yaml 默认的配置值文件,定义了模板中使用的所有可配置参数的默认值。
templates/ 存放 Go 模板文件的目录,模板渲染后生成 Kubernetes 资源清单(YAML)。
charts/ 存放子 Chart(依赖)的目录,当 Chart 有依赖时,依赖包会被下载到此目录。
crds/ 存放自定义资源定义(CRD)的目录,Helm 会在安装时优先安装这些 CRD。
templates/NOTES.txt 安装成功后向用户显示的帮助文本,通常包含使用说明或访问地址。
templates/_helpers.tpl 存放可复用的模板片段(命名模板),通过 include 或 template 函数调用。
策略冲突关注点: Kyverno 策略通常作用于 templates/ 目录渲染出的最终资源。如果 _helpers.tpl 中定义的标签或注解与策略的匹配规则冲突,会导致安装失败或资源被策略拒绝。

3.2 模板渲染机制

Helm 的模板引擎基于 Go 的 text/template 包,并扩展了 50 多个模板函数。渲染过程将 values.yaml 中的值注入到 templates/ 目录下的 Go 模板文件中,最终生成纯 YAML 资源清单。

核心渲染流程:
  1. 值合并: 将默认 values.yaml、用户提供的 --set 参数、外部 values 文件按优先级合并为一个全局 Values 对象。
  2. 模板解析: 遍历 templates/ 目录下的所有 .yaml、.tpl、.txt 文件,解析其中的模板指令(如 {{ .Values.replicaCount }})。
  3. 函数执行: 执行模板中的控制结构(if、range、with)和函数调用(include、required、toYaml)。
  4. 输出生成: 将渲染后的结果输出为标准的 Kubernetes YAML 资源,每个模板文件对应一个或多个资源。
# 示例:templates/deployment.yaml 中的模板片段
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "myapp.fullname" . }}
  labels:
    {{- include "myapp.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "myapp.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "myapp.selectorLabels" . | nindent 8 }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
策略冲突风险: 模板中的 include 函数可能动态生成标签或注解,这些动态值若与 Kyverno 策略中的 match 或 exclude 规则不匹配,会导致策略无法正确应用到预期资源,或错误地拦截本应放行的资源。

3.3 Values 与依赖管理

Values 是 Helm 配置的核心,它通过层级结构和优先级规则实现灵活的配置覆盖。依赖管理则允许一个 Chart 引用其他 Chart,形成复合应用。

Values 优先级(从低到高)

  1. Chart 内置的 values.yaml:最低优先级,提供默认值。
  2. 父 Chart 的 values.yaml:当 Chart 作为子 Chart 被依赖时,父 Chart 的值可以覆盖子 Chart 的默认值。
  3. 用户提供的 values 文件:通过 -f 或 --values 参数指定的 YAML 文件。
  4. 命令行 --set 参数:最高优先级,直接覆盖所有层级的值。

依赖管理机制

在 Chart.yaml 中使用 dependencies 字段声明依赖,Helm 会解析并下载依赖 Chart 到 charts/ 目录。依赖 Chart 的 Values 可以通过全局值(global)或子 Chart 名称作用域进行传递。

# Chart.yaml 中的依赖声明示例
dependencies:
  - name: redis
    version: "17.3.0"
    repository: "https://charts.bitnami.com/bitnami"
    condition: redis.enabled
    tags:
      - cache
  - name: postgresql
    version: "12.1.0"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled
策略冲突关注点: 依赖 Chart 的 Values 传递路径复杂,父 Chart 的 global 值会穿透到所有子 Chart。如果 Kyverno 策略检查资源上的特定注解(如 policy.kyverno.io/inject-sidecar),而该注解通过 global 值传递时被覆盖或遗漏,会导致策略行为异常。

3.4 Release 生命周期

Release 是 Helm Chart 的一次部署实例。每个 Release 都有唯一的名称和版本号,Helm 通过 Release 对象管理应用的安装、升级、回滚和卸载。

Helm Release 生命周期 helm install PENDING DEPLOYED FAILED helm upgrade SUPERSEDED helm rollback UNINSTALLED 安装失败或策略拒绝

Release 状态转换说明

状态 触发操作 策略冲突典型场景
PENDING helm install 执行中 Kyverno 策略在资源创建前拦截,导致安装卡在 PENDING 状态。
DEPLOYED 安装/升级成功 策略允许资源创建,但后续策略变更可能导致下次升级失败。
FAILED 安装/升级过程中出错 模板渲染后的资源违反 Kyverno 策略(如缺少必需标签、镜像来源受限)。
SUPERSEDED 新版本 Release 被部署 旧版本 Release 被标记为 SUPERSEDED,但其资源可能仍被策略审计。
UNINSTALLED helm uninstall 卸载时,Kyverno 策略可能阻止删除某些资源(如 PVC、Namespace)。
关键排查线索: 当 Release 处于 FAILED 状态时,使用 helm get manifest RELEASE_NAME 可以查看 Helm 实际提交给 Kubernetes 的最终 YAML 清单。将此清单与 Kyverno 策略的匹配规则进行比对,是定位冲突的最直接方法。

3.5 模板渲染与策略注入点

理解 Helm 模板渲染的时机和输出,对于定位 Kyverno 策略冲突至关重要。策略引擎在 Helm 提交资源清单后介入,因此冲突发生在渲染后的 YAML 层面。

Helm 模板渲染与 Kyverno 策略作用域 Chart 模板 + Values (Go 模板引擎) 渲染后 YAML 清单 (纯 Kubernetes 资源) Kyverno 策略引擎 (验证/变更/生成) K8s API (资源创建) 冲突排查关键:检查渲染后的 YAML 是否包含策略要求的标签、注解、安全上下文等字段 使用 helm template 命令可在不安装的情况下预览渲染结果
排查实用命令:
  • helm template RELEASE_NAME CHART_DIR — 本地渲染模板,输出 YAML 到标准输出,用于离线检查策略合规性。
  • helm get manifest RELEASE_NAME — 获取已安装 Release 的最终资源清单,用于对比实际部署与策略要求。
  • helm get values RELEASE_NAME — 查看 Release 使用的最终 Values 值,帮助定位值传递问题。