kube-scheduler原理介绍及分析

目录

 

kube-scheduler是什么

一句话

两层含义

两个注意

Scheduler调度功能

主要职责

调度节点分配

调度的两个过程

好的调度器考虑的方向

scheduler 调度机制工作原理

框架图

第一个控制循环   Informer Path

第二个控制循环,调度器负责pod调度的主循环scheduling path 

Assume方式API对象更新方式

二次确认 

scheculer设计亮点 

Kubernetes默认调度器调度策略解析

 Predicates

GeneralPredicates

volume相关的过滤规则

宿主机相关的过滤规则

Pod相关的过滤规则

priorities

总结


kube-scheduler是什么

一句话

调度器的指责主要是为新创建的pod在集群中寻找最合适的node,并将pod调度到Node上。

两层含义

  • 从集群所有节点中,根据调度算法挑选出所有可以运行该pod的节点。
  • 再根据调度算法从上述node节点选择最优节点作为最终结果。

Scheduler调度器运行在master节点,它的核心功能是监听apiserver来获取PodSpec.NodeName为空的pod,然后为pod创建一个binding指示pod应该调度到哪个节点上,调度结果写入apiserver。

两个注意

Pod.spec.nodeName用于强制约束将Pod调度到指定的Node节点上,强制匹配。(通过指定nodeName可直接绕过调度器,并不会做任何的资源过滤和检查)

pod.spec.nodeSelector是通过kubernetes的label-selector机制进行节点选择,由scheduler调度策略MatchNodeSelector进行label匹配,调度pod到目标节点,该匹配规则是强制约束。

Scheduler调度功能

主要职责

  1. 集群高可用:如果 kube-scheduler 设置了 leader-elect 选举启动参数,那么会通过 etcd 进行节点选主( kube-scheduler 和 kube-controller-manager 都使用了一主多从的高可用方案)
  2. 调度资源监听:通过 list-Watch 机制监听 kube-apiserver 上资源的变化,这里的资源主要指的是 Pod 和 Node
  3. 调度节点分配:通过预选(Predicates)与优选(Priorites)策略,为待调度的 Pod 分配一个 Node 进行绑定并填充nodeName,同时将分配结果通过 kube-apiserver 写入 etcd。 

调度节点分配

调度节点分配主要可以分为预选(Predicates)与优选(Priorites)这两个环节,上面讲到的调度资源监听的实质就是为这两个环节提供输入。

  • 预选:根据配置的 Predicates Policies(默认为 DefaultProvider 中定义的default predicates policies 集合)过滤掉那些不满足这些 Policies 的 Node,预选的输出作为优选的输入;
  • 优选:根据配置的 Priorities Policies(默认为 DefaultProvider 中定义的 default priorities policies 集合)给预选后的 Node 进行打分排名,得分最高的 Node 即作为最适合的 Node ,该 Pod 就绑定(Bind)到这个 Node 。

注:如果经过优选将 Node 打分排名后,有多个 Node 并列得分最高,那么 kube-scheduler 将随机从中选择一个 Node 作为目标 Node 。

调度的两个过程

 

  • 首先是过滤掉不满足条件的节点这个过程称为predicate
  • 然后对通过的节点按照优先级排序,这个是priorlty
  • 最后从中选择优先级最高的节点

好的调度器考虑的方向

  1. 尽可能地将 工作负载 平均到不同的节点,减少单个节点宕机造成的损失。
  2. 可扩展性。集群规模增大后,保证调度器不会成为性能的瓶颈。
  3. 高可用。调度器能做成集群,任何一个调度器出现问题,不会影响整个集群的调度。
  4. 灵活性。不同的用户会有不同的调度需求,需要考虑用户能够配置不同的调度算法。
  5. 资源合理和高效利用。调度器应该尽可能地提高集群的资源利用率,防止资源浪费。

scheduler 调度机制工作原理

框架图

调度核心:实际上就是两个相互独立的控制循环。 一个是Informer Path循环上list-watch机制和cache机制。 一个是scheduler Path循环上的预选优选机制和绑定回调机制。

