6 张图带你深入了解 kube-scheduler

本文目录:

  • kube-scheduler 用途
  • Scheduler Pod 调度流程
  • 源码调用链路
  • Scheduler Framework
  • 如何扩展

kube-scheduler 用途

顾名思义:负责将 Pod 调度到 Node 上。

Pod 创建流程:

说明: 所有的组件只与 Apiserver 做交互,Apiserver 再把信息更新的 Etcd 中。

  1. 用户向 Kubernetes API server 发送创建(create/apply)指令。
  2. Apiserver 接收到配置文件,进行校验后,将配置数据存储到 etcd 中。
  3. Controller-manager 监听 Apiserver 的变化,检测到有新的 Pod 对象时,控制器创建 Pod 并将其状态设为 Pending。
  4. Scheduler 也通过监听 Apiserver 的变化,发现有新的、尚未分配节点的 Pod。根据预选策略和优选策略,选择一个最适合的 Node 来运行新的 Pod。
  5. Pod 被调度到对应的 Node 后,该 Node 上的 kubelet 组件则开始根据 Pod 配置文件,拉镜像、启动 app、就绪探针探测。
  6. Kubelet 向 Apiserver 上报状态为 Reday, Apiserver 写入到 etcd 中。

Scheduler 调度流程

Scheduler 的作用是 负责将 Pod 调度到 Node 上。

如果让你设计这个组件,你会如何设计,保证它稳定高效的运行。

1)需要能够实时监听到 有新的 Pod 待调度

2)同一时间如果有大量待调度的 Pod,如果处理,如果保证不能漏掉,应该先处理哪个 Pod,调度过程中,如果失败,如何处理, 所以得加个队列,有重试机制等

3)调度过程中依赖 Node、Pod 的实时信息,根据 Node、Pod 信息,决策 Pod 调度到哪个Node上合适,每次调度 调 Apiserver ,显然低效, 得在本地缓存一份数据,加个缓存

4)调度选择过程中,考虑因素太多,很难周全,可扩展性一定要设计好

5)Pod 绑定过程中 可能依赖 pvc 绑定等,耗时较长, 所以绑定得是异步的, 但是匹配哪个Node合适的算法 需要同步执行,所以要有两个周期, 调度周期和绑定周期,调度周期串行,绑定周期并行

duang,框架这不就出来的了

源码调用链路

原图放到 Github 上了,需要的自取,图片使用 draw.io 画的,可打开后二次编辑

https://github.com/clay-wangzhi/draw/blob/main/k8s-scheduler.png

