故障域隔离基础:定义故障域与拓扑分布策略

在 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 的取值,必须与故障域隔离策略联动。下图展示了故障域定义如何影响排空参数决策:

故障域隔离与排空参数调优关系图 故障域隔离 → 排空参数调优决策流 可用区 (Zone) 机架 (Rack) 节点组 (Node Group) 拓扑分布约束 PodAntiAffinity PDB 容忍度 --timeout 延长 --grace-period 调整 --force 谨慎使用 排空操作安全性与服务可用性平衡 说明:故障域粒度越粗(如可用区),排空超时时间应越长;AntiAffinity 越严格,越需要配合 PDB 放宽不可用副本数。

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 的基准值,隔离策略越严格,排空参数越需保守。