[k8s理论知识]6.k8s调度器

news/2024/10/25 11:44:20/

k8s默认调度器

k8s调度器的主要职责,就是为一个新创建出来的pod寻找一个适合的节点Node。这包括两个步骤,第一,从所有集群的节点中,根据调度算法挑选出所有可以运行该pod的节点,第二,从第一步的结果中,根据调度算法挑选一个最符合条件的pod作为最终结果。

所以在具体的调度流程中,默认调度器会首先调用一组叫作 Predicate 的调度算法,来检查每个 Node。然后,再调用一组叫作 Priority 的调度算法,来给上一步得到的结果里的每个 Node 打分。最终的调度结果,就是得分最高的那个 Node。

cache化

为了高效的完成调度过程,调度器必须要频繁的查询集群的状态信息,如节点的资源使用情况,节标签、污点等等。这些操作每次都从etcd中获取数据,会导致性能瓶颈。为了解决这个问题,Kubernetes 引入了调度器缓存(scheduler cache)。调度器缓存是一个内存中的数据结构,用于存储集群的节点信息和其他相关元数据。通过将这些信息缓存起来,调度器可以更快地访问和处理这些数据,从而提高调度算法的执行效率。

通过将集群信息尽可能的缓存化,可以提高k8s的调度效率,提高性能。通过将节点信息和其他元数据缓存到内存中,调度器可以减少对 etcd 的直接访问次数,从而降低网络延迟和 I/O 开销。

从上图可以看出,第一个控制循环informer Path的主要目的就是启动一系列的informer,用来监听etcd中的pod、node、service等与调度相关的API对象的变化,如果有调度需求,就将这个pod加入调度队列,这个调度队列是一个优先级队列。调度器还要负责对调度器缓存进行更新(update cache)。

第二个控制循环是负责Pod调度的主循环,叫做scheduling path。Scheduling Path 的主要逻辑,就是不断地从调度队列里出队一个 Pod。然后,调用 Predicates 算法进行“过滤”。这一步“过滤”得到的一组 Node,就是所有可以运行这个 Pod 的宿主机列表。当然,Predicates 算法需要的 Node 信息,都是从 Scheduler Cache 里直接拿到的,这是调度器保证算法执行效率的主要手段之一。接下来,调度器就会再调用 Priorities 算法为上述列表里的 Node 打分,分数从 0 到 10。得分最高的 Node,就会作为这次调度的结果。执行完调度算法之后,调度器就需要将 Pod 对象的 nodeName 字段的值,修改为上述 Node 的名字。这个步骤在 Kubernetes 里面被称作 Bind。

乐观绑定

当进行到上面说的修改nodeName的时候,其实pod还没有被部署到这个节点。但是这个时候scheduler就已经把这个调度信息写入到scheduler cache中了。然后再异步的向API server发起更新pod的请求,以真正的完成bind操作。这种设计被称为乐观假设。

这是因为如果选定node名称之后,发起同步的API server通信等待响应,会显著增加调度器的延迟。通过异步绑定,调度器可以在确定合适节点后立即更新调度器缓存,然后继续处理下一个 Pod 的调度,而不需要等待 API Server 的响应。这大大减少了关键路径上的延迟,提高了调度器的吞吐量。

如果调度失败的话,scheduler cache中写入的内容也会在与etcd更新的时候进行修正,并不会使集群的信息不同步。

admit操作

由于乐观绑定的操作,当一个新的 Pod 完成调度需要在某个节点上运行起来之前,该节点上的 kubelet 还会通过一个叫作 Admit 的操作来再次验证该 Pod 是否确实能够运行在该节点上。Admit 操作会重新执行一组最基本的调度算法,如“资源是否可用”、“端口是否冲突”等,作为 kubelet 端的二次确认。

无锁化

调度器会启动多个 Goroutine,以节点为粒度并发执行 Predicates 算法。这样可以并行地检查多个节点是否满足 Pod 的调度要求,从而显著提高这一阶段的执行效率。在并发编程中,锁是一种常用的同步机制,用于确保多个 Goroutine 之间对共享资源的访问是安全的。比如说多个goroutine可能会同时的向队列中加入或移除pod,或是同时操作scheduler cache。然而,锁的使用会带来一定的性能开销,特别是在高并发场景下。

