3. Helm 依赖管理:子 Chart 与全局值、条件依赖、hooks 机制

在生产级 Helm 应用中,一个 Chart 往往需要依赖多个子 Chart(如 MySQL、Redis、Prometheus)来组成完整的服务栈。Helm 的依赖管理机制允许你声明式地定义这些子 Chart,并通过 全局值、条件依赖 和 Hooks 实现精细化的交付控制。本章将深入剖析这三项核心能力,并结合 SRE 场景说明其应用。

3.1 子 Chart 与全局值传递

子 Chart 通过 Chart.yaml 中的 dependencies 字段声明。Helm 会从仓库下载或本地路径引用子 Chart,并在渲染时将其模板合并到父 Chart 中。

3.1.1 依赖声明与值覆盖

以下是一个典型的 Chart.yaml 依赖声明:

# Chart.yaml
apiVersion: v2
name: myapp
version: 1.0.0
dependencies:
  - name: redis
    version: "~17.0.0"
    repository: "https://charts.bitnami.com/bitnami"
    alias: cache
  - name: mysql
    version: "~9.0.0"
    repository: "https://charts.bitnami.com/bitnami"
    condition: mysql.enabled

子 Chart 的值默认从父 Chart 的 values.yaml 中同名键读取。例如,父 Chart 中 redis.xxx 会传递给子 Chart redis。但更推荐使用 全局值 实现跨 Chart 共享配置。

3.1.2 全局值(Global Values)

全局值通过父 Chart values.yaml 中的 global 字段定义,所有子 Chart 均可直接引用。这在设置公共环境标签、镜像仓库地址、全局开关时非常有用。

# 父 Chart values.yaml
global:
  registry: "registry.internal.company.com"
  environment: "production"
  labels:
    team: "sre"
    app: "myapp"

redis:
  image:
    registry: "{{ .Values.global.registry }}"
  fullnameOverride: "myapp-cache"

mysql:
  enabled: true
  image:
    registry: "{{ .Values.global.registry }}"
SRE 最佳实践: 使用全局值统一管理镜像仓库、环境标签和告警接收地址,避免在每个子 Chart 中重复定义。当发生 DNS 延迟故障时,全局标签可帮助快速定位受影响的服务实例。

3.2 条件依赖(Conditional Dependencies)

条件依赖允许根据父 Chart 的值动态启用或禁用子 Chart。这在多环境部署(如开发环境不启用 MySQL 集群,生产环境启用)中至关重要。

3.2.1 条件声明与使用

在 Chart.yaml 的依赖项中,使用 condition 字段指定一个布尔值路径:

# Chart.yaml
dependencies:
  - name: mysql
    condition: mysql.enabled  # 当 .Values.mysql.enabled 为 true 时安装
  - name: redis
    condition: redis.enabled  # 当 .Values.redis.enabled 为 true 时安装

在 values.yaml 中控制开关:

# values.yaml
mysql:
  enabled: true
redis:
  enabled: false

执行 helm dependency update 后,Helm 会根据条件生成锁文件 Chart.lock,并在安装时只渲染启用的子 Chart。

3.2.2 条件依赖与全局值联动

条件依赖可以与全局值结合,实现更复杂的策略:

# values.yaml
global:
  highAvailability: true

mysql:
  enabled: "{{ .Values.global.highAvailability }}"
  replicaCount: 3
注意: 条件依赖的值必须在父 Chart 的 values.yaml 中显式定义,否则 Helm 会将其视为 false 并跳过子 Chart。在 SLO 违约后的快速恢复场景中,错误的条件配置可能导致关键依赖缺失。

3.3 Hooks 机制:Pre/Post Install、Upgrade、Delete

Helm Hooks 允许在 Release 生命周期的特定节点执行自定义 Job。这对于数据库迁移、预热缓存、DNS 记录更新、SLO 违约后的延迟处置等场景至关重要。

3.3.1 Hook 类型与执行顺序

