【Kubernetes从入门到精通】第64篇:Scheduler深度解析——Pod调度算法的“高考阅卷“,预选打分一个不落 上一篇【第63篇】Informer机制——K8s高性能事件驱动的核心没有它控制器早累死了下一篇【第65篇】kubelet深度解析——节点上的全能管家摘要当你kubectl apply一个PodAPI Server把它存进etcd状态是Pending——因为还没决定放哪个Node。这时候Scheduler出场了。Scheduler的工作像高考阅卷先预选过滤掉不满足条件的Node就像先划分数线再优选给剩下的Node打分排名就像按总分排座次最后挑最高分的绑定。这套机制在K8s里叫Scheduling Framework由一串可插拔的扩展点组成。这篇文章讲透调度流程、预选和优选的核心策略以及怎么写自定义调度插件比如让GPU Pod只去有GPU的机器。第026篇我们聊过调度的婚介所比喻这篇是那个比喻的源码级展开。一、调度流程总览1.1 两阶段预选 优选【Scheduler 调度一个Pod的全流程】 Pod 创建 → 状态 Pending (没Node) │ ▼ ┌────────────────────────────────────────────┐ │ 阶段1: 预选 (Filter / Predicates) │ │ 哪些Node有资格? │ │ • 资源够吗?(CPU/内存) │ │ • 有污点不匹配吗? │ │ • 端口冲突吗? │ │ • 亲和性满足吗? │ │ → 过滤出合格Node列表 │ └────────────────────────────────────────────┘ │ 合格列表 ▼ ┌────────────────────────────────────────────┐ │ 阶段2: 优选 (Score / Priorities) │ │ 合格Node里谁最合适? │ │ • 哪个Node剩余资源多? │ │ • 哪个Node上同类Pod少?(打散) │ │ • 哪个Node离数据近? │ │ → 每个Node打0-100分加权求和 │ └────────────────────────────────────────────┘ │ 最高分Node ▼ ┌────────────────────────────────────────────┐ │ 阶段3: 绑定 (Bind) │ │ 写 Pod.spec.nodeName 选中的Node │ │ → 状态变 Boundkubelet接手起容器 │ └────────────────────────────────────────────┘要点预选是排除法先砍掉不合格优选是选拔法在合格里挑最好。如果预选后一个Node都不剩Pod就一直Pending——这时候就该看调度失败事件第069篇Event机制、第084篇排障会讲。这个先过滤再打分的思路和高考先过线再排名一模一样。二、Scheduling Framework2.1 扩展点一览K8s v1.19的调度器是插件化的由一串扩展点组成【Scheduling Framework 扩展点(调度流水线)】 QueueSort → 决定Pod出队顺序(谁先调度) │ ▼ PreFilter → 预选前的准备工作(预计算) │ ▼ Filter → ★预选(核心!) 返回true/false │ (插件: NodeUnschedulable/PodFitsResources/ │ NodeAffinity/TaintToleration/... ) ▼ PostFilter→ 预选全失败时的补救(如抢占Preemption) │ ▼ Score → ★优选(核心!) 给Node打0-100分 │ (插件: LeastAllocated/NodeAffinity/ │ InterPodAffinity/ImageLocality/... ) ▼ Reserve → 预留资源(防止并发调度抢同一Node) │ ▼ Permit → 允许/拒绝/等待(可延迟绑定) │ ▼ PreBind → 绑定前准备(如准备网络/卷) │ ▼ Bind → ★真正写 nodeName │ ▼ PostBind → 绑定后清理2.2 关键插件说明扩展点插件名作用FilterPodFitsResourcesPod资源请求 ≤ Node可分配量FilterNodeUnschedulableNode没被标记为不可调度FilterTaintTolerationPod能容忍Node的污点FilterNodeAffinity满足节点亲和性FilterInterPodAffinity满足Pod间亲和/反亲和ScoreLeastAllocinated剩余资源多的Node高分ScoreBalancedAllocation资源分配均衡的Node高分ScoreInterPodAffinity满足亲和打散的Node高分ScoreImageLocality已有镜像的Node高分(省拉取)三、预选策略详解3.1 常见的一票否决【预选 每个Filter都是一票否决】 Node A 资源够 没污点 端口不冲突 → 合格 ✅ Node B 资源不够 → 直接淘汰 ❌ (其他条件再好也没用) 核心预选条件 • PodFitsResources: requested CPU/Mem ≤ allocatable • PodFitsHost: Pod指定了nodeName/nodeSelector要匹配 • PodFitsHostPorts: Node上该hostPort没被占 • NoDiskConflict: 挂载的卷不冲突 • MatchNodeSelector: 匹配nodeSelector • CheckServiceAffinity: 满足Service的亲和 • PodToleratesNodeTaints: 容忍Node污点# 看调度失败原因(预选没过)kubectl describe pod my-pod# Events:# Warning FailedScheduling 0/3 nodes are available:# 1 node(s) had untolerated taint,# 2 node(s) didnt match PodFitsResources (insufficient cpu)# ↑ 直接告诉你哪个预选条件挂了四、优选策略详解4.1 打分求和【优选 多个Score插件加权求和】 对每个合格Node每个Score插件给0-100分 Node A: LeastAllocated80, Balanced60, ImageLocality40 Node B: LeastAllocated50, Balanced70, ImageLocality90 加权求和(有默认权重): Node A 80*w1 60*w2 40*w3 总分X Node B 50*w1 70*w2 90*w3 总分Y 选总分最高的 → 如果并列随机挑一个(防脑裂)4.2 两个最常用的优选【LeastAllocated vs BalancedAllocation】 LeastAllocated (剩余越多分越高): 目的: 把Pod分散到不同Node避免单Node过载 适合: 一般业务追求打散 BalancedAllocation (各资源比例均衡分越高): 目的: 避免CPU用光但内存闲着(或反过来) 适合: 混合负载追求资源利用率均衡 实际是两者配合先用LeastAllocated打散 再用BalancedAllocation避免资源倾斜五、自定义调度插件5.1 实战GPU Pod只去GPU节点// 自定义Score插件(伪代码): GPU Pod优先调度到有GPU的NodetypeGPUScorePluginstruct{}func(p*GPUScorePlugin)Score(ctx,cycleState,pod,node)(int64,*Status){nodeHasGPU:node.Labels[accelerator]nvidia-tesla-v100podNeedsGPU:pod.Spec.Resources.Limits[nvidia.com/gpu]0ifpodNeedsGPUnodeHasGPU{return100,nil// 完美匹配满分}ifpodNeedsGPU!nodeHasGPU{return0,nil// 需要GPU但没GPU0分(自然被淘汰)}return50,nil// 不需要GPU普通分}// 注册为Score插件 → 编译进自定义调度器或用调度器扩展# 或者用现成的: 直接给GPU Node打污点NodeAffinity# 更简单不用写代码(见第027/028篇)kubectl labelnodegpu-node-1acceleratornvidia-tesla-v100 kubectl taint nodes gpu-node-1gputrue:NoSchedule要点大部分自定义调度需求其实用NodeAffinityTaint/Toleration就能搞定见第027/028篇不用写插件。真正需要写调度插件的是打分逻辑特殊的场景比如考虑实时电价、考虑数据局部性。Scheduling Framework的插件化设计让扩展调度变得整洁——你只实现关心的扩展点其他用默认的。本篇小结Scheduler用预选优选两阶段给Pod选Node预选是Filter插件的一票否决资源够吗、污点容忍吗、端口冲突吗优选是Score插件加权打分剩余资源多、分配均衡、镜像就近的Node高分最后Bind写nodeName。这套流程封装在Scheduling Framework里由QueueSort→Filter→Score→Reserve→Permit→Bind等扩展点串成流水线。简单调度需求用AffinityTaint就够了复杂打分逻辑才需要写自定义插件。下篇讲kubelet——Node上真正起容器的全能管家。上一篇【第63篇】Informer机制——K8s高性能事件驱动的核心没有它控制器早累死了下一篇【第65篇】kubelet深度解析——节点上的全能管家

