调度器怎么工作
kube-scheduler 为一个未绑定的 Pod 找节点,分成两个主要阶段:Filter(也叫 Predicates)过滤出所有可行节点,检查资源余量、节点选择器与亲和性、污点容忍、卷拓扑等硬条件;Score 给可行节点打分排序,考虑资源均衡、亲和权重、拓扑分布等倾向性因素;最后 Bind 阶段把 Pod 与选中节点写入绑定关系,由该节点 kubelet 接管创建。调度失败时不会重试到超时为止,而是按周期重新放回队列。
基本信息
| 执行者 | kube-scheduler(控制面组件,可多副本选主) |
|---|---|
| 触发时机 | Pod 创建、节点资源释放、节点状态变化等 |
| 第一阶段 | Filter:硬性过滤,任一条件不满足即淘汰节点 |
| 第二阶段 | Score:对可行节点打分,取最高分 |
| 收尾 | Bind:写入 spec.nodeName 完成绑定 |
典型使用场景
- Pod 长期 Pending:按事件里的失败原因逐条核对是资源不足还是条件不满足
- 节点刚恢复:NotReady 期间被跳过的节点会自动重新参与调度,不必手工干预
- 缩容与腾挪:理解打分倾向后,用拓扑分布与优先级让副本分散而不是挤在一台机器
- 大规格 Pod 落地:单机资源碎片化时可能出现「总余量够但单节点不够」的 Pending
- 卷与节点绑定:有状态 Pod 的调度需同时满足卷所在可用区,属于 Filter 阶段的硬条件
读懂调度事件
读懂调度事件
kubectl get events --field-selector reason=FailedScheduling --sort-by=.lastTimestamp | tail -5
kubectl describe pod pending-x | sed -n '/Events:/,$p' # 事件原文会逐个列出节点的淘汰原因
kubectl get pod pending-x -o jsonpath='{.status.conditions[?(@.type=="PodScheduled")].message}'
kubectl describe node node1 | sed -n '/Allocated resources:/,/Events:/p' # 看节点余量与已分配 requests阶段关注点
| 阶段 | 判断内容 | 典型失败表现 |
|---|---|---|
| Filter | CPU/内存余量、nodeSelector、nodeAffinity、污点容忍、卷拓扑、端口占用 | 事件里出现 Insufficient cpu/memory、node(s) had untolerated taint |
| Score | 资源均衡度、节点亲和权重、Pod 拓扑分布、镜像本地性 | Pod 能调度但分布不均,热点集中 |
| Bind | 写入绑定关系 | 绑定写入失败多为 apiserver 侧问题,较少见 |
| Preempt | 抢占低优先级 Pod 腾出空间(可选) | 事件里出现 Preempting 相关说明 |
调度只看 requests,不看实际使用量:节点上跑得很轻但 requests 写满的 Pod 一样会让新 Pod 无处可落。容量规划与 requests 设置是调度能否成功的前提。
FailedScheduling 事件的原文会给出每个节点的具体淘汰原因,例如「3 Insufficient memory, 1 node(s) had untolerated taint」,逐条读比猜测快得多,也避免把资源不足误判成亲和性配置错误。