2021腾讯数字生态大会直播预约通道开启!技术内容大爆发,开发者必看! 了解详情
写点什么

kube-scheduler 源码解析

2019 年 11 月 27 日

kube-scheduler 源码解析

本篇文章带大家了解部署在我们 HULK 容器服务 master 节点上的重要组件之一,kube-scheduler 的运行机制解读和核心代码分析,给想要阅读学习 Kubernetes 源码的同学一个参考。


本文所涉及的源码为 Kubernetes 1.9,git commit id 为 925c127ec。本文前半部分讲解 scheduler 的原理,后半部分对 scheduler 源码进行分析。


1 kubernetes scheduler 基本原理

kubernetes scheduler 作为一个单独的进程部署在 master 节点上,它会 watch kube-apiserver 进程去发现 PodSpec.NodeName 为空的 Pod,然后根据指定的算法将 Pod 调度到合适的 Node 上,这一过程也叫绑定(Bind)。scheduler 的输入是需要被调度的 Pod 和 Node 的信息,输出是经过调度算法筛选出条件最优的 Node,并将该 Pod 绑定到这个 Node 上。如下图所示:



scheduler 调度算法分为两个阶段:


  • 预选 (Predicates)


根据 Predicates 策略去滤掉不符合 Policies 的 Node.


  • 优选 (Priorities)


经过 Predicates 剩下的 Node,需要经过 Priorities 策略选出一个最优的 Node,并将 Pod 绑定到该 Node 上。根据下面这张调度图详细描述下:


  1. 首先 scheduler 根据 predicates 集合过滤掉不符合的 Node。例如,如果 PodSpec 指定的请求资源 (resource requests),那么 scheduler 会过滤掉没有足够资源的 Node。

  2. 其次 scheduler 会根据 priority functions 集合从 predicates 中过滤出来的 Node 中,选出一个最优的 Node。


算法实现:


对每一个 Node, priority functions 会计算出一个 0-10 之间的数字,表示 Pod 放到该 Node 的合适程度,其中 10 表示非常合适,0 表示不合适,priority functions 集合中的每一个函数都有一个权重 (weight),最终的值为 weight 和 priority functions 的乘积,而一个节点的 weight 就是所有 priority functions 结果的加和。例如,有两个 priority functions: priorityFunc1 和 priorityFunc2,对应的 weight 分别为 weight1 和 weight2,那么 NodeA 的最终得分是:



  1. 最终,得分最高的 Node 胜出(如果有多个得分相同的 Node,会随机的选取一个 Node 作为最终胜出的 Node)。



2 kubernetes scheduler 源码分析

scheduler 的代码结构


  • k8s.io/kubernetes/plugin/cmd/scheduler.go 为程序入口文件 (main.go)

  • k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/server.go 包含 scheduler 的基础配置项


除了入口函数,scheduler 的具体逻辑实现均在 k8s.io/kubernetes/plugin/pkg/scheduler 目录下,这里就不一一介绍了。


scheduler 的具体实现


上面的时序图就是整个 scheduler 的具体实现逻辑。下面根据这个时序图来对 scheduler 的源码进行解析。


  • NewSchedulerCommand 创建一个 scheduler 命令行实例,用来对 scheduler 的命令行参数进行解析校验并且包含 scheduler 程序的入口函数 Run 的函数定义。

  • command.Execute() 会执行命令行实例中的 options.Run 方法。


在 options.Run 中主要进行了如下的操作:


  • loadConfigFromFile 加载 scheduler 配置文件信息。

  • NewSchedulerServer 创建 scheduler server 实例,使用 scheduler 配置参数对 scheduler server 进行初始化,如:


1.createClients 创建一系列 client,如连接 k8s 的 client,进行 scheduler 选主的 client 及 event client.


2.makeLeaderElectionConfig 生成 Leader Election 配置信息 (scheduler 做了 HA,可以同时运行多个实例进程,但只有一个能正常工作,如果主的 scheduler 挂了,会重新进行选举)。


3.makeHealthzServer 初始化 healthz server,用于健康检查。