# 42个序号对应的源码位置依次为:
1 找到启动主函数
https://github.com/kubernetes/kubernetes/blob/v1.31.0/cmd/kube-scheduler/scheduler.go#L30
https://github.com/kubernetes/kubernetes/blob/v1.31.0/cmd/kube-scheduler/app/server.go#L81
https://github.com/kubernetes/kubernetes/blob/v1.31.0/cmd/kube-scheduler/scheduler.go#L31
https://github.com/kubernetes/kubernetes/blob/v1.31.0/cmd/kube-scheduler/app/server.go#L1342 Setup 初始化
https://github.com/kubernetes/kubernetes/blob/v1.31.0/cmd/kube-scheduler/app/server.go#L153
https://github.com/kubernetes/kubernetes/blob/v1.31.0/cmd/kube-scheduler/app/server.go#L3843、16 初始化 scheduler 实例
https://github.com/kubernetes/kubernetes/blob/v1.31.0/cmd/kube-scheduler/app/server.go#L413
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/scheduler.go#L363
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/scheduler.go#L654、5 初始化 snapshot 实例
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/scheduler.go#L293
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/cache/snapshot.go#L48
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/cache/snapshot.go#L296、7、8、9 初始化 profiles、fwk 实例
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/scheduler.go#L304
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/profile/profile.go#L49
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/profile/profile.go#L38
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/framework/runtime/framework.go#L260
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/framework/runtime/framework.go#L5310、11、12 初始化 podQueue 实例
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/scheduler.go#L340
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/queue/scheduling_queue.go#L134
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/queue/scheduling_queue.go#L372
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/queue/scheduling_queue.go#L15513、14、15 初始化 schedulerCache 实例
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/scheduler.go#L357
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/cache/cache.go#L41
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/cache/cache.go#L87
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/cache/cache.go#L5717、18 运行 scheduler
https://github.com/kubernetes/kubernetes/blob/v1.31.0/cmd/kube-scheduler/app/server.go#L159
https://github.com/kubernetes/kubernetes/blob/v1.31.0/cmd/kube-scheduler/app/server.go#L163
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/scheduler.go#L46019、运行 SchedulingQueue
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/scheduler.go#L462
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/queue/scheduling_queue.go#L41720、21 从队列中拿出 Pod 进行调度
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/scheduler.go#L470
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L65
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/queue/scheduling_queue.go#L944获取 fwk
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L85
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L36822、23、24、25、26、27、28、29、30、31、32、33、34、35 进入 调度周期
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L110
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L138
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L148
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L400更新 Snapshot
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L403
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/cache/cache.go#L185https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L412
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/cache/snapshot.go#L173运行 PreFilterPlugins
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L463
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/framework/runtime/framework.go#L698运行 FilterPlugin
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L507
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L582
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L616
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L649
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/framework/runtime/framework.go#L973
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/framework/runtime/framework.go#L861运行 PreScorePlugins
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L435
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L754
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L777
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/framework/runtime/framework.go#L1052运行 ScorePlugins
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L783
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/framework/runtime/framework.go#L1101运行 ReservePluginsReserve
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L208
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/framework/runtime/framework.go#L1359运行 PermitPlugins
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L230
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/framework/runtime/framework.go#L144336、37、38、39、40、41 进入 绑定周期
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L124
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L264运行 WaitOnPermit
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L277
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/framework/runtime/framework.go#L1503运行 PreBindPlugins
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L293
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/framework/runtime/framework.go#L1232运行 BindPlugins
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L309
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L967
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L977
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/framework/runtime/framework.go#L1275运行 PostBindPlugins
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L322
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/framework/runtime/framework.go#L132442 标记 Pod 调度已完成,不要回队列
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/schedule_one.go#L131
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/queue/scheduling_queue.go#L981
https://github.com/kubernetes/kubernetes/blob/v1.31.0/pkg/scheduler/internal/queue/scheduling_queue.go#L988

具体代码就不贴了,太多了,可以根据调用链路图,梳理下,看不懂的可以问 gpt。

Scheduler Framework 调度器

上面调度链路图,可以清晰的看出 Framework 调度算法的扩展点。

具体每个扩展点包含哪些 plugin, 每个 plugin 可作用于那些扩展点,如下图:

如何扩展

如果我们要实现自己的插件,必须向调度框架注册插件并完成配置,另外还必须实现扩展点接口。

1)向调度框架注册插件 & 扩展点实现接口如下:

out-of-tree 实现扩展示例

main.go

package mainimport ("os""k8s.io/component-base/cli"_ "k8s.io/component-base/metrics/prometheus/clientgo" // for rest client metric registration_ "k8s.io/component-base/metrics/prometheus/version"  // for version metric registration"k8s.io/kubernetes/cmd/kube-scheduler/app""xxx/pkg/example"// Ensure scheme package is initialized._ "sigs.k8s.io/scheduler-plugins/apis/config/scheme"
)func main() {// Register custom plugins to the scheduler framework.// Later they can consist of scheduler profile(s) and hence// used by various kinds of workloads.command := app.NewSchedulerCommand(app.WithPlugin(example.Name, example.New),)code := cli.Run(command)os.Exit(code)
}

example.go

package exampleimport ("context"v1 "k8s.io/api/core/v1""k8s.io/apimachinery/pkg/runtime""k8s.io/klog/v2""k8s.io/kubernetes/pkg/scheduler/framework"
)const Name = "example"var _ framework.FilterPlugin = &ExamplePlugin{}type ExamplePlugin struct{}// NewExampleSchedPlugin initializes a new plugin and returns it.
func NewExamplePlugin(_ runtime.Object, _ framework.Handle) (framework.Plugin, error) {return &ExamplePlugin{}, nil
}func (e *ExamplePlugin) Filter(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeInfo *framework.NodeInfo) *framework.Status {cpu := nodeInfo.Allocatable.MilliCPUmemory := nodeInfo.Allocatable.Memoryklog.InfoS("tanjunchen-scheduler Filter", "pod_name", pod.Name, "current node", nodeInfo.Node().Name, "cpu", cpu, "memory", memory)return framework.NewStatus(framework.Success, "")
}func (e *ExamplePlugin) Name() string {return Name
}

2)进行配置, enable 插件

编写 kube-scheduler 启动命令配置文件 example-cm.yaml

