知识卡片
状态共享双循环调度机制用调度缓存避免每次调度都远程轮询节点
内容
调度问题在几个、十几个节点的小集群里怎么实现都不难,但在数千节点的 大规模集群里就完全不同:各节点资源状态实时变动,如果每次调度都要发起 数千次远程调用去问各节点”你现在还有多少资源”,调度器本身会先成为 性能瓶颈,而且等信息传回来时状态很可能又变了,调度结果不准确。Google 在Omega论文里总结的解法是”共享状态的双循环调度机制”,后来被Kubernetes 继承。第一个循环叫Informer Loop:一组Informer持续监视etcd中Pod、Node 等资源的变化,一旦有变动就触发对应Handler,更新调度队列(Priority Queue)和调度缓存(Scheduler Cache)——新Pod生成就入队,必要时触发 [[Pod优先级与抢占机制让高优先级Pod主动挤走低优先级Pod]]里的抢占;节点 加入或资源变动就同步进调度缓存。第二个循环叫Scheduler Loop:不停地从 调度队列里取出Pod,用Predicate算法(一组节点过滤器)筛选节点——注意 Predicate算法用的数据全部来自调度缓存,绝不会去远程访问节点本身,整个 Scheduler Loop除了最后异步写一次etcd做绑定,其余都是进程内访问。调度 缓存正是两个循环共享的状态(Shared State)——这个设计避免了每次调度 都主动轮询全部节点,是调度器执行效率的关键保证。但共享状态终究会有 同步延迟,所以调度结果出来后、kubelet真正创建Pod前,还要在目标节点上 重新跑一次Predicate算法做Admit二次确认,弥补”调度缓存已经过时”这个 残余风险。
结构图:
flowchart LR
A[etcd资源变化] -->|Informer监视| B[Informer Loop]
B -->|更新| C[调度队列 Priority Queue]
B -->|更新| D[调度缓存 Scheduler Cache]
D -.共享状态, 无远程调用.-> E[Scheduler Loop]
C --> E
E -->|Predicate筛选+Priorities评分, 全用缓存数据| F[选定目标节点]
F -->|异步写etcd做绑定| G[kubelet检测到变化]
G -->|Admit二次确认Predicate| H[真正创建Pod]
参考来源
- 位置:《凤凰架构:构建可靠的大型分布式系统》第14章"资源与调度"14.4节
"默认调度器"(源文件:_epub-src对应OEBPS/Text/chapter167.xhtml)
- 结论依据:原文详述Informer Loop监视etcd变化更新调度队列和调度缓存、
Scheduler Loop只用调度缓存数据运行Predicate算法不做远程访问,以及
Admit操作作为二次确认弥补状态同步延迟,直接支撑本卡片的结构梳理。
- 原始内容:Google在论文……提出了一种共享状态的双循环调度机制……
Predicate算法所使用的一切数据均来自于调度缓存,而绝对不会去远程
访问节点本身……当调度结果出来之后,kubelet真正创建Pod之前,还必须
执行一次Admit操作,在该节点上重新调用Predicate算法来进行二次确认。