4、故障域隔离原理:节点故障域、可用区(AZ)、Pod反亲和性、TopologySpreadConstraints

在云原生环境中,故障域(Failure Domain)是指一组共享单一故障点的资源集合。当该故障点(如电源、网络交换机、机架或数据中心)失效时,域内所有资源将同时不可用。Helm 应用交付的故障域隔离演练,核心目标就是验证工作负载是否被正确分散到多个独立的故障域中,从而保证单一故障不会导致整个服务中断。

本章深入剖析 Kubernetes 集群中四个层次的故障域隔离机制:节点故障域、可用区(AZ)、Pod 反亲和性以及 TopologySpreadConstraints。理解这些原理是设计自动化测试断言的基础。

4.1 节点故障域与可用区(AZ)

节点故障域是最基础的物理或逻辑隔离单元。在云平台中,通常表现为可用区(Availability Zone, AZ)。每个 AZ 拥有独立的电力、冷却和网络设施,AZ 之间通过低延迟光纤互联。

故障域层级 典型范围 故障影响面 Kubernetes 标签
节点(Node) 单台物理机/虚拟机 该节点上的所有 Pod kubernetes.io/hostname
机架(Rack) 同一机架内的多台节点 机架级电源/网络故障 topology.kubernetes.io/zone(部分实现)
可用区(AZ) 数据中心独立区域 AZ 级灾难(断电、火灾) topology.kubernetes.io/zone
地域(Region) 跨 AZ 的地理区域 区域性自然灾害 topology.kubernetes.io/region
演练要点:自动化测试框架应首先验证集群节点是否分布在至少 2 个 AZ 上。如果集群是单 AZ 部署,则节点故障域隔离的测试用例应直接标记为 SKIP 或 WARNING,因为物理上无法实现 AZ 级隔离。

4.2 Pod 反亲和性(Pod Anti-Affinity)

Pod 反亲和性是一种调度约束,用于强制或偏好将同一应用的多个副本调度到不同的故障域中。它分为两种类型:

  • requiredDuringSchedulingIgnoredDuringExecution(硬约束):调度器必须满足该规则,否则 Pod 无法被调度。
  • preferredDuringSchedulingIgnoredDuringExecution(软约束):调度器尽量满足该规则,但不强制。

反亲和性可以基于 topologyKey 定义故障域粒度:

affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchLabels:
          app: my-app
      topologyKey: topology.kubernetes.io/zone    # 按 AZ 分散
    - labelSelector:
        matchLabels:
          app: my-app
      topologyKey: kubernetes.io/hostname         # 按节点分散
常见陷阱:如果只配置了 kubernetes.io/hostname 的反亲和性,当集群节点分布在多个 AZ 时,Pod 可能被调度到同一 AZ 的不同节点上。这无法防御 AZ 级故障。自动化测试必须检查 topologyKey 是否包含了 AZ 级别的键。

4.3 TopologySpreadConstraints(拓扑分布约束)

TopologySpreadConstraints 是 Kubernetes 1.19+ 引入的更灵活的调度策略,它允许用户定义 Pod 在多个拓扑域中的均匀分布或最大倾斜度。相比 Pod 反亲和性,它更适合控制大规模副本的分布。

topologySpreadConstraints:
- maxSkew: 1
  topologyKey: topology.kubernetes.io/zone
  whenUnsatisfiable: DoNotSchedule
  labelSelector:
    matchLabels:
      app: my-app
- maxSkew: 2
  topologyKey: kubernetes.io/hostname
  whenUnsatisfiable: ScheduleAnyway
参数 含义 典型值
maxSkew 允许的最大 Pod 数量差异 1(严格均匀)或 2(允许少量倾斜)
topologyKey 拓扑域标签键 topology.kubernetes.io/zone
whenUnsatisfiable 不满足约束时的行为 DoNotSchedule(硬)或 ScheduleAnyway(软)
labelSelector 匹配哪些 Pod 参与分布计算 matchLabels: { app: my-app }
自动化测试断言逻辑:对于每个 Deployment/StatefulSet,测试框架应:
  1. 获取所有 Pod 的 topology.kubernetes.io/zone 标签值。
  2. 统计每个 AZ 中的 Pod 数量。
  3. 计算最大 Pod 数与最小 Pod 数的差值(即 skew)。
  4. 断言 skew ≤ 配置的 maxSkew 值。