一个 ksc 里面可以描述多个 profile, 会启动多个独立 scheduler。

pod 想用哪个 schduler,就填对应的 schdulerName。 如果没指定,就是 default-scheduler。

由于这个配置是给 kube-scheduler 的,而不是 kube-apiserver,

所以 k api-resourcesk get KubeSchedulerConfiguration 都是找不到这个资源的。

apiVersion: v1
kind: ConfigMap
metadata:name: example-scheduler-confignamespace: kube-system
data:scheduler-config.yaml: |apiVersion: kubescheduler.config.k8s.io/v1kind: KubeSchedulerConfigurationleaderElection:leaderElect: falseclientConnection:acceptContentTypes: ""burst: 100contentType: application/vnd.kubernetes.protobufqps: 100profiles:- schedulerName: example-schedulerplugins:filter:enabled:- name: "example" 

3) 使用自定义 scheduler

Pod yaml 文件中指定 schedulerName: example-scheduler 即可使用自定义 Scheduler 了

rbac授权 及 自定义 Scheduler 部署文件:略

enjoy~

参考链接:

  • 深入理解 Kubernetes Scheduler Framework 调度框架(Part 2):https://tanjunchen.github.io/post/2024-04-07-scheduler-framework-02/
  • K8s 调度框架设计与 scheduler plugins 开发部署示例(2024):https://arthurchiao.art/blog/k8s-scheduling-plugins-zh/

下篇文章,我们分析 crane 和 koordinator 中负载感知调度中的插件。

我是 Clay,下期见 👋


  • 欢迎订阅我的公众号「SRE运维进阶之路」或关注我的 Github https://github.com/clay-wangzhi/SreGuide 查看最新文章

  • 欢迎加我微信sre-k8s-ai,与我讨论云原生、稳定性相关内容

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/6702.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构(8.7_1)——外部排序

知识总览 外存、内存之间的数据交换 外部排序原理 构造初始“归并段” 第一趟归并 第二趟归并 输出缓冲区1空了用归并段1的下一块元素补上 ..... 顺序的两个归并段方法一样..... 第三趟归并 时间开销分析 对外部排序进行优化 由于文件总块数无法改变,所以…

“方块兽神仙猿点石成金”游戏搭建开发

“方块兽神仙猿点石成金”是一款结合了策略和运气的休闲游戏。玩家需在规定时间内向不同的山头投入矿石,等待神仙猿降临并随机选择一座山进行“点石成金”。根据神仙猿的选择,玩家将获得不同的奖励。 游戏核心机制 矿石投入:玩家在游戏开始…

【压力测试】如何确定系统最大并发用户数?

一、明确测试目的与了解需求 明确测试目的:首先需要明确测试的目的,即为什么要确定系统的最大并发用户数。这通常与业务需求、系统预期的最大用户负载以及系统的稳定性要求相关。 了解业务需求:深入了解系统的业务特性,包括用户行…

达梦数据库DM管理工具增删改不生效怎么办?如何设置事务自动提交?

前言 我在使用达梦数据库DM时,一开始使用的是达梦数据库自带的连接工具DM管理工具。自带的有它自己的好处,起码对于修改新增字段等是比较兼容的。后面我发现DBeaver也是支持连接达梦数据库的,所以后面用DBeaver也在连接达梦数据库。 我在一…

JVM出现OOM错误排查

前言 对应线程出现的OOM错误,其实分好几类:堆内存溢出、栈溢出、方法区溢出,下面我们要区分两个概念 内存泄漏: 内存泄漏是指GC垃圾回收的速度跟不上内存消耗的速度,造成OOM的情况 内存溢出: 内存溢出是指程序员在申请内存时&…

WinForms 中使用 MVVM 模式构建应用:实现登录页面、页面导航及 SQLite 数据库连接完整框架搭建过程

