Hotdry.
systems-engineering

Kubernetes Pod 调度:亲和性规则、污点容忍与拓扑感知卷绑定

通过亲和性规则、污点/容忍机制及拓扑分布约束,实现Pod在多节点间的均衡调度与高效卷绑定,提升资源利用率。

在 Kubernetes 多节点集群中,Pod 调度直接影响资源利用率、故障恢复和高可用性。默认调度器基于资源匹配进行简单分配,但生产环境需精细控制。通过节点亲和性(Node Affinity)、Pod 亲和性 / 反亲和性(Pod Affinity/Anti-Affinity)、污点与容忍(Taints & Tolerations)以及 Pod 拓扑分布约束(Topology Spread Constraints),结合拓扑感知卷绑定(Topology-Aware Volume Binding),可实现高效的多节点资源分配,避免热点、提升本地性和均匀分布。

节点亲和性与 Pod 亲和性规则

节点亲和性是 nodeSelector 的升级版,支持硬约束(requiredDuringSchedulingIgnoredDuringExecution)和软约束(preferredDuringSchedulingIgnoredDuringExecution)。硬约束要求 Pod 必须调度到匹配标签的节点,否则 Pending;软约束优先匹配,并通过 weight(1-100)加权评分。

例如,优先调度到 us-east-1a 可用区的 GPU 节点:

spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values: ["us-east-1a"]
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: node-type
            operator: In
            values: ["gpu"]

Pod 亲和性控制 Pod 间共置:podAffinity 吸引同类 Pod 到同一拓扑域(如 hostname 或 zone),podAntiAffinity 避免单点故障。例如,高可用部署避免相同服务 Pod 同节点:

affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
    - labelSelector:
        matchLabels:
          app: my-app
      topologyKey: kubernetes.io/hostname

参数要点:

  • operator:In/NotIn(多值匹配)、Exists/DoesNotExist(键存在)、Gt/Lt(数值比较,仅 nodeAffinity)。
  • topologyKey:如 kubernetes.io/hostname(节点级)、topology.kubernetes.io/zone(区域级)。
  • 权重总分最高节点优先,结合资源评分。

落地清单:1. 标签节点kubectl label nodes node1 accelerator=gpu;2.Deployment 中配置 affinity;3. 监控kubectl get pods -o wide,调整 weight 防 Pending。

官方文档指出,亲和性比 nodeSelector 更强大,支持复杂表达式。[1]

污点与容忍机制

污点(Taints)是节点 “排斥” 标签,Pod 需配置容忍(Tolerations)匹配 key=value:effect 才能调度。常用于专用节点如 GPU 隔离。

命令打污点:kubectl taint nodes node-gpu dedicated=gpu:NoSchedule

Pod YAML 容忍:

spec:
  tolerations:
  - key: "dedicated"
    operator: "Equal"
    value: "gpu"
    effect: "NoSchedule"
  - key: "disktype"  # 模糊匹配
    operator: "Exists"
    effect: "NoExecute"
    tolerationSeconds: 300  # NoExecute宽限期

效果类型:

Effect 描述
NoSchedule 拒绝新 Pod 调度
PreferNoSchedule 尽量避免
NoExecute 拒绝新 Pod 并驱逐无容忍旧 Pod

风险:过度 taint 导致无可用节点,监控kubectl describe node的 Taints。

实战:GPU 节点kubectl taint nodes gpu-node nvidia.com/gpu=true:NoSchedule,仅容忍 Pod 调度。回滚:kubectl taint nodes gpu-node nvidia.com/gpu=true:NoSchedule-

Pod 拓扑分布约束

K8s 1.19 + 引入 topologySpreadConstraints,实现跨 zone/hostname 均匀分布,避免集中故障。核心参数 maxSkew 定义最大偏差。

示例:跨 zone 均匀:

spec:
  topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: topology.kubernetes.io/zone
    whenUnsatisfiable: DoNotSchedule  # 或ScheduleAnyway
    labelSelector:
      matchLabels:
        app: my-app
  • maxSkew=1:目标域 Pod 数与全局最小差≤1。
  • minDomains:最小合格域数(v1.28 + 默认)。
  • whenUnsatisfiable:DoNotSchedule(硬)或 ScheduleAnyway(软优先低 skew)。
  • nodeAffinityPolicy/nodeTaintsPolicy:Honor(尊重)或 Ignore(忽略)节点亲和 / 污点(v1.26+ beta)。

内置默认:hostname maxSkew=3,zone maxSkew=5(ScheduleAnyway)。

拓扑感知卷绑定

为高效多节点存储,CSI 支持 Topology-Aware Volume Provisioning。动态 provision PV 时,匹配 Pod topologyKeys(如 zone),确保卷本地绑定,减少跨域延迟。

StorageClass 配置:

apiVersion: storage.k8s.io/v1
kind: StorageClass
parameters:
  csi.storage.k8s.io/fstype: ext4
allowedTopologies:
- matchLabelExpressions:
  - key: topology.kubernetes.io/zone
    values: ["us-east-1a", "us-east-1b"]

参数:allowedTopologies 限制 provision 域。Pod 调度后,CSI 检查 volume 是否匹配 topology,否则延迟绑定。

监控:kubectl describe pvc,事件中查看 VolumeBinding 失败。

组合工程化实践

多机制协同:

  1. 专用池:GPU 节点 taint + nodeAffinity。
  2. HA 分布:podAntiAffinity + topologySpread(hostname skew=1)。
  3. 卷本地:topologySpread(zone)+ allowedTopologies。

阈值建议:

场景 maxSkew topologyKey whenUnsatisfiable
小集群 HA 1 hostname DoNotSchedule
大集群均衡 2 zone ScheduleAnyway
卷本地 1 zone DoNotSchedule

回滚策略:优先 ScheduleAnyway,Descheduler 定期重平衡(LowNodeUtilization)。监控 Prometheus scheduler_pending_pods,警报 > 10。

引用 Kubernetes 官方文档,亲和性和拓扑约束可显著降低跨域流量。[2]

实际部署中,先小规模测试,避免硬约束导致 Pending。通过这些参数,集群资源利用率提升 20% 以上,故障域恢复更快。

资料来源: [1] https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ [2] https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/

(字数:1256)

查看归档