Kubernetes 是 Google 开源的容器集群管理系统(谷歌内部:Borg),而今天要介绍的 kube-scheduler 是 k8s 系统的核心组件之一,其主要职责就是经过自身的调度算法,为新建立的 Pod 寻找一个最合适的 Node。
主要包含以下几个步骤:node
spec.nodeName
字段。官方流程图以下:git
For given pod: +---------------------------------------------+ | Schedulable nodes: | | | | +--------+ +--------+ +--------+ | | | node 1 | | node 2 | | node 3 | | | +--------+ +--------+ +--------+ | | | +-------------------+-------------------------+ | | v +-------------------+-------------------------+ Pred. filters: node 3 doesn't have enough resource +-------------------+-------------------------+ | | v +-------------------+-------------------------+ | remaining nodes: | | +--------+ +--------+ | | | node 1 | | node 2 | | | +--------+ +--------+ | | | +-------------------+-------------------------+ | | v +-------------------+-------------------------+ Priority function: node 1: p=2 node 2: p=5 +-------------------+-------------------------+ | | v select max{node priority} = node 2
scheduler 的工做看似很简单,但其实否则。考虑的问题很是多,好比要保证每一个节点被公平调度,提升资源利用率,提升 pod 调度效率,提高调度器扩展能力等等。
可涉及的内容很是多,接下来会围绕两个核心步骤对 k8s 的 默认调度策略
深刻了解。github
参考 Kubernetes 版本: v1.12
Predicates 在调度过程当中的做用就是先进行过滤
,过滤掉全部不符合条件的节点后,剩下的全部节点就都是能够运行带调度 Pod。算法
Predicates 的能够分为以下四类:api
具体的 Predicates 默认策略,能够参考: 默认调度策略
当开始调度一个 Pod 的时候,调度器会同时开启多个协程并发的进行 Node Predicates 过滤,最后返回一个能够运行 Pod 的节点列表。每一个协程都是按照固定的顺序进行计算过滤的。缓存
接下来,咱们看下四大类具体运行的调度策略内容。并发
看字面意思就知道 GeneralPredicates 负责的是最基础的调度策略,其包含的具体策略以下:ide
由于 GeneralPredicates 是最基础的调度策略,因此该接口也会被别的组件直接调用,好比 kubelet、daemonSet controller。kubelet 在启动 pod 以前,还会再执行一遍 GeneralPredicates,用于二次确认。函数
不废话就直接列举具体的策略了:命令行
这些规则主要考察待调度的 Pod 是否知足 Node 自己的一些条件。
具体的策略以下:
该规则主要就是 PodAffinityPredicate,用于检查待调度 Pod 与 Node 上已有的 Pod 之间的亲和性和反亲和性关系。
具体的亲和性相关的调度,后面会单独拿一篇文章进行介绍。
完成了前一个阶段的节点 “过滤” 以后,便须要经过 Priorities
为这些节点打分,选择得分最高的节点,做为调度对象。
打分函数不少,总得分能够参考:总分 = (权重1 * 打分函数1) + (权重2 * 打分函数2) + … + (权重n * 打分函数n)
。
每一次打分的范围是 0 — 10 分。10 表示很是合适,0 表示很是不合适。
而且每一个打分函数均可以配置对应的权重值,下面介绍 调度器策略配置
时,也会涉及权重值的配置。默认权重值是 1,若是以为某个打分函数特别重要,即可以加大该权重值。
具体的 Priorities 默认策略能够参考: defaultPriorities 。
Priorities 最经常使用到的一个打分规则是 LeastRequestedPriority
, 该算法用于选出空闲资源(cpu & memory)最多的宿主机。
还有一个常见的是 BalancedResourceAllocation
,该规则主要目的是资源平衡。在全部节点里选择各类资源分配最均衡的节点,避免出现某些节点 CPU 被大量分配,可是 Memory 大量剩余的状况。
此外,还有 InterPodAffinityPriority
、NodeAffinityPriority
、TaintTolerationPriority
,与亲和性与污点调度有关,后面会有单独的文章进行介绍。这里表示节点知足的规则越多,那得分就越高。
在 K8S v1.12 版本还引入了一个调度策略,即 ImageLocalityPriority
。该策略主要目的是优先选择那些已经存有 Pod 所需 image 的节点,能够避免实际运行 Pod 时,再去下载 image。
注意: pod 运行时是否会下载 image,还跟 Pod ImagePullPolicy 配置有关。
能够看到 k8s scheduler 完成一次调度所需的信息很是之多。因此在实际的调度过程当中,大量的信息都事先已经缓存,提升了 Pod 的调度效率。
Kubernetes 调度器有默认的调度策略,具体能够参考 default 。固然用户也能够修改调度策略,能够经过命令行参数 policy-config-file
指定一个 JSON 文件来描述哪些 predicates 和 priorities 在启动 k8s 时被使用, 经过这个参数调度就能使用管理者定义的策略了。
示例以下:
{ "kind" : "Policy", "apiVersion" : "v1", "predicates" : [ {"name" : "PodFitsHostPorts"}, {"name" : "PodFitsResources"}, {"name" : "NoDiskConflict"}, {"name" : "NoVolumeZoneConflict"}, {"name" : "MatchNodeSelector"}, {"name" : "HostName"} ], "priorities" : [ {"name" : "LeastRequestedPriority", "weight" : 1}, {"name" : "BalancedResourceAllocation", "weight" : 1}, {"name" : "ServiceSpreadingPriority", "weight" : 1}, {"name" : "EqualPriority", "weight" : 1} ], "hardPodAffinitySymmetricWeight" : 10, "alwaysCheckAllPredicates" : false }
前面提到了调度器的扩展能力,除了使用 k8s 自带的调度器,你也能够编写本身的调度器。经过修改 Pod 的 spec.schedulername
参数来指定调度器的名字。