3. 默认调度策略详解:节点选择、节点亲和性、Pod亲和性与反亲和性、污点与容忍度

Kubernetes 调度器(kube-scheduler)的核心职责是将待调度的 Pod 绑定到最合适的节点上。默认调度策略并非单一算法,而是一套由 过滤(Predicates) 和 打分(Priorities) 组成的多阶段决策流程。本章深入解析节点选择、节点亲和性、Pod 亲和性与反亲和性、污点与容忍度四大核心机制,帮助 SRE 精准控制 Pod 分布。

3.1 调度两阶段:过滤与打分

调度器对每个待调度 Pod 依次执行两个阶段:

  1. 过滤阶段(Filtering):遍历所有节点,剔除不满足 Pod 硬性约束的节点(如资源不足、端口冲突、污点不匹配)。
  2. 打分阶段(Scoring):对通过过滤的节点按优先级策略打分,选出最优节点。
关键指标: 调度延迟(Scheduling Latency)应控制在 100ms 以内;若过滤阶段耗时过长,需检查节点规模或启用调度器缓存。

3.2 节点选择:nodeName 与 nodeSelector

节点选择是最基础的调度约束,分为显式指定和标签匹配两种方式。

机制 描述 适用场景 限制
nodeName 直接指定节点名称,跳过调度器过滤 调试、单节点部署、DaemonSet 辅助 节点不可用则 Pod 无法调度;不灵活
nodeSelector 基于节点标签(label)的简单匹配 按硬件类型(如 GPU)、环境(如 prod/staging)分组 仅支持等值匹配(In/NotIn 需用节点亲和性)
# nodeName 示例
apiVersion: v1
kind: Pod
metadata:
  name: fixed-node-pod
spec:
  nodeName: worker-01
  containers:
  - name: nginx
    image: nginx

# nodeSelector 示例
apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  nodeSelector:
    hardware-type: gpu
  containers:
  - name: cuda-app
    image: nvidia/cuda:12.0

3.3 节点亲和性:精细化节点选择

节点亲和性(Node Affinity)是 nodeSelector 的升级版,支持更丰富的匹配逻辑和调度阶段控制。分为 requiredDuringSchedulingIgnoredDuringExecution(硬约束)和 preferredDuringSchedulingIgnoredDuringExecution(软约束)。

最佳实践: 硬约束用于强制 Pod 必须运行在特定拓扑(如可用区);软约束用于优化性能(如优先选择 SSD 节点),但允许降级。
apiVersion: v1
kind: Pod
metadata:
  name: node-affinity-pod
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - us-east-1a
            - us-east-1b
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: disk-type
            operator: In
            values:
            - ssd
  containers:
  - name: app
    image: myapp:latest

3.4 Pod 亲和性与反亲和性:Pod 间拓扑控制

Pod 亲和性(Pod Affinity)与反亲和性(Pod Anti-Affinity)控制 Pod 之间的相对位置,常用于微服务就近部署或高可用分散。

类型 语义 典型场景 性能影响
Pod 亲和性 将 Pod 调度到与目标 Pod 相同的拓扑域 缓存与计算服务同节点部署,减少网络延迟 增加调度器计算量,需配合 topologyKey
Pod 反亲和性 将 Pod 调度到与目标 Pod 不同的拓扑域 多副本分散到不同节点/可用区,提升容灾 required 模式可能降低集群利用率
# Pod 反亲和性:确保同一 Deployment 的副本分散在不同节点
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web
            topologyKey: kubernetes.io/hostname
      containers:
      - name: nginx
        image: nginx
避坑提示: Pod 反亲和性使用 required 模式时,若副本数超过可用拓扑域数量(如 5 副本但只有 3 节点),部分 Pod 将处于 Pending 状态。建议生产环境使用 preferred 模式或增加节点。

3.5 污点与容忍度:节点排斥与 Pod 准入

污点(Taint)是节点对 Pod 的排斥标记,容忍度(Toleration)是 Pod 对污点的豁免声明。两者共同实现节点隔离、专用节点和故障驱逐等场景。

3.5.1 污点三要素

  • Key:污点标识符,如 node.kubernetes.io/unreachable
  • Value:可选,用于更细粒度匹配
  • Effect:调度影响,包括:
    • NoSchedule:不调度新 Pod(已有 Pod 不受影响)
    • PreferNoSchedule:尽量不调度,软约束
    • NoExecute:不调度新 Pod,并驱逐已有不匹配的 Pod

3.5.2 容忍度匹配规则

污点 Effect 容忍度 Operator 匹配行为
NoSchedule Equal / Exists Pod 可调度到该节点
PreferNoSchedule Equal / Exists 调度器尽量避开,但不强制
NoExecute Equal / Exists Pod 可运行;若未容忍,则被驱逐
# 给节点添加污点:禁止普通 Pod 调度
kubectl taint nodes worker-02 dedicated=ml:NoSchedule

# Pod 容忍度示例:允许运行在专用 ML 节点
apiVersion: v1
kind: Pod
metadata:
  name: ml-pod
spec:
  tolerations:
  - key: "dedicated"
    operator: "Equal"
    value: "ml"
    effect: "NoSchedule"
  containers:
  - name: pytorch
    image: pytorch/pytorch:latest

3.6 综合调度流程:从过滤到绑定的完整链路

以下 SVG 图展示默认调度策略中节点选择、亲和性、污点容忍度的协同工作流程。

Kubernetes 默认调度策略综合流程 默认调度策略综合流程 待调度 Pod 过滤阶段(Predicates) 节点选择 | 污点容忍度 | 资源充足性 打分阶段(Priorities) 节点亲和性 | Pod 亲和性/反亲和性 绑定最优节点 调度约束优先级 1. nodeName(最高) 2. 污点容忍度 3. 节点亲和性(硬) 4. Pod 反亲和性(硬) 5. 节点亲和性(软) 6. Pod 亲和性(软) 7. 默认打分策略

3.7 实战排查:调度失败常见原因

当 Pod 处于 Pending 状态时,按以下步骤快速定位:

  1. 检查事件:kubectl describe pod <pod-name> 查看 Events 字段
  2. 验证节点资源:kubectl describe node <node-name> 查看 Allocatable 和 Conditions
  3. 确认污点:kubectl describe node <node-name> | grep Taints
  4. 检查亲和性规则:确认 labelSelector 和 topologyKey 是否匹配现有节点标签
SRE 排查口诀: 先看事件后看节点,污点标签逐个检;资源不足加节点,亲和规则别写反。

3.8 性能优化:调度器配置调优

对于大规模集群(节点数 > 500),默认调度策略可能成为瓶颈。以下参数可在 kube-scheduler 配置中调整:

参数 默认值 推荐值(大规模) 说明
percentageOfNodesToScore 50% 10% 减少打分阶段扫描节点数,降低延迟
bindTimeoutSeconds 100 30 缩短绑定超时,快速失败重试
podInitialBackoffSeconds 1 5 调度失败后初始重试间隔

通过合理组合节点选择、亲和性规则和污点容忍度,SRE 可以实现从简单隔离到复杂拓扑感知的精细化调度控制,为上层应用提供稳定、高性能的运行环境。