2. Helm Values 核心机制:Values 文件结构、全局变量与局部变量、层级覆盖规则
精细化故障域隔离的落地,首先依赖于对 Helm Values 体系的深刻理解。Values 并非简单的键值对集合,而是一套具备层级、作用域和覆盖规则的声明式配置系统。掌握其核心机制,是后续实现多环境、多集群、多故障域隔离的基石。
2.1 Values 文件结构与命名约定
Helm Chart 的标准目录结构中,Values 文件位于 Chart 根目录,通常包含以下关键文件:
| 文件 | 作用域 | 覆盖优先级 | 典型用途 |
|---|---|---|---|
values.yaml |
Chart 默认值 | 最低(基准) | 定义所有可配置参数的默认值,作为 Chart 的“契约” |
values.schema.json |
全局校验 | 安装时校验 | 对 values.yaml 中的参数进行类型、范围、必填项校验 |
charts/ 内子 Chart 的 values.yaml |
子 Chart 局部 | 子 Chart 内部默认 | 子 Chart 自身维护的默认配置,与父 Chart 隔离 |
在故障域隔离场景中,我们通常不会直接修改 values.yaml,而是通过外部覆盖文件(如 values-az1.yaml、values-region-b.yaml)来注入特定故障域的差异化配置。这种文件结构天然支持配置的“基线 + 增量”模式。
values.yaml 视为“不可变契约”,所有环境差异通过 -f 参数传入的外部文件实现。这能确保 Chart 的通用性,避免因修改默认值导致 Chart 在不同故障域间行为不一致。
2.2 全局变量(global)与局部变量
Helm 通过 global 关键字实现跨 Chart 的变量共享。理解全局与局部的作用域边界,是避免配置冲突的关键。
- 局部变量(Local Values): 定义在
values.yaml或外部覆盖文件的顶层键下,仅对当前 Chart 及其直接模板可见。子 Chart 无法直接访问父 Chart 的局部变量。 - 全局变量(Global Values): 定义在
global键下,会被递归传递给所有子 Chart。子 Chart 可以通过.Values.global访问父 Chart 设置的全局变量。
以下是一个典型的全局变量定义示例:
# 父 Chart values.yaml
global:
region: "cn-north-1"
faultDomain: "az-a"
clusterName: "prod-cluster-1"
commonLabels:
environment: "production"
team: "platform"
# 子 Chart 局部变量(子 Chart 自己的 values.yaml)
service:
port: 8080
replicas: 3
在故障域隔离中,global 最适合承载“跨所有子 Chart 共享的故障域标识”,例如区域名称、可用区 ID、集群名称等。而每个子 Chart 的局部变量则用于定义该组件在特定故障域下的差异化行为,如副本数、资源限制、存储类等。
global 变量。Helm 的全局变量覆盖规则是:子 Chart 无法通过自己的 values.yaml 覆盖父 Chart 传入的 global 值。如果子 Chart 定义了同名的 global 键,父 Chart 的全局值会优先。这可能导致子 Chart 的“意图”被静默忽略。
2.3 Values 的层级覆盖规则
Helm 的 Values 覆盖遵循严格的优先级顺序,理解这一规则是进行精细化配置管理的前提。覆盖优先级从低到高排列如下:
- Chart 内置的
values.yaml—— 最低优先级,作为所有配置的默认基线。 - 父 Chart 的
values.yaml—— 父 Chart 可以为子 Chart 提供默认值,通过子 Chart 名称作为键传递。 - 子 Chart 内置的
values.yaml—— 子 Chart 自身的默认值,优先级高于父 Chart 提供的默认值。 - 通过
-f指定的外部 YAML 文件 —— 按文件顺序依次覆盖,后指定的文件优先级更高。 - 通过
--set指定的命令行参数 —— 最高优先级,直接覆盖所有文件中的同名配置。
以下 SVG 图展示了 Helm Values 的完整覆盖链路:
2.4 父 Chart 与子 Chart 的 Values 传递机制
当父 Chart 包含子 Chart 时,Values 的传递遵循“显式传递”原则。父 Chart 可以通过两种方式为子 Chart 提供配置:
- 隐式传递(通过子 Chart 名称键): 父 Chart 的
values.yaml中,如果存在与子 Chart 名称同名的顶级键,Helm 会自动将该键下的内容传递给子 Chart。例如,子 Chart 名为mysql,父 Chart 中定义mysql: { replicaCount: 3 },则子 Chart 的.Values.replicaCount会被覆盖为 3。 - 显式传递(通过
templates/中的include或template): 父 Chart 可以在模板中通过{{ include "子Chart名称.values" . }}的方式显式传递 Values 上下文。这种方式更灵活,但需要手动管理。
以下是一个父 Chart 为子 Chart 传递故障域配置的示例:
# 父 Chart values.yaml
global:
region: "us-east-1"
faultDomain: "az-b"
# 为名为 "nginx" 的子 Chart 传递局部配置
nginx:
replicaCount: 5
resources:
requests:
memory: "512Mi"
cpu: "500m"
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: "topology.kubernetes.io/zone"
operator: In
values:
- "us-east-1b"
# 为名为 "redis" 的子 Chart 传递局部配置
redis:
replicaCount: 3
persistence:
storageClass: "gp3-encrypted"
size: "100Gi"
在这个例子中,nginx 和 redis 子 Chart 会分别接收到父 Chart 为它们定义的局部配置,同时共享 global 中的区域和故障域信息。这种机制使得我们可以在父 Chart 层面统一管理故障域策略,而子 Chart 只需关注自身组件的差异化配置。
global 中,将“故障域内组件的差异化行为”(如副本数、资源规格、存储配置)放在子 Chart 的局部键下。这样既能实现全局统一标识,又能保持每个组件的独立可配置性。
2.5 覆盖规则在故障域隔离中的实战映射
将上述覆盖规则映射到故障域隔离场景,可以总结为以下配置策略:
| 配置层级 | 故障域隔离用途 | 示例 |
|---|---|---|
values.yaml(Chart 默认) |
定义跨所有故障域的通用基线,如镜像版本、日志级别 | image.tag: "v1.0.0" |
global(父 Chart) |
传递故障域标识,如 region、zone、cluster 名称 | global.zone: "az-a" |
| 子 Chart 名称键(父 Chart) | 为特定组件注入故障域差异化配置 | nginx.replicaCount: 5 |
-f values-az-a.yaml |
按故障域加载外部覆盖文件,实现环境隔离 | helm install -f values-az-a.yaml |
--set |
临时覆盖,用于调试或紧急变更 | --set global.zone=az-b |
通过这种层级化的覆盖规则,我们可以实现“一次 Chart 定义,多故障域差异化部署”的目标,而无需为每个故障域维护独立的 Chart 副本。这正是 Helm Values 管理在精细化故障域隔离中的核心价值所在。