为了增加predicate过程的速度,调度器采用了无锁化设计,在这些并发路径上,调度器避免设置任何全局的竞争资源,从而避免了没有锁带来的状态难以管理的问题。

默认调度器的重构

随着 Kubernetes 项目的逐步稳定,越来越多的用户开始将其应用于规模更大、业务更加复杂的私有集群中。在这些复杂场景下,用户对默认调度器的扩展和重新实现提出了更高的需求。社区对 Kubernetes 项目的主要诉求之一就是增强默认调度器的可扩展性。

下图是默认调度器的可扩展性设计的示意图。可以看到在调度器生命周期的各个关键点上,为用户暴露出了可以扩展和实现的接口。每一个绿色的箭头都是一个可以插入自定义逻辑的接口。比如,上面的 Queue 部分,就意味着你可以在这一部分提供一个自己的调度队列的实现,从而控制每个 Pod 开始被调度(出队)的时机。

在 Kubernetes 的整体架构中,kube-scheduler 的责任虽然重大,但其实它却是在社区里最少受到关注的组件之一。这里的原因也很简单,调度这个事情,在不同的公司和团队里的实际需求一定是大相径庭的,上游社区不可能提供一个大而全的方案出来。所以,将默认调度器进一步做轻做薄,并且插件化,才是 kube-scheduler 正确的演进方向。 


http://www.ppmy.cn/news/1541815.html

相关文章

10.24程序员节,你的代码安全吗?

随着10月24日程序员节的到来,我们向全世界的程序员们致敬,感谢他们用代码构建了我们依赖的数字化世界。在这个属于程序员的节日里,我们不仅要庆祝程序员的成就,更应该关注他们在网络安全领域的重要作用。网络开发人员作为数字世界…

PodCastLM:将PDF内容转化为音频播客的创新工具

在这个信息爆炸的时代,我们每天都在接触大量的文本内容,从学术论文到新闻报道,再到各种专业文章。但是,你有没有想过,这些静态的文字内容可以被转换成生动的音频播客,让你在通勤、健身或是休息时也能轻松吸…

linux-fslc 与 linux-imx

git://github.com/Freescale/linux-fslc.git 和 https://github.com/nxp-imx/linux-imx.git区别 git://github.com/Freescale/linux-fslc.git 和 https://github.com/nxp-imx/linux-imx.git 是两种不同的 Linux 内核源码仓库,分别由 Freescale 和 NXP 提供。它们的…

Java安全——AES(对称加密)和 RSA(非对称加密)的实现

目录 一、对称加密和非对称加密 1.对称加密 常见算法 2.非对称加密 常见算法 3.对称加密和非对称加密的对比 二、AES(对称加密) 1.生成AES密钥 2.加密数据 3.解密数据 完整代码 三、RSA(非对称加密) 1.生成RSA密钥对…

基于KU115+ZU19EG+C6678 的高性能6U VPX 载板

基于KU115ZU19EGC6678 的高性能6U VPX 载板,板载 2 个 HPC 形式的FMC 连接器(用于外部信号扩展)。板卡选用了 1 片Xilinx 公司的Kintex UltraScale 系列 FPGA 家族中的XCKU115-2FLVA1517I 和 1 片 Zynq UltraScale MPSoC 家族的XCZU19EG-2FFV…

django celery 定时任务 Crontab 计划格式

Celery 定时任务教程 Celery 是一个强大的异步任务队列/作业队列基于分布式消息传递的开源项目。它广泛用于处理各种类型的后台任务,例如发送电子邮件、处理图像、数据分析和视频转换等。 本文将介绍如何使用 Celery 实现定时任务,包括: 安…

智能AI监测系统燃气安全改造方案的背景及应用价值

随着燃气行业的迅速发展和城市化进程的加快,燃气安全管理成为企业运营和城市管理中不可忽视的关键领域。燃气泄漏、管道破损等事故的发生不仅会造成严重的经济损失,还威胁到人民生命财产安全。传统的安全管理方法往往依赖人工巡检和手动监测,…

【CSS进阶】之属性值的计算过程背后的原理

当我们在页面上看见一个元素显示的时候,并附上了丰富的CSS样式,其实这背后经历了一系列复杂的属性计算过程,而最终页面上所呈现的样式则是最终计算的结果,可能并不是我们所编写的样式,这样一来就会在一些场景中造成一些…