调度器就是一个独立的进程,负责不断从apiserver拉取尚未被调度的pod,以及可调度的node列表,经过一些列算法筛选,选出一个node并与该pod绑定,将绑定的结果写回apiservernode
下面讲解基于k8s v1.6.6的源码git
算法须要通过两个阶段,分别是过滤和打分,首先过滤掉一部分,保证剩余的节点都是可调度的,接着在打分阶段选出最高分节点,该节点就是scheduler的输出节点。github
算法流程:算法
过滤环节就是一条过滤器链,包含多个过滤器,每一个至关于一个函数,接收node和待调度的pod做为参数,返回bool来肯定是否可调度。经过组合多个函数能够完成一条可扩展的过滤器链。目前k8s中已注册的过滤器函数以下:api
算法名称 | 是否默认 | 详细说明 |
---|---|---|
NoVolumeZoneConflict | 是 | 当主机上zone-label(地区)包含pod中PersistentVolume卷下的zone label时,能够调度。当主机没有zone-label,表示没有没有zone限制,也可调度 |
MaxEBSVolumeCount | 是 | 当主机上被挂载的AWS EBS Volume超过了默认限制39,就不调度到该主机 |
MaxGCEPDVolumeCount | 是 | 当主机上被挂载的GCD Persistent Disk超过了默认限制16,就不调度到该机器 |
MaxAzureDiskVolumeCount | 是 | 当主机上被挂载的Azure Disk Volume超过了默认限制16,就不调度到该机器 |
NoDiskConflict | 是 | 当主机上全部pod使用的卷和待调度pod使用的卷存在冲突,就不调度到该主机。这项检查只针对GCE, Amazon EBS, Ceph RBD, ISCSI,具体规则为:函数
|
MatchInterPodAffinity | 是 | 亲和性检查,设带调度的pod为X,当主机上全部正运行的pod与X不相互排斥时,则可调度 |
PodToleratesNodeTaints | 是 | 当pod能够容忍(tolerate)主机全部的taint(污点)时,才可被调度(容忍taint标签的方式就是给本身也打上相应tolerations标签) |
CheckNodeMemoryPressure | 是 | 当主机剩余内存紧张时,BestEffort类型的pod没法被调度到该主机 |
CheckNodeDiskPressure | 是 | 当主机剩余磁盘空间紧张时,没法调度到该主机 |
PodFitsHostPorts | 是 | 当待调度pod中全部容器所用到的HostPort与工做节点上已使用端口存在冲突,就不调度到该主机 |
PodFitsPorts | 是 | 被PodFitsHostPorts取代 |
PodFitsResources | 是 | 当总资源-主机中全部pod对资源的request总量 < 带调度的pod request资源量,则不调度到该主机,如今会检查CPU,MEM,GPU资源 |
HostName | 是 | 若是待调度的pod指定了pod.Spec.Host,则调度到该主机上 |
MatchNodeSelector | 是 | 当主机label与pod中nodeSelector以及annotations scheduler.alpha.kubernetes.io/affinity匹配,则可调度 |
打分环节也是一条链路,包含多个打分函数,每一个打分函数会接收node和待调度的pod做为参数,返回一个范围在0-10的分数,每一个打分函数还有一个权重值。某个node算出的总分就是全部打分函数的分值*权重值的总和,获取总分最大的node(若是有多个,随机取一个),该node就是最终要被调度的节点spa
示例:假设有个节点nodeA,有两个打分函数priorityFunc一、priorityFunc2(每一个方法都能返回一个score),两个方法分别都有权重因子weight一、weight2。则nodeA的总分为:finalScoreNodeA = (weight1 * priorityFunc1) + (weight2 * priorityFunc2)server
目前k8s中已注册的打分函数以下:进程
算法名称 | 是否默认 | 权重 | 详细说明 |
---|---|---|---|
SelectorSpreadPriority | 是 | 1 | 相同service/rc的pods越分散,得分越高 |
ServiceSpreadingPriority | 否 | 1 | 相同service的pods越分散,优得分越高,被SelectorSpreadPriority取代,保留在系统中,并不使用 |
InterPodAffinityPriority | 是 | 1 | pod与node上正运行的其余pod亲和性匹配度越高,得分越高 |
LeastRequestedPriority | 是 | 1 | 剩余资源越多,得分越高。cpu((capacity - sum(requested)) * 10 / capacity) + memory((capacity - sum(requested)) * 10 / capacity) / 2 |
BalancedResourceAllocation | 是 | 1 | cpu和内存利用率越接近,得分越高。10 - abs(cpuFraction-memoryFraction)*10 |
NodePreferAvoidPodsPriority | 是 | 10000 | 当node的annotation scheduler.alpha.kubernetes.io/preferAvoidPods被设置时,说明该node不但愿被调度,得分低,当没有设置时得分高。之因此权重较大是由于一旦设置preferAvoidPods表示该node不但愿被调度,该项得分为0,其余没有设置的node得分均为10000*分值,至关于直接过滤掉该节点。思考:其实能够放在过滤环节处理 |
NodeAffinityPriority | 是 | 1 | pod与node的亲和性匹配度越高,得分越高 |
TaintTolerationPriority | 是 | 1 | pod对node的污点(taint)的容忍(tolerate)程度越高,得分越高 |
EqualPriority | 否 | 1 | 全部机器得分同样 |
ImageLocalityPriority | 否 | 1 | 待调度的pod会使用到一些镜像,拥有这些镜像越多的节点,得分越高 |
MostRequestedPriority | 否 | 1 | request资源越多,得分越高,与LeastRequestedPriority相反。(cpu(10 * sum(requested) / capacity) + memory(10 * sum(requested) / capacity)) / 2 |