Hook 名称 触发时机 典型用途
pre-install 在 Release 资源被创建之前 创建数据库、初始化配置、验证依赖
post-install 在 Release 所有资源创建成功后 数据填充、缓存预热、健康检查
pre-upgrade 在 Upgrade 操作执行之前 备份数据、暂停流量、DNS 预切换
post-upgrade 在 Upgrade 操作执行成功后 验证新版本、清理旧资源、更新 DNS 记录
pre-delete 在 Release 删除操作执行之前 优雅关闭、数据导出、通知下游
post-delete 在 Release 删除操作执行成功后 清理外部资源、发送告警

3.3.2 Hook 资源定义示例

以下是一个 pre-upgrade Hook,用于在升级前备份 MySQL 数据:

# templates/pre-upgrade-backup.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}-pre-upgrade-backup"
  annotations:
    "helm.sh/hook": pre-upgrade
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": before-hook-creation
spec:
  template:
    spec:
      restartPolicy: Never
      containers:
        - name: backup
          image: "{{ .Values.global.registry }}/mysql-backup:latest"
          env:
            - name: DB_HOST
              value: "{{ .Release.Name }}-mysql"
            - name: BACKUP_PATH
              value: "/backup/{{ .Release.Name }}-pre-upgrade.sql"
          command: ["/bin/sh", "-c", "mysqldump -h $DB_HOST -u root -p$DB_PASSWORD --all-databases > $BACKUP_PATH"]

3.3.3 Hook 权重与删除策略

  • 权重(hook-weight): 控制同一 Hook 类型下多个 Job 的执行顺序。权重越小,越先执行。默认权重为 0。
  • 删除策略(hook-delete-policy): 控制 Hook Job 在完成后是否自动删除。常用值:before-hook-creation(创建新 Hook 前删除旧 Job)、hook-succeeded(成功后删除)、hook-failed(失败后保留以便排查)。
SRE 场景:DNS 延迟处置中的 Hooks 应用
当检测到 SLO 违约(如 DNS 解析延迟 > 500ms)时,可通过 pre-upgrade Hook 执行 DNS 预切换脚本,将流量指向备用 DNS 服务器;post-upgrade Hook 验证新 DNS 记录的生效时间,确保延迟恢复到 SLO 阈值内。

3.4 依赖管理与 Hooks 的协同流程

下图展示了 Helm 在安装/升级过程中,依赖解析与 Hooks 的执行顺序:

Helm 依赖与 Hooks 协同执行流程 1. 依赖解析 Chart.yaml + Chart.lock 2. 条件过滤 enabled: true/false 3. Pre-Hooks pre-install / pre-upgrade 4. 渲染与安装 子 Chart 模板合并 5. Post-Hooks post-install / post-upgrade 全局值传递 • global.registry • global.environment • 所有子 Chart 共享 Hook 权重控制 • hook-weight: -5 • hook-delete-policy • 先执行权重小的 Job 总结:依赖解析 → 条件过滤 → Pre-Hooks → 渲染安装 → Post-Hooks 全局值贯穿整个流程,条件依赖控制子 Chart 开关,Hooks 提供生命周期干预点

3.5 常见陷阱与 SRE 建议

陷阱 现象 SRE 建议
子 Chart 版本未锁定 不同环境安装的版本不一致 始终提交 Chart.lock 到 Git,使用 helm dependency build
全局值命名冲突 子 Chart 意外覆盖全局值 使用 global. 前缀,避免与子 Chart 内部键名重复
Hook Job 残留 大量已完成 Job 占用集群资源 设置 hook-delete-policy: hook-succeeded,并配置 TTL 控制器
条件依赖未生效 子 Chart 始终被安装或跳过 检查 condition 路径是否与 values.yaml 层级一致,使用 helm template --debug 验证
Hook 执行超时 Release 安装/升级卡住 为 Hook Job 设置 activeDeadlineSeconds,并在 helm install 时使用 --timeout 参数
生产级配置示例: 在 SLO 违约后的 DNS 延迟处置场景中,建议在 pre-upgrade Hook 中执行 DNS 预切换(权重 -10),在 post-upgrade Hook 中执行 DNS 延迟验证(权重 +10),确保切换过程可观测、可回滚。