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