故障域隔离基础:定义故障域与拓扑分布策略
在 Kubernetes 集群升级与节点排空操作中,故障域(Failure Domain)是隔离风险的核心抽象。一个故障域代表一组共享单一故障点的资源集合——当该点失效时,域内所有节点或 Pod 将同时不可用。理解并正确配置故障域,是保证排空操作不导致全局服务中断的前提。
2.1 故障域的三层定义
生产集群通常按物理或逻辑维度将故障域划分为三个层级,从大到小依次为:可用区(Zone)、机架(Rack)、节点组(Node Group)。下表总结了各层级的典型故障范围与 Kubernetes 标签映射:
| 层级 | 故障范围 | Kubernetes 标签 | 排空影响 |
|---|---|---|---|
| 可用区(Zone) | 数据中心/可用区级电力、网络、制冷失效 | topology.kubernetes.io/zone |
整个可用区节点同时不可用,需跨区冗余 |
| 机架(Rack) | 机架级交换机、PDU 或 ToR 故障 | topology.kubernetes.io/rack(自定义) |
同一机架内节点批量排空时可能触发级联 |
| 节点组(Node Group) | 节点自身硬件、内核、kubelet 异常 | kubernetes.io/hostname |
单点排空,影响最小但需逐台验证 |
实践建议:在公有云环境中,可用区通常由云厂商直接提供(如 AWS
us-east-1a);自建机房需自行通过 nodeLabels 或 kubelet --node-labels 注入机架与节点组标签。排空策略应优先按可用区维度分批,再在区内按机架串行。
2.2 Kubernetes 拓扑分布策略
Kubernetes 原生提供 Pod Topology Spread Constraints(拓扑分布约束)来控制 Pod 在故障域间的分布。该策略通过 topologySpreadConstraints 字段定义,确保工作负载在升级排空期间仍能保持跨域冗余。
核心参数说明:
| 参数 | 含义 | 典型值 |
|---|---|---|
topologyKey |
指定故障域标签键 | topology.kubernetes.io/zone |
maxSkew |
允许的最大 Pod 分布不均衡度 | 1(严格均衡) |
whenUnsatisfiable |
不满足约束时的行为 | DoNotSchedule / ScheduleAnyway |
labelSelector |
匹配 Pod 的标签选择器 | app: my-service |
以下是一个典型的跨可用区分布配置示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 6
template:
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web-app
containers:
- name: nginx
image: nginx:1.25
排空关联:当排空某个可用区的节点时,
maxSkew: 1 会阻止调度器将新 Pod 集中到剩余可用区,从而避免单区过载。若 whenUnsatisfiable 设为 DoNotSchedule,排空期间可能产生 Pending Pod,需配合 PDB 容忍度使用。
2.3 PodAntiAffinity:硬性隔离与软性偏好
PodAntiAffinity 提供更细粒度的 Pod 间互斥规则,确保同一工作负载的多个副本不会调度到同一故障域内。它与拓扑分布策略的区别在于:AntiAffinity 是“排斥性”规则,而拓扑分布是“均衡性”约束。
两种模式对比:
| 模式 | requiredDuringSchedulingIgnoredDuringExecution | preferredDuringSchedulingIgnoredDuringExecution |
|---|---|---|
| 行为 | 硬性要求:不满足则 Pod 无法调度 | 软性偏好:尽量满足,不满足也可调度 |
| 适用场景 | 关键服务(etcd、API Server) | 普通无状态服务 |
| 排空风险 | 排空时可能导致 Pod 无法重调度 | 排空时调度器会尝试避开同一域 |
硬性 AntiAffinity 配置示例:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-app
topologyKey: topology.kubernetes.io/zone
排空陷阱:如果集群只有 2 个可用区,且使用
requiredDuringScheduling 配合 replicas: 3,排空一个可用区时剩余可用区无法容纳所有副本,Pod 将一直处于 Pending 状态。此时必须配合 PDB 允许部分副本不可用,或改用 preferredDuringScheduling。
2.4 故障域隔离与排空参数调优的关系
节点排空参数 --force、--grace-period、--timeout 的取值,必须与故障域隔离策略联动。下图展示了故障域定义如何影响排空参数决策:
2.5 故障域标签注入与验证
确保节点带有正确的故障域标签是后续所有策略生效的基础。以下命令用于验证和注入标签:
# 查看节点现有标签
kubectl get nodes --show-labels
# 为节点注入可用区标签(自建机房示例)
kubectl label node worker-1 topology.kubernetes.io/zone=zone-a
# 为节点注入机架标签
kubectl label node worker-1 topology.kubernetes.io/rack=rack-01
# 批量验证所有节点的故障域标签完整性
kubectl get nodes -o custom-columns=NAME:.metadata.name,ZONE:.metadata.labels.topology\\.kubernetes\\.io/zone,RACK:.metadata.labels.topology\\.kubernetes\\.io/rack
自动化建议:在集群初始化阶段,通过
kubelet --node-labels 或 Karpenter/Cluster Autoscaler 的标签模板自动注入故障域标签,避免人工遗漏。排空前应运行标签完整性检查脚本,确保所有节点已正确标记。
2.6 本章小结
- 故障域三层模型:可用区(Zone)→ 机架(Rack)→ 节点组(Node Group),每层对应不同的故障范围和排空策略。
- 拓扑分布约束:通过
topologySpreadConstraints实现跨域 Pod 均衡,maxSkew: 1是排空场景的推荐起始值。 - PodAntiAffinity:提供硬性/软性互斥,
requiredDuringScheduling在排空时需配合 PDB 避免死锁。 - 参数联动:故障域粒度决定
--timeout和--grace-period的基准值,隔离策略越严格,排空参数越需保守。