4. 默认调度算法:节点筛选(Predicates)、节点优选(Priorities)、调度器扩展点
Kubernetes 默认调度器(kube-scheduler)的核心工作流程可概括为两个连续阶段:节点筛选(Predicates)与节点优选(Priorities)。筛选阶段从集群中选出所有满足 Pod 调度约束的候选节点;优选阶段则对这些候选节点进行打分排序,最终选择最优节点完成绑定。此外,调度器还提供了丰富的扩展点(Extension Points),允许用户在不修改核心代码的前提下注入自定义调度逻辑。
4.1 节点筛选(Predicates)
筛选阶段是一组硬约束(Hard Constraints)的集合,只有通过所有激活筛选器的节点才会进入下一阶段。如果没有任何节点通过筛选,Pod 将处于 Pending 状态,调度器会持续重试直到满足条件。
| 筛选器名称 | 功能描述 | 关键参数 |
|---|---|---|
| PodFitsResources | 检查节点剩余 CPU、内存等资源是否满足 Pod 请求 | requests.cpu, requests.memory |
| PodFitsHostPorts | 检查节点上指定端口是否已被占用 | containerPort, hostPort |
| PodMatchNodeSelector | 检查节点标签是否匹配 Pod 的 nodeSelector 或 nodeAffinity | nodeSelector, matchExpressions |
| PodToleratesNodeTaints | 检查 Pod 的 tolerations 是否能容忍节点的 taints | taints, tolerations |
| CheckNodeDiskPressure | 检查节点是否处于磁盘压力状态 | NodeCondition |
| CheckNodeMemoryPressure | 检查节点是否处于内存压力状态 | NodeCondition |
| CheckNodePIDPressure | 检查节点是否处于 PID 压力状态 | NodeCondition |
| CheckNodeUnschedulable | 检查节点是否被标记为不可调度(spec.unschedulable: true) |
node.Spec.Unschedulable |
| InterPodAffinity | 检查节点上已有 Pod 是否满足 Pod 的亲和性/反亲和性规则 | podAffinity, podAntiAffinity |
性能优化提示: 筛选器按计算开销从低到高排序执行。例如,
CheckNodeUnschedulable 和 PodFitsResources 优先执行,而 InterPodAffinity 等需要遍历所有 Pod 的筛选器放在最后。这种排序可以尽早淘汰不合格节点,减少计算量。
4.2 节点优选(Priorities)
优选阶段对通过筛选的节点进行软评分(Soft Scoring),每个优选器输出 0-100 的分数,最终按权重加权求和,得分最高的节点被选中。如果多个节点得分相同,调度器会随机选择一个。
| 优选器名称 | 评分逻辑 | 默认权重 |
|---|---|---|
| LeastRequestedPriority | 优先选择资源利用率低的节点,实现负载均衡 | 1 |
| MostRequestedPriority | 优先选择资源利用率高的节点,提高资源装箱率 | 1 |
| BalancedResourceAllocation | 优先选择 CPU 和内存使用率最均衡的节点 | 1 |
| NodePreferAvoidPodsPriority | 根据节点注解 scheduler.alpha.kubernetes.io/preferAvoidPods 打分 |
10000 |
| NodeAffinityPriority | 根据 preferredDuringSchedulingIgnoredDuringExecution 亲和性规则打分 |
2 |
| TaintTolerationPriority | 根据 Pod 对节点 taints 的容忍程度打分,容忍越多分数越高 | 1 |
| InterPodAffinityPriority | 根据 Pod 亲和性/反亲和性偏好打分 | 2 |
| ImageLocalityPriority | 优先选择已缓存 Pod 所需镜像的节点 | 1 |
关键理解: 筛选是“能不能调度”,优选是“调度到哪里最好”。筛选失败意味着 Pod 无法运行在该节点;优选分数低只是调度优先级低,并不阻止调度。
4.3 调度器扩展点(Extension Points)
Kubernetes 1.19+ 的调度器框架(Scheduling Framework)将调度流程拆分为多个扩展点,每个扩展点对应一个调度阶段。用户可以通过实现 Plugin 接口并注册到指定扩展点,来定制调度行为。
4.4 自定义调度器配置示例
以下是一个使用 KubeSchedulerConfiguration 启用自定义插件的配置片段:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: custom-scheduler
plugins:
filter:
enabled:
- name: "MyCustomFilter"
score:
enabled:
- name: "MyCustomScorer"
disabled:
- name: "*" # 禁用所有默认评分插件
pluginConfig:
- name: "MyCustomFilter"
args:
threshold: 80
注意: 禁用默认插件(如
NodeResourcesFit、NodeName)可能导致调度行为异常。建议在自定义插件中保留关键筛选逻辑,或通过 disabled 精确控制而非通配符禁用。
4.5 调度算法选择策略
- 默认策略:适用于大多数通用工作负载,兼顾资源利用率和负载均衡。
- 装箱策略(Bin Packing):启用
MostRequestedPriority并提高权重,适用于资源紧张、需要最大化节点利用率的场景。 - 拓扑感知策略:结合
NodeAffinityPriority和InterPodAffinityPriority,将 Pod 调度到靠近数据源或同组 Pod 的节点,降低网络延迟。 - 自定义策略:通过扩展点注入 GPU 拓扑、NUMA 亲和性、存储本地性等专业调度逻辑。
生产建议: 在大型集群中,筛选器和优选器的数量直接影响调度延迟。建议定期使用
scheduler_scheduling_duration_seconds 指标监控各阶段耗时,对计算开销大的插件(如 InterPodAffinity)进行针对性优化或降级。