4、故障域定义:节点故障域、可用区故障域、集群故障域

在多租户 Deployment 的滚动更新场景中,故障域(Failure Domain)是决定更新中断范围与租户恢复能力的基础边界。不同的故障域粒度决定了 Pod 在发生节点宕机、可用区断电或集群级灾难时的容错上限。本节从节点、可用区、集群三个层次定义故障域,并分析其对多租户滚动更新的影响。

4.1 故障域层次模型

Kubernetes 原生支持将节点按拓扑键(topology.kubernetes.io/zone、kubernetes.io/hostname)划分为不同故障域。在多租户架构中,每个租户的 Pod 副本应尽量分布在多个故障域内,以降低单点故障导致的批量中断风险。下表对比了三种故障域的核心特征:

故障域类型 粒度 典型故障场景 Pod 分布策略 滚动更新影响范围
节点故障域 单台物理机/虚拟机 硬件故障、内核崩溃、网络中断 PodAntiAffinity + hostname 单个节点上的租户 Pod 同时中断
可用区故障域 数据中心内独立电力/网络单元 机架断电、交换机故障、制冷失效 PodTopologySpread + zone 整个可用区内的租户 Pod 批量中断
集群故障域 整个 Kubernetes 集群 控制面崩溃、etcd 数据损坏、版本升级失败 多集群联邦 + 跨集群调度 所有租户全部中断,需集群级恢复
设计原则:租户的 Pod 副本数应至少大于最大故障域内可容忍的副本损失数。例如,若每个可用区最多容忍 1 个副本丢失,则租户副本数应 ≥ 可用区数 + 1。

4.2 节点故障域(Node Failure Domain)

节点故障域是最小粒度的故障隔离单元。在滚动更新中,如果 Deployment 的 maxSurge 和 maxUnavailable 设置不当,同一租户的多个 Pod 可能被调度到同一节点,导致该节点故障时租户服务容量骤降。

关键配置:

  • 使用 podAntiAffinity 的 requiredDuringSchedulingIgnoredDuringExecution 规则,强制同一租户的 Pod 分布在不同节点。
  • 结合 topologyKey: kubernetes.io/hostname 实现节点级分散。
  • 滚动更新时,maxUnavailable 应 ≤ 1,避免节点故障域内同时销毁多个租户 Pod。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tenant-app
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - tenant-app
            topologyKey: kubernetes.io/hostname

4.3 可用区故障域(Zone Failure Domain)

可用区故障域对应云厂商或自建数据中心内的独立故障隔离区域。当滚动更新触发 Pod 重建时,如果所有新 Pod 被调度到同一个可用区,该可用区一旦故障,租户将完全不可用。

关键配置:

  • 使用 PodTopologySpread 约束,按 topology.kubernetes.io/zone 实现可用区级均匀分布。
  • 设置 maxSkew: 1 确保任意两个可用区之间的 Pod 数量差不超过 1。
  • 滚动更新期间,maxSurge 应小于等于可用区数,避免新 Pod 集中在少数可用区。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tenant-app
spec:
  replicas: 6
  template:
    spec:
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: topology.kubernetes.io/zone
        whenUnsatisfiable: DoNotSchedule
        labelSelector:
          matchLabels:
            app: tenant-app
常见陷阱:仅设置 PodTopologySpread 而不配合 PodAntiAffinity,可能导致同一可用区内多个 Pod 仍被调度到同一节点,形成节点级单点故障。建议两层约束叠加使用。

4.4 集群故障域(Cluster Failure Domain)

集群故障域是最粗粒度的故障边界。当整个集群因控制面故障、etcd 数据损坏或版本升级失败而不可用时,所有租户的 Deployment 滚动更新将完全中断。集群故障域的恢复通常依赖多集群联邦或备份集群的切换。

关键策略:

  • 使用 Cluster Federation(KubeFed) 将 Deployment 分发到多个集群,每个集群视为一个故障域。
  • 配置 跨集群 Pod 分布策略,确保每个租户的副本在至少 2 个集群中有运行实例。
  • 滚动更新时,采用 金丝雀发布 策略,先在一个集群中更新,验证通过后再推广到其他集群。
apiVersion: types.kubefed.io/v1beta1
kind: FederatedDeployment
metadata:
  name: tenant-app
spec:
  template:
    spec:
      replicas: 6
  placement:
    clusters:
    - name: cluster-a
    - name: cluster-b
  overrides:
  - clusterName: cluster-a
    clusterOverrides:
    - path: "/spec/replicas"
      value: 3
  - clusterName: cluster-b
    clusterOverrides:
    - path: "/spec/replicas"
      value: 3

4.5 故障域与滚动更新中断的关系

下图展示了三种故障域在滚动更新过程中对租户 Pod 中断范围的影响:

故障域层次与滚动更新中断范围 故障域层次与滚动更新中断范围 节点故障域 粒度:单台节点 中断范围:1 个节点 租户影响:1~N 个 Pod 恢复方式:节点自愈/驱逐 可用区故障域 粒度:独立可用区 中断范围:整个可用区 租户影响:批量 Pod 中断 恢复方式:跨区重新调度 集群故障域 粒度:整个集群 中断范围:全部租户 租户影响:完全不可用 恢复方式:集群切换/重建 说明: 故障域粒度越细,滚动更新中断范围越小,恢复速度越快。多租户场景应优先保证节点级和可用区级分散。 集群故障域需要多集群架构支持,适用于对可用性要求极高的关键租户。 故障域选择建议 • 节点故障域:适用于所有租户,作为基础容错层,必须配置 PodAntiAffinity。 • 可用区故障域:适用于跨可用区部署的租户,结合 PodTopologySpread 实现均匀分布。 • 集群故障域:适用于关键业务租户,需要多集群联邦或备份集群,成本较高。 • 滚动更新时,应逐级验证:先节点级、再可用区级、最后集群级,避免跨域中断扩散。

4.6 故障域配置清单

在 Deployment 多租户环境中,建议按以下清单检查故障域配置的完整性:

检查项 节点故障域 可用区故障域 集群故障域
PodAntiAffinity ✅ 必须配置 ✅ 建议配置 ❌ 不适用
PodTopologySpread ❌ 不适用 ✅ 必须配置 ❌ 不适用
maxUnavailable ≤ 1 ≤ 可用区数 - 1 ≤ 集群数 - 1
maxSurge ≤ 节点数 - 1 ≤ 可用区数 ≤ 集群数
恢复时间目标(RTO) < 5 分钟 < 15 分钟 < 30 分钟
恢复点目标(RPO) 0(无数据丢失) 0(无数据丢失) < 5 分钟
核心结论:故障域定义是滚动更新中断隔离的基础。节点故障域保证单点故障不扩散,可用区故障域保证区域故障不全局化,集群故障域保证灾难场景有逃生通道。多租户 Deployment 应至少覆盖前两层,关键租户需覆盖全部三层。