第一个控制循环   Informer Path

主要目的启动一系列的Informer,用来监听(list-watch)Etcd 中Pod、Node、Sservice等与调度相关的API对象的变化。 

例:当一个待调度pod(nodename字段为空)被创建,调度器会通过Pod Informer的Handler,将待调度的pod添加进调度队列。

  1. 默认情况,kubernetes调度队列是一个PriorityQueue(优先级队列),并且当某些集群信息发生变化的时候,调度器会对调度队列中的内容进行特殊操作。主要是出于调度优先级和抢占的考虑。
  2. 负责对调度器缓存(scheduler cache)进行更新。Kubernetes调度部分进行性能优化的最根本原则,尽最大可能将集群信息Cache化,提高Predicate和Priority调度算法的执行效率。

第二个控制循环,调度器负责pod调度的主循环scheduling path 

  1. 主要逻辑:不断从调度队列出队Pod,调用Predicates算法进行“过滤”。“过滤”得到一组Node,就是所有可以运行这个Pod的宿主机列表。Predicates算法需要的Node信息,从scheduler cache直接获取,保障算法执行效率。
  2. 调度器会调用Priorities算法为上述列表的Node打分,分数从0-10。得分最高的Node,作为调度的结果。

调度算法执行完成之后,调度器就需要将Pod对象的nodeName字段的值,填充为Node名字。 ====> Bind阶段。

Assume方式API对象更新方式

为了不在关键调度路径里远程访问APIServer,k8s默认调度器在Bind阶段,只会更新Scheduler Cache里的Pod和Node信息。基于“乐观”假设的API对象更新方式,称作Assume。

Assume之后,调度器会创建Goroutinue来异步向APIServer发起更新pod的请求,来真正完成Bind操作。如果异步Bind过程失败了,其实也没有多大关系,等scheduler cache同步之后就会恢复正常。

二次确认 

正是由于kubernetes调度器的“乐观”绑定设计,当一个新的pod完成调度需要在某个节点运行起来之前,该节点的kubelet执行Admit操作再次验证该Pod是否确实能够运行在该节点上。实际上就是把一组 叫做“GeneralPredicates”的最基本调度算法作为二次确认。

scheculer设计亮点 

  1. Scheduler Cache化。将集群中的pod、node、service等根调度相关的对象信息cache化,并通过list-watch机制 根据API对象的变化去更新相应的缓存信息。提高算法的执行效率。
  2. 乐观绑定。避免远程访问APIServer
  3. 无锁化。在scheduler path上,调度器会启动多个Goroutinue以节点为粒度并发执行Predicates算法,提高执行效率。Priorities算法也会以MapReduce方式并行计算然后再进行汇总。需要并发的路径上,调度器会避免设置任何全局的竞争资源,从而避免使用锁进行同步带来的巨大性能损耗。
  4. 加锁:调度队列和scheduler cache操作。都不在 Scheduling Path 的算法执行路径上。

Kubernetes默认调度器调度策略解析

Predicates和Priorities两个调度策略主要发生作用的阶段。

 Predicates

Fliter过滤器,即:按照调度策略,从当前集群的所有节点中,“过滤”出一系列符合条件的节点。待调度Pod的宿主机。

GeneralPredicates

负责的是最基础的调度策略。

  • PodFitsResource 计算的就是宿主机的CPU和内存资源是否够用。检查的是pod的requests字段。Kubernetes 的调度器并没有为 GPU 等硬件资源定义具体的资源类型,而是统一用一种名叫Extended Resource的、key-value格式的扩展字段来描述的。
  • PodFitsHost,宿主机名字是否和 pod的spec.nodeName一致。
  • PodFitsHostPorts pod申请的宿主机端口 spec.nodePort 是不是跟已经使用的端口冲突。
  • PodMatchNodeSelector  pod的 nodeselector 或者 nodeAffinity 指定的节点,是否与待调度的节点label信息匹配。

