1. 故障域概念:什么是故障域(Failure Domain),K8s 中故障域的层级
故障域(Failure Domain)是分布式系统与云原生架构中的核心概念,它定义了一组共享同一故障风险边界的资源集合。当该边界内的基础设施(如电源、网络交换机、制冷系统或物理服务器)发生故障时,集合内的所有组件会同时受到影响。在 Kubernetes 中,理解故障域是进行高可用部署、资源调度优化以及故障隔离的前提。
1.1 故障域的本质
故障域的本质是故障隔离边界。一个故障域内的资源具有相同的单点故障风险;跨故障域的资源则具备故障独立性。Kubernetes 调度器利用这一特性,将工作负载副本(Pod)分散到不同的故障域中,从而保证即使某个域整体失效,应用仍能通过其他域中的副本继续提供服务。
1.2 Kubernetes 中的故障域层级
Kubernetes 通过节点标签(Label)和拓扑分布约束(Topology Spread Constraints)来定义和利用故障域。从物理与逻辑维度,故障域通常划分为以下四个层级:
| 层级 | K8s 标签示例 | 故障范围 | 典型故障场景 |
|---|---|---|---|
| 节点(Node) | kubernetes.io/hostname |
单台物理机或虚拟机 | 操作系统崩溃、磁盘损坏、内核 Panic、网卡故障 |
| 机架(Rack) | topology.kubernetes.io/rack |
同一机架内的所有节点 | 机架交换机故障、电源分配单元(PDU)断电、上联链路中断 |
| 可用区(Zone) | topology.kubernetes.io/zone |
同一数据中心内独立的故障隔离区域 | 可用区级电力中断、制冷失效、网络汇聚层故障 |
| 区域(Region) | topology.kubernetes.io/region |
跨数据中心的完整地理区域 | 自然灾害、大规模电力故障、骨干网络中断 |
1.3 故障域层级关系与可视化
下图展示了 Kubernetes 集群中从区域到节点的完整故障域层级结构,以及各层级之间的包含关系。每个层级代表一个独立的故障边界,Pod 副本应尽可能分布在不同层级的故障域中。
1.4 各层级故障域详解
1.4.1 节点级故障域
节点是 Kubernetes 中最小的故障域单元。每个节点对应一个 kubernetes.io/hostname 标签,该标签在集群内唯一标识一台物理机或虚拟机。节点级故障包括:
- 硬件故障:CPU/内存/磁盘损坏、电源模块失效
- 软件故障:操作系统 OOM、内核死锁、kubelet 异常退出
- 网络故障:节点网卡故障、IP 地址冲突
1.4.2 机架级故障域
机架级故障域通过自定义标签 topology.kubernetes.io/rack 标识。同一机架内的节点共享机架交换机(ToR)、电源分配单元(PDU)和物理布线。典型故障场景:
- 机架交换机断电或端口批量故障
- PDU 跳闸导致整机架掉电
- 机架内网线批量损坏
1.4.3 可用区级故障域
可用区(Zone)是云提供商或自建数据中心内独立的故障隔离区域,通过 topology.kubernetes.io/zone 标签标识。每个可用区拥有独立的电力供应、网络汇聚层和制冷系统。可用区之间通常通过高带宽光纤互联,但延迟和带宽存在上限。
1.4.4 区域级故障域
区域(Region)是最高层级的故障域,通过 topology.kubernetes.io/region 标签标识。区域由多个可用区组成,地理上相隔数百公里。区域级故障极为罕见,但一旦发生影响范围最大。
1.5 故障域在 kubectl debug 中的意义
当使用 kubectl debug 诊断资源冲突时,故障域信息帮助工程师快速定位:
- 调度失败:Pod 是否因拓扑分布约束无法找到满足故障域分散要求的节点
- 资源争抢:同一故障域内的节点是否因共享网络/存储资源导致性能瓶颈
- 级联故障:某个故障域失效后,流量是否被正确转移到其他域,以及是否引发新的资源冲突
1.6 故障域配置示例
以下 YAML 展示了如何通过 topologySpreadConstraints 让 Deployment 的副本跨可用区和节点分散:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 6
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web
containers:
- name: nginx
image: nginx:1.25
上述配置确保:
- 每个可用区最多比最少多运行 1 个 Pod(
maxSkew: 1) - 每个节点最多运行 1 个 Pod
- 当无法满足约束时,Pod 不会被调度(
DoNotSchedule)