4.makeMetricsServer 初始化 metrics server,用于 prometheus 性能监控。


  • SchedulerServer.Run 启动 SchedulerServer,用于监控还是否有 Pod 待调度,并且进行相应的调度工作。具体的代码实现:



  • SchedulerConfig() 创建 Scheduler Config,其中关键性函数是 NewConfigFactory 和 CreateFromProvider。


1.NewConfigFactory 定义了 podQueue 用来存储需要被调度的 Pod,每当新的 Pod 建立后,就会将 Pod 添加到该 queue 中。


2.CreateFromProvider 根据 algorithm provider 名称创建一个 scheduler 配置信息。其中 GetAlgorithmProvider 则根据 provider 名称去获取指定的 provider。



scheduler 默认使用的 provider 是 DefaultProvider。它主要实现了如下数据结构:



AlgorithmProviderConfig 这个数据结构包含预选和优选相关算法 key 的集合 (一个算法对应一个 key,key 是算法的名字,value 是算法的具体实现 funtion),而这些算法注册是在 scheduler/algorithmprovider/defaults/defaults.go 文件的 init() 方法中进行注册 (实现使用的是工厂模式)。 如果想了解预选和优选算法的详细信息,请参看官方文档:


https://github.com/kubernetes/community/blob/master/contributors/devel/scheduler_algorithm.md


接着往下说: 通过 GetAlgorithmProvider 得到了 provider 关联的预选和优选算法集合的 Key。然后通过调用 CreateFromKeys (预选和优选的 Key 作为参数) 来获取预选和优选算法的具体实现 (funtion),并对 NewGenericScheduler 实例进行初始化,返回最终的 scheduler 配置信息。


  • NewFromConfig 由 Scheduler Config 创建一个 schduler。

  • Start up the healthz server 启动健康检查服务

  • Start up the metrics server 启动 metrics 服务,供 Prometheus 进行性能监控数据的抓取。

  • LeaderElection 如果指定选举的方式来启动 scheduler,则使用这种方式来执行 scheduler。(使用 CallBack 的方式执行 Run 方法。如果主的 scheduler 出现问题,还会指定优雅处理函数对其进行处理)。


下面就到了 scheduler 真正干活的逻辑了,每次调度一个 Pod 都会执行下面的 Scheduler.Run(),具体的代码如下:



  • WaitForCacheSync() 将最新的数据同步到 SchedulerCache 缓存中。

  • scheduleOne() 调度 Pod 的整体逻辑。具体的实现可以看下面代码:



  • NextPod() 从 PodQueue 中获取一个未绑定的 Pod。

  • schedule(pod) 执行对应 Algorithm 的 Schedule,进行预选和优选。接口定义如下:



  • Schedule 主要包含如下几个重要的方法:


1.nodeLister.List() 获取可用的 Node 列表。


2.findNodesThatFit() 进行预选。


3.PrioritizeNodes() 进行优选。


4.selectHost() 如果优选出的多个得分相同的 Node,则随机选取一个 Node。


  • assume() 更新 SchedulerCache 中 Pod 的状态,标志该 Pod 为 scheduled,并更新到 NodeInfo 中。

  • bind() 调用 kube-apiserver API,将 Pod 绑定到选出的 Node,之后 Kube-apiserver 会将元数据写入 etcd 中。接口定义如下:



这样一个 Pod 绑定到 Node 的流程就完成了。


3 总结

kube-scheduler 作为 Kubernetes master 上一个单独的进程提供调度服务,通过 master 指定 kube-api-server 的地址,用来 watch Pod 和 watch Node 并调用 api server bind 接口完成 Node 和 Pod 的 Bind 操作。


kube-scheduler 中维护了一个 FIFO 类型的 PodQueue cache (其实还有一种 PriorityQueue 用于指定 Pod 的优先级,需要指定参数开启,默认是 FIFO 队列),新创建的 Pod 都会被 ConfigFactory watch 到,被添加到该 PodQueue 中,每次调度都从该 PodQueue 中 NextPod() 一个即将调度的 Pod。