故障域隔离层次与调度策略关系图 Region(地域) topology.kubernetes.io/region 可用区 A(AZ-1) topology.kubernetes.io/zone: az-1 可用区 B(AZ-2) topology.kubernetes.io/zone: az-2 Node-1 hostname: node-1 Node-2 hostname: node-2 Node-3 hostname: node-3 Node-4 hostname: node-4 Pod-A1 Pod-A2 Pod-B1 Pod-B2 调度策略作用域 Pod 反亲和性 + TopologySpreadConstraints 控制 Pod 在 Node / AZ / Region 之间的分布

4.4 三种调度策略的对比与选择

在 Helm Chart 的 values.yaml 中,应用开发者需要根据服务特性选择合适的隔离策略。下表总结了三种策略的适用场景:

策略 粒度控制 硬/软约束 适用场景 对副本数的要求
PodAntiAffinity(required) 按 topologyKey 严格分散 硬 有状态服务、数据库、关键中间件 副本数 ≤ 拓扑域数量
PodAntiAffinity(preferred) 按 topologyKey 尽量分散 软 无状态服务、可容忍少量聚集 无严格限制
TopologySpreadConstraints 按 maxSkew 控制均匀度 硬/软均可 大规模微服务、需要精确控制分布偏差 副本数可远大于拓扑域数量
自动化测试关键检查点:
  • 如果使用 requiredDuringScheduling 反亲和性,测试框架应验证集群拓扑域数量是否 ≥ 应用副本数。否则必然有 Pod 处于 Pending 状态。
  • 如果使用 TopologySpreadConstraints 且 whenUnsatisfiable: DoNotSchedule,同样需要检查拓扑域容量。
  • 对于 StatefulSet,除了调度约束,还需检查 Pod 的 topology.kubernetes.io/zone 标签是否与 PVC 的 allowedTopologies 一致,确保数据面也实现了 AZ 隔离。
Pod 分布对比:无隔离 vs 有隔离 ❌ 无故障域隔离 可用区 AZ-1 Pod-1 Pod-2 Pod-3 可用区 AZ-2 (无 Pod 部署) ✅ 启用故障域隔离 可用区 AZ-1 Pod-1 Pod-2 可用区 AZ-2 Pod-3 AZ-1 故障 → 3 个 Pod 全部丢失 AZ-1 故障 → 仅丢失 2 个 Pod,服务降级不中断

4.5 自动化测试断言设计原则

基于上述原理,Helm 应用交付故障域隔离演练的自动化测试框架应包含以下核心断言:

  1. 拓扑域存在性检查:集群中至少存在 2 个不同的 topology.kubernetes.io/zone 值。
  2. 调度策略存在性检查:目标 Deployment/StatefulSet 的 PodTemplate 中必须包含 podAntiAffinity 或 topologySpreadConstraints 配置。
  3. topologyKey 覆盖检查:配置的 topologyKey 必须包含 AZ 级别的键(topology.kubernetes.io/zone),仅包含 kubernetes.io/hostname 不足以防御 AZ 故障。
  4. 分布均匀性检查:对于 TopologySpreadConstraints,实际 Pod 分布的 maxSkew 必须 ≤ 配置值。
  5. 容量适配检查:如果使用硬约束,副本数必须 ≤ 可用拓扑域数量。
Helm Chart 最佳实践:建议在 Chart 的 values.yaml 中提供 topologySpreadConstraints 的默认配置,并允许用户通过 global.availabilityZones 参数声明集群的 AZ 数量。自动化测试框架可以读取该参数,动态调整断言阈值。