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 副本应尽可能分布在不同层级的故障域中。

Kubernetes 故障域层级结构图 Kubernetes 故障域层级结构 区域(Region) 例:华北、华东、美西 可用区 A(Zone A) 独立电力/网络/制冷 可用区 B(Zone B) 独立电力/网络/制冷 机架 R1 交换机+PDU 机架 R2 交换机+PDU 机架 R3 交换机+PDU 机架 R4 交换机+PDU Node-1 hostname Node-2 hostname Node-3 hostname Node-4 hostname Pod-A1 Pod-A2 Pod-B1 Pod-B2 Pod 副本跨可用区、跨机架、跨节点分布 任一故障域失效,其他域中的副本仍可提供服务

1.4 各层级故障域详解

1.4.1 节点级故障域

节点是 Kubernetes 中最小的故障域单元。每个节点对应一个 kubernetes.io/hostname 标签,该标签在集群内唯一标识一台物理机或虚拟机。节点级故障包括:

  • 硬件故障:CPU/内存/磁盘损坏、电源模块失效
  • 软件故障:操作系统 OOM、内核死锁、kubelet 异常退出
  • 网络故障:节点网卡故障、IP 地址冲突

1.4.2 机架级故障域

机架级故障域通过自定义标签 topology.kubernetes.io/rack 标识。同一机架内的节点共享机架交换机(ToR)、电源分配单元(PDU)和物理布线。典型故障场景:

  • 机架交换机断电或端口批量故障
  • PDU 跳闸导致整机架掉电
  • 机架内网线批量损坏
生产建议: 在物理机部署场景中,务必为每个节点打上机架标签。即使使用虚拟机,也应通过 hypervisor 的物理位置信息映射机架拓扑,避免调度器将同一应用的多个副本放在同一机架。

1.4.3 可用区级故障域

可用区(Zone)是云提供商或自建数据中心内独立的故障隔离区域,通过 topology.kubernetes.io/zone 标签标识。每个可用区拥有独立的电力供应、网络汇聚层和制冷系统。可用区之间通常通过高带宽光纤互联,但延迟和带宽存在上限。

1.4.4 区域级故障域

区域(Region)是最高层级的故障域,通过 topology.kubernetes.io/region 标签标识。区域由多个可用区组成,地理上相隔数百公里。区域级故障极为罕见,但一旦发生影响范围最大。

1.5 故障域在 kubectl debug 中的意义

当使用 kubectl debug 诊断资源冲突时,故障域信息帮助工程师快速定位:

  • 调度失败:Pod 是否因拓扑分布约束无法找到满足故障域分散要求的节点
  • 资源争抢:同一故障域内的节点是否因共享网络/存储资源导致性能瓶颈
  • 级联故障:某个故障域失效后,流量是否被正确转移到其他域,以及是否引发新的资源冲突
常见误区: 仅依赖节点级故障域(hostname)进行 Pod 分散,而忽略机架和可用区层级。这会导致在机架交换机故障时,虽然节点分布在不同的 hostname 上,但所有节点仍同时失联,造成应用完全不可用。

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)