3. 调度亲和性原理:节点亲和性、Pod间亲和性与反亲和性

在 Kubernetes 集群中,调度器(kube-scheduler)负责将 Pod 分配到合适的节点。亲和性与反亲和性规则提供了比简单 nodeSelector 更灵活、更强大的调度控制能力。本章深入解析三种核心调度约束的 YAML 配置语义与运行机制,为后续治理集群故障排查与配置漂移审计奠定基础。

3.1 节点亲和性(nodeAffinity)

节点亲和性允许 Pod 根据节点上的标签(Label)选择目标节点,分为硬性要求(requiredDuringSchedulingIgnoredDuringExecution)和软性偏好(preferredDuringSchedulingIgnoredDuringExecution)两种策略。

策略类型 语义 调度行为 执行阶段
required 必须满足 找不到匹配节点则 Pod 处于 Pending 调度时
preferred 尽量满足 不满足时仍可调度到其他节点,权重影响优先级 调度时
关键字段解析:
  • matchExpressions:支持 In、NotIn、Exists、DoesNotExist、Gt、Lt 操作符。
  • weight(仅 preferred):1–100 整数,权重越高优先级越大。
  • topologyKey:用于 podAffinity/podAntiAffinity,定义拓扑域。
apiVersion: v1
kind: Pod
metadata:
  name: node-affinity-demo
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disk-type
            operator: In
            values:
            - ssd
            - nvme
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: zone
            operator: In
            values:
            - az-a
运维提示:required 规则写错会导致 Pod 永久 Pending,排查时优先检查节点标签是否存在、值是否匹配。preferred 规则即使写错也不会阻塞调度,但可能造成负载不均。

3.2 Pod间亲和性(podAffinity)

Pod 间亲和性将一组 Pod 调度到相同的拓扑域(如同一个节点、同一个可用区),常用于降低网络延迟或满足数据本地性需求。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: cache-affinity
spec:
  replicas: 3
  selector:
    matchLabels:
      app: cache
  template:
    metadata:
      labels:
        app: cache
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - frontend
            topologyKey: kubernetes.io/hostname
      containers:
      - name: cache
        image: redis:7
参数 说明 常见值
labelSelector 选择目标 Pod 的标签 matchLabels / matchExpressions
topologyKey 定义“相同位置”的粒度 kubernetes.io/hostname、topology.kubernetes.io/zone
namespaces 限定标签选择的范围(默认当前 ns) default、kube-system
配置漂移风险:podAffinity 的 topologyKey 一旦写错(如误用 kubernetes.io/hostname 代替 topology.kubernetes.io/zone),会导致 Pod 全部挤在同一节点,造成单点故障。审计时应重点核对 topologyKey 与业务容灾要求是否一致。

3.3 Pod间反亲和性(podAntiAffinity)

反亲和性强制或偏好 Pod 分散到不同拓扑域,是高可用部署的核心手段。典型场景:将同一 Deployment 的多个副本分布在不同节点或可用区。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-ha
spec:
  replicas: 5
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - web
              topologyKey: kubernetes.io/hostname
      containers:
      - name: nginx
        image: nginx:1.25
required vs preferred 选择指南:
  • required:副本数 ≤ 可用节点数时使用,保证分散;节点数不足时 Pod 会 Pending。
  • preferred:副本数可能超过节点数时使用,尽量分散但不阻塞调度。

3.4 三种亲和性对比与审计要点

特性 nodeAffinity podAffinity podAntiAffinity
作用对象 节点标签 Pod 标签 Pod 标签
调度目标 绑定到特定节点 与目标 Pod 同拓扑域 与目标 Pod 不同拓扑域
典型用途 GPU 节点、SSD 节点 缓存与前端同节点 多副本跨节点/跨可用区
配置漂移常见点 标签 key 拼写错误、values 遗漏 topologyKey 粒度错误 required 导致调度死锁

3.5 调度亲和性决策流程(SVG)

调度亲和性决策流程 Pod 创建请求 节点亲和性 (nodeAffinity) required 硬约束 → 必须匹配节点标签 Pod 间亲和性 (podAffinity) 与目标 Pod 同拓扑域 Pod 反亲和性 (podAntiAffinity) 与目标 Pod 不同拓扑域 全部满足? 否 是 Pod Pending Pod 调度成功 审计重点:检查 required 规则是否导致调度死锁,preferred 权重是否合理

3.6 配置漂移审计清单

  1. 标签一致性检查:nodeAffinity 引用的节点标签是否真实存在?Pod 标签是否与 podAffinity 的 labelSelector 匹配?
  2. topologyKey 合理性:是否使用了正确的拓扑域?生产环境建议使用 topology.kubernetes.io/zone 而非 kubernetes.io/hostname 实现可用区级容灾。
  3. required 规则数量:过多 required 规则会大幅缩小可调度节点池,建议每个 Pod 不超过 2 条 required 规则。
  4. preferred 权重分布:权重值是否集中在少数规则上?避免权重差异过大导致调度倾斜。
  5. 反亲和性副本数:required podAntiAffinity 的副本数是否超过目标拓扑域数量?超过会导致部分副本 Pending。
Helm 治理实践:在 Helm Chart 的 values.yaml 中暴露亲和性配置项,通过模板条件渲染 required/preferred,避免硬编码。审计时对比 values 与渲染后的 YAML,快速定位配置漂移。