获取到待调度的 Pod 后,就执行 AlgorithmProvider 配置 Algorithm 的 Schedule 方法进行调度,整个调度过程分两个关键步骤:Predicates 和 Priorities,最终选出一个最适合该 Pod 的 Node。


更新 SchedulerCache 中 Pod 的状态 (AssumePod),标志该 Pod 为 scheduled,并更新到 NodeInfo 中。


调用 api server 的 Bind 接口,完成 Node 和 Pod 的 Bind 操作,如果 Bind 失败,从 SchedulerCache 中删除上一步中已经 Assumed 的 Pod。


本文转载自公众号 360 云计算(ID:hulktalk)。


原文链接:


https://mp.weixin.qq.com/s/egG7g6Krtya24NxjPqAmJA


2019 年 11 月 27 日 16:24695

评论

发布
暂无评论
发现更多内容

区块链技术的价值传递

CECBC区块链专委会

区块链

深入理解 Web 协议(三):HTTP 2

vivo互联网技术

Web HTTP HTTP2.0

Protobuf源码解读之编解码

batman

protubuf zigzag varint

区块链电子合同应用平台,区块链存证系统

13530558032

趣谈哈希表优化:从规避 Hash 冲突到利⽤ Hash 冲突

程序员小毕

Java 数据结构 面试 算法 hash

快速搭建本土「Clubhouse」

anyRTC开发者

ios android WebRTC RTC 语音通话

2021最新总结:阿里/京东/饿了么/拼多多/爱奇艺面经分享(堪称Offer收割机)

比伯

Java 编程 架构 面试 计算机

量化机器人APP开发|量化机器人软件系统开发

系统开发

云算力系统开发|云算力APP软件开发

系统开发

菜单展示的递归与非递归形式实现 (go语言版)

我的腿腿

数据结构和算法

Linux Jenkins 自动打包vue部署到远程window服务器

三爻

Vue jenkins Win

OAtuth2.0 知多少

圣杰

oauth2.0 dotnet

农产品区块链溯源平台,区块链溯源方案

13530558032

为了面试阿里巴巴、腾讯、字节跳动、京东、华为等大厂,我收集了8家大厂高频Java面试真题集锦(含答案)

Java架构之路

Java 程序员 架构 面试 编程语言

读书笔记-MySQL索引

crush

话题讨论 | 你”节后综合症“了吗?

程序员架构进阶

话题讨论 28天写作 2月春节不断更 话题王者 节后焦虑

第二次书摘的微信视频号直播复盘

小匚

用户体验

2021 iOS底层提升计划

iOS底层

从事Java9年,27天熬夜把近年遇到的面试题收录成册全网开源!

程序员小毕

Java spring 程序员 面试 分布式

最值得期待的Python进阶宝典《Effective Python》第2版中文版来咯!

华章IT

Python 代码整洁 Python编程 EffectivePython Python进阶

jenkins Android 自动构建-扫码下载

三爻

LeetCode题解:322. 零钱兑换,动态规划,JavaScript,详细注释

Lee Chen

算法 LeetCode 前端进阶训练营

助力文化荟萃,区块链或可打造“新”春晚?

CECBC区块链专委会

区块链 春晚

产品训练营第五周作业

产品经理训练营

开源微服务运行时 Dapr 发布 1.0 版本

阿里巴巴云原生

开源 容器 微服务 开发者 云原生

危机还是机遇?我靠着这份算法笔记成功拿下字节offer

互联网架构师小马

Java 数据结构 面试 算法 数据结构与算法

读懂框架设计的灵魂—Java反射机制

云流

Java 编程 架构

智慧组工党务解决方案,智慧党建系统

13530558032

做一个很出色的程序员

四猿外

Java 程序员 面试 架构师 职场成长

60K*17薪的面试题是什么样的,需要具备什么技术?首发“Java面试考点大全”

Java架构之路

Java 程序员 架构 面试 编程语言

面试腾讯T3,过关斩将直通3面,终斩获offer流下了激动的泪水(腾讯面经总结分享)

Java架构之路

Java 程序员 架构 面试 编程语言

英特尔On技术创新峰会

英特尔On技术创新峰会

kube-scheduler 源码解析-InfoQ