前言 在传统的 WinForms 应用程序开发中,很多开发者使用事件驱动的设计模式,直接将业务逻辑编写在界面代码中。然而,随着应用程序的复杂性增加,单一的界面文件变得臃肿,难以测试和维护。借鉴 WPF 中 MVVM(…

windows系统编程 - 静态库和动态库

文章目录 前言一、使用obj保护源码生成obj文件导入并使用obj文件方式一 拖入解决方案方式二 附加依赖项适配C语言文件 二、静态库的概述三、静态库的创建与使用四、动态库的概述五、动态库的创建六、动态库的两种调用方式七、动态链接库的隐式加载__declspec(dllimport) 声明外…

数据结构 ——— 查找链式二叉树中值为X的节点

目录 链式二叉树示意图 手搓一个链式二叉树 查找链式二叉树中值为X的节点 链式二叉树示意图 手搓一个链式二叉树 代码演示: // 数据类型 typedef int BTDataType;// 二叉树节点的结构 typedef struct BinaryTreeNode {BTDataType data; //每个节点的数据struc…

基于SSM的BBS社区论坛系统源码

1.项目介绍 系统角色:管理员、业主(普通用户)功能模块:管理员(用户管理、二手置换管理、报修管理、缴费管理、公告管理)、普通用户(登录注册、二手置换、生活缴费、信息采集、报事报修&#xf…

python的安装环境Miniconda(Conda 命令管理依赖配置)

这一段时间,对AI大模型 有了兴趣就想研究一下。 在研究之前肯定要先把需要的编程技能掌握了。经过我查阅资料,今天就先学一下 python的 环境安装。 Node.js 包管理工具:npm 依赖配置文件:package.json 环境管理:nvm&am…

出租房管理系统有哪些?

出租房管理系统在现代房产租赁市场中发挥着至关重要的作用,其供应商众多,各具特色。以下是对易收租、寓小二、全房通、水滴管家以及悟空租房管理系统等供应商的详细介绍。 一、深圳合众致达科技有限公司的易收租 深圳合众致达科技有限公司是一家专注于…

【在Linux世界中追寻伟大的One Piece】Socket编程TCP

目录 1 -> TCP socket API 2 -> V1 -Echo Server 2.1 -> 测试多个连接的情况 1 -> TCP socket API socket(): socket()打开一个网络通讯端口,如果成功的话,就像open()一样返回一个文件描述符。应用程序可以像读写文件一样用r…

【spring】IOC与DI

💐个人主页:初晴~ 📚相关专栏:程序猿的春天 一、IOC(Inversion of Control) 1、概念 IOC(Inversion of Control,控制反转)是一种设计原则,它将对象的控制权…

【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-16

文件下载与邀请翻译者 学习英特尔开发手册,最好手里这个手册文件。原版是PDF文件。点击下方链接了解下载方法。 讲解下载英特尔开发手册的文章 翻译英特尔开发手册,会是一件耗时费力的工作。如果有愿意和我一起来做这件事的,那么&#xff…

​​​​​​​PHP类型比较

在php中符号分为两种,一种是,还是一种是 松散比较:使用两个等号 比较,只比较值,不比较类型。 严格比较:用三个等号 比较,除了比较值,也比较类型。 注意,当一个号时&…

Mysql、Dm8达梦数据库通过脚本导出指定库所有表的结构详情信息到

目录 前言二、Mysql三、达梦8 前言 在当今复杂多变的数据环境中,数据库作为信息存储与管理的核心,其重要性不言而喻。随着业务的不断拓展和深化,对于数据库表结构的理解与管理成为了确保数据一致性和准确性的关键。特别是在跨数据库系统的场…

yelp数据集上识别潜在的热门商家

yelp数据集是研究B2C业态的一个很好的数据集,要识别潜在的热门商家是一个多维度的分析过程,涉及用户行为、商家特征和社区结构等多个因素。从yelp数据集里我们可以挖掘到下面信息有助于识别热门商家 用户评分和评论分析 评分均值: 商家的平均评分是反映其…

文献阅读记录6-Toward computer-made artificial antibiotics

摘要 将合成生物学和计算生物学的概念结合起来,可能会产生比现有药物更不容易产生耐药性的抗生素,而且还能对抗耐药感染。事实上,计算机引导策略与大规模并行高通量实验方法相结合,代表了抗生素发现的新范式。耐多药微生物引起的…

【docker compose】docker compose的hello world

安装docker desktop后在终端使用以下命令,代表安装成功,并查看当前安装的版本 docker-compose --version示例docker-compose.yml文件 version: 3.8 # 指定 Docker Compose 文件的版本services:scau_jwc: # 定义一个名为 scau_jwc 的服务image: scau_…

PyTorch核心概念:从梯度、计算图到连续性的全面解析(二)

文章目录 pytorch中的Autograd计算图叶子张量 inplace操作PyTorch的两大特点动态图eager execution PyTorch中的Variable参考文献 pytorch中的Autograd pytorch提供了自动求导机制和对GPU的支持 了解自动求导背后的原理和规则:当使用pytorch中没有的loss function时…