上面的正是考察一个pod能否运行在一个node上的最基本过滤条件。 Kubelet启动pod前,会执行一个Admit操作二次确认。

volume相关的过滤规则

负责跟容器持久化volume相关的调度策略。

  • NoDiskConflict检查的条件,是判断备选pod的getPersistentDisk或AWS EBS类型和备选节点中已存在的Pod是否冲突。AWS EBS类型的volume是不允许被两个pod同时使用的。(pod.spec.volumes)
  • MaxPDVolumeCountPredicate:一个节点上某种类型的持久化volume是不是已经超过了一定数目,如果是的话,那么声明使用该类型持久化volume的pod就不能再调度到这个节点上了。
  • VolumeZonePredicate检查持久化volume的Zone 高可用域 标签,是否与待调度节点的zone标签相匹配。
  • VolumeBindingPredicate 检查的是 该pod对应PV的 nodeAffinity字段是否跟某个节点的标签相匹配。
  • Local Persistent Volume 本地持久化卷,必须使用nodeAffinity来跟某个具体的节点绑定。根据pod的volume属性进行调度。

宿主机相关的过滤规则

主要考察待调度pod是否满足node本身的某些条件。

  • PodToleratesNodeTaints,负责检查的就是Node的 污点 机制。
  • NodeMemoryPressurePredicate 检查当前节点内存是不是已经不够充足。

Pod相关的过滤规则

  • podAffinityPredicate 检验待调度的pod与Node上已有pod之间的亲和性和反亲和性。
  • podAntiAffinity 规则,就指定了这个 Pod不希望跟任何携带了 x=y 标签的 Pod存在于同一个node上。
  • podaffinitypredicate是有作用域的,仅对携带key是kubernetes.io/hostname标签的 Node有效。 正是topologyKey的作用。
  • podAffinity亲和性:Pod,就只会被调度到已经有携带了 x=y 标签的 Pod 运行的 Node 上。而这条规则的作用域则是所有携带Key是failure-domain.beta.kubernetes.io/zone的Node。、
  • requiredDuringSchedulingIgnoredDuringExecution字段含义:这条规则必须在pod调度时进行检查(requiredDuringScheduling);如果是已经运行的Pod发生变化,label修改,造成该pod不再适合运行在这个Node上的时候,kubernetes不会主动修改(IgnoredDuringExecution)。

上面四种类型predicates,构成调度器确定一个Node可以运行待调度Pod的基本策略。

注意:具体执行的时候,当开始调度一个pod时,kubernetes调度器会同时启动16个Goroutine并发的为集群里的所有Node计算Predicates,最后返回这个pod的宿主机列表。(宿主机相关的predicates会放在相对靠前的位置检查)

priorities

宿主机之间资源利用率均衡,最适合运行的node。节点打分阶段,得分最高的就是pod绑定的最佳节点。

  • LeastRequestedPriority:从备选节点列表选出资源消耗最小的节点。选择空闲资源最多的宿主机。

score = (cpu((capacity-sum(requested))10/capacity) + memory((capacity-sum(requested))10/capacity))/2

  • BalancedResourceAllocation:调度完成后,资源分配最均衡的节点。避免一个节点上CPU被大量分配而mem大量剩余的情况。

score = 10 - variance(cpuFraction,memoryFraction,volumeFraction)*10

每种资源的Fraction的定义是:Pod请求的资源/节点上的可用资源。而variance算法的作用,则是计算每两种资源Fraction之间的“距离”。最后选择资源Fraction差距最小的节点。 

  • NodeAffinityPriority、TaintTolerationPriority和InterPodAffinityPriority三种priority。一个node满足上述规则的字段数目越多,得分越高。
  • ImageLocalityPriority策略,待调度pod使用的镜像很大,并且已经存在于某些Node上,得分会比较高。              可以通过为 Priorities 设置权重,来控制调度器的调度行为。

总结

本文主要介绍调度器的调度功能、设计原理和调度算法,帮助读者加深对调度器的整体认识。后续会对调度器的源码进行详细分析。

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值