相关新闻

最新新闻

放射性废水扩散建模:从对流-扩散方程到Python数值求解实战

放射性废水扩散建模:从对流-扩散方程到Python数值求解实战

1. 项目概述:从“华数杯”赛题看放射性废水扩散建模 最近刚带着团队打完今年的“华数杯”数学建模竞赛,题目一出来就引起了不小的讨论,尤其是这道关于日本放射性废水排放的题。说实话,这类环境流体扩散问题在数模竞赛里算是经典题…

2026/8/21 9:17:43
30秒搞定公式编号与电子签名排版:Word/LaTeX/Markdown全方案

30秒搞定公式编号与电子签名排版:Word/LaTeX/Markdown全方案

最近在整理技术文档和论文时,很多同学都遇到了公式编号和电子签名排版的“老大难”问题。公式编号要么偏上,要么偏下,就是没法跟公式本身完美对齐;手写的电子签名插入文档后,更是七零八落,严重影响文档的专…

2026/8/21 9:17:43
2026智能巡检机器人选型指南:从场景需求倒推技术规格

2026智能巡检机器人选型指南:从场景需求倒推技术规格

你打开采购清单,准备为项目选型一台智能巡检机器人。面对市场上五花八门的宣传资料,从“AI视觉识别”到“自主导航”,从“多传感器融合”到“云边协同”,每个厂商都说自己的产品是“最优解”。但当你真正开始对比参数、询问价格、…

2026/8/21 9:17:43
从 Coding 到 Working:国产 Work 系 Agent 和海外 Codex、Claude Cowork 有什么不同

从 Coding 到 Working:国产 Work 系 Agent 和海外 Codex、Claude Cowork 有什么不同

文章目录从 Coding 到 Working:国产 Work 系 Agent 和海外 Codex、Claude Cowork 有什么不同海外:先征服开发者,再外溢到所有人Claude Code → Claude CoworkCodex → ChatGPT Work国产:直接面向办公,绑定自家生态Work…

2026/8/21 9:17:43
大模型量化实战:7B参数模型压缩至4GB以下,NF4与GPTQ方案详解

大模型量化实战:7B参数模型压缩至4GB以下,NF4与GPTQ方案详解

1. 项目概述:当7B模型遇上4GB内存墙 最近在折腾大语言模型本地部署的朋友,估计都绕不开一个头疼的问题:显存。一个7B参数量的模型,动辄就要14GB以上的显存才能以FP16精度跑起来,这对大多数消费级显卡来说,简…

2026/8/21 9:17:43
Vue面试高频考点与实战技巧全解析

Vue面试高频考点与实战技巧全解析

1. Vue面试题全面解析:从基础到实战高频考点 作为前端开发者,Vue.js的掌握程度直接影响着你的职业发展。我在技术面试中担任过多次面试官,也参与过不少前端岗位的招聘评审工作。今天就来分享那些真正在面试中高频出现的Vue问题,以…

2026/8/21 9:12:42