3

前言

近期在学习极客时间的张磊老师-深入剖析Kubernetes课程42、43讲内容的调度策略、优先级、抢占机制三个知识点的时候,发现自己理解和记忆比较浅薄。

试图使用第三视角去观看,模拟整个过程,降低理解复杂度,体验其中设计之美,以下为模拟过程记录

对象映射列表

K8s对象 模拟对象
K8s系统 旅社
Node 房间
Pod 人员
Controller 旅社主管
PriorityAdmissionController 前台小姐
派生Goroutine 下属
CPU、GPU、内存等资源 配套设施
Volume 储物箱
Taint 瑕疵

模拟过程

开始

将K8S当成一个旅社,旅社有很多的房间(Node),房间(Node)有相应的基础配套设施可以用(CPU、GPU、内存等资源)
这时你(Pod)想要住在旅社(K8S)
旅社(K8S)的旅社主管(默认调度器Controller)就会对你(Pod)的请求进行审核(Predicates + Priortiy)

审核过程(Predicates + Priortiy)

初筛房间(Node)列表(Predicates)

首先旅社主管(Controller)将会按以下规则(SchedulerRule)进行过滤筛选(Filter)出符合你要求的现在的房间(Node) -> (Predicates)

  1. 检查哪些房间(Node)符合你(Pod)的入住基本需求(GeneralPredicates)

    1. 检查房间(Node)里的当前可用的配套设施(CPU、GPU、内存等资源)是否符合你的要求

      PodFitsResources算法
    2. 检查房间(Node)的房号(NodeName)是否符合你(Pod)要求的指定的房号(spec.nodeName),如果没指定就不判定

      PodFitsHost算法
    3. 检查房间(Node)里的窗口位置是否符合你(Pod)要求的位置(spec.nodePort),如果没有指定就不判定

      PodFitsHostPort算法
    4. 检查房间(Node)的位置、装修等是否符合你的要求(NodeSelector或NodeAffinity

      PodMatchNodeSelector算法
  2. 检查哪些房间(Node)还能放你想配备的储物箱(Volume) (VolumePredicates)

    1. 检查想要配备的储物箱(Volume)是否已经被在房间(Node)里的其他人(Pod)使用中了

      NoDiskConfict算法
    2. 检查想要配备的储物箱(Volume)的牌子(类型)是否在房间(Node)里面已经被烂大街了

      MaxPDVolumeCountPredicate算法
    3. 检查想要配备的储物箱(Volume)是不是跟房间(Node)同属于一个区域(Zone)

      VolumeZonePredicate算法
    4. 检查想要配备的储物箱(Volume)是不是符合你想要放置的房间(Node)里

      VolumeBindingPredicate算法
      你想要用房间(Node)里面的已经配备的储物箱(Local Persistent Volume)的话,就必须要先在要求(nodeAffinity)中指定好,这样好给你分配相应的房间(Node)
  3. 检查哪些房间(Node)能真的给你入住

    1. 检查房间(Node)的瑕疵(Taint)是否你(Pod)能忍受

      PodToleratesNodeTaints算法
      这里要求你需在要求清单里面写上可忍受的瑕疵(Toleration)
    2. 检查房间(Node)的入住体验是否已经很差

      NodeMemoryPressurePredicate算法
      如果已经很差了,肯定就不想住这个房间(Node)了
  4. 检查哪些房间(Node)里有哪类人、哪个人(Pod)你不想跟TA住的(anti-affinity),或者房间(Node)里应该有哪类人、哪个人(Pod)你想跟TA住的(affinity)

    1. 这里会在旅社主管(Controller)给你安排房间(Node)的时候进行调配,如果你已经入住了,里面有人突然变成你不想要住的那类人时,你还是得继续住

      IngoredDuringExecution

通过以上4个检查流程对每个房间(Node)进行检查,基本可以确定哪个房间(Node)可以给你入住

这个过程负责的旅社主管(Controller)会吩咐16个其他下属(派生Goroutine)一起检查,然后得到你可以入住的房间(Node)列表(Nodes)

对房间(Node)评分(Priorities)

在得到房间(Node)列表后,现在得在这里选个最好的房间(Node)给你入住,所以接下来将会用以下规则给房间(Node)打分(0-10)(Priorities)

  1. 用公式计算 房间(Node)的最低基本配备设施使用率(CPU、内存)的分数

    LeastRequestedPriority算法
    公式:score = (cpu((capacity-sum(requested))10/capacity) + memory((capacity-sum(requested))10/capacity))/2
  2. 用公式计算房间(Node)的基本配备设施使用率最均衡的分数

    BalancedResourceAllocation算法
    公式:score = 10 - variance(cpuFraction,memoryFraction,volumeFraction)*10
    每种资源的 Fraction 的定义是 :Pod 请求的资源 / 节点上的可用资源
  3. 此外还会有计算 房间(Node)与你要求的符合度分数(NodeAffinityPriority)、房间(Node)瑕疵与你可容受的符合度分数(TaintTolerationPriority)、房间(Node)里的人员与你共处的符合度分数(InterPodAffintityPriority)

    以上三个计算跟选出房间(Node)列表的规则(PodMatchNodeSelector、PodToleratesNodeTaints 和 PodAffinityPredicate)类似,但是作为符合度,规则符合的越多分数就越高
  4. 特殊的配备:如果你要的电脑(image镜像)在哪些房间(Node)里已经布置好了,那房间(Node)的分数就会比较高(ImageLocalityPriority)

    如果房间(Node)里配备的电脑是少数的时候,会适当的调低这些房间(Node)的优先级,因为房间(Node)里可以住很多人的,这样可以避免人员挤在一起(堆叠的风险)

通过上述的过程,这里就会得到所有房间(Node)的分数,而其中最高分的房间(Node)就是你该入住的房间(Node),完成了房间(Node)的分配问题。

关于效率损耗

关于这个旅社主管(Controller)执行效率(调度计算效率),房间(Node)的信息都会先把信息整理好存放到可以快速拿得到的地方比如电脑的Excel(内存),然后再进行计算,总体来说还是挺快。

处理人员入住失败(优先级【Priority】和抢占【Preemption】机制)

在上述中过程其实就是分配房间(Node)的过程,当然这里的结果也会有房间(Node)的分配不到的问题。
那如果分配不到你该怎么办?这时候你只能等旅社主管(Controller)处理了。

这里就涉及到另外一个机制:优先级(Priority)和抢占(Preemption)机制
就是用于解决的是Pod调度失败时该怎么办的问题

优先入住问题(优先级【Priority】)

这时候的旅社主管(Controller)就解决 ”怎么多人谁可以优先入住” 这个问题
a. 为什么要“优先入住”?

因为这里人员其实有会员等级的区分,旅社主管(Controller)想要尽可能是满足会员等级高的人先去入住,从而提升旅社的声誉和收益,毕竟会员等级低的人对旅社没什么太大的影响,让他们体验差点、延迟入住也可以。

而这时候的旅社主管(Controller)接下来就会想尽办法让会员等级高的入住,这里可能会有让会员等级低搬到其他房间(Node)去住、或者直接先将他们请出房间(Node)(有点狠)

b. 如何优先入住?
会员卡(PriorityClass)
  1. 现在你也想要优先入住,怎么办?

    • 你首先先要有个旅社(K8S)里设定的会员卡(PriorityClass)证明你的会员等级(优先级)
    优先级是一个32bit的整数,最大值不超过10亿,值越大优先级越高
  2. 如果没有会员卡?

    • 你的会员等级就是旅社中设定的默认等级,
    如果有globalDefault为true的PriorityClass就是这个优先级,否则就是0
c. 高等级会员权益(抢占【Preemption】)
  1. 当你(Pod)申请入住的时候前台小姐(PriorityAdmissionController)就会在你(Pod)的信息(spec.priority)里面附加上会员等级
  2. 假设你(Pod)的是高等级会员,而你现在无法入住
  3. 旅社主管(Controller)发现你现在没法入住,接下来这个旅社主管(Controller)就想办法会让你优先入住(抢占能力触发)
  4. 旅社主管(Controller)将在所有房间(Node)里找出一个房间(Node),让房间(Node)里面的低会员等级的搬出来,然后将这个房间(Node)号附加在你(Pod)的申请信息(spec.nominatedNodeName)中

    这时候Pod就是“抢占者”(Preemptor)
  5. 等待入住(等待下次调度)

    经过旅社主管(Controller)的一顿操作,你(Pod)还没真正入住房间(Node)你需要等待下次旅社主管(Controller)分配才能入住

    • 为什么?

      1. 需要等待旅社主管(Controller)先处理好低会员等级的人

        通过DeleteAPI删除被抢占的Pod,其会有30秒优雅退出时间
      2. 等待这段期间内其他房间(Node)或者有新房间(Node)也有可能变得更适合你入住的。
  6. 入住危机感(更高等级抢占发动)

    • 其实你(Pod)还不能放心,在等待过程中如果有比你会员等级高的人要来入住
    • 这时旅社主管(Controller)可能把你(Pod)原先已经分配到的房间分给他(Pod),然后你就又要重新等待抢房间(Node)了
    Pod的spec.nominatedNodeName清空,将重新调度分配
d. 旅社主管(Controller)的猛虎操作(抢占过程)
  1. 人员(Pod)房间(Node)分配情况归纳分组

    旅社主管(Controller)有两份名单列表,一条处理入住失败名单列表(unschedulableQ)、还有一条处理等待入住名单列表(activeQ)

    • 当你(Pod)申请入住时就会,旅社主管(Controller)就会把你申请信息放到等待入住名单列表(activeQ),然后旅社主管(Controller)会处理,为你分配房间(Node)
    • 当你(Pod)分配不到房间(Node)时,旅社主管(Controller)就会把你放到入住失败名单列表,然后旅社主管(Controller)会想办法给你分配房间(Node),分配到则将你放进等待入住名单列表(activeQ),否则就继续等
  2. 想办法给你(Pod)分配房间(Node)的过程

    其实就是把低会员等级人员(牺牲者)的请出来腾出房间(Node)
    1. 首先旅社主管(Controller)会考虑你(Pod)入住失败的原因,毕竟可能是你无理取闹,要求太高,现在根本没有符合你要求的房间(Node)

      1. PodFitHost算法中nodeSelector的名字没有匹配到
    2. 如果旅社主管(Controller)确定你(Pod)是可以入住的,会把当前所有的房间(Node)信息整理(复制一份),然后模拟给你(Pod)分配房间(Node)过程如下

      1. 会检查每个房间(Node)
      2. 将从房间(Node)里会员等级最低的开始,逐一请出去
      3. 每请一个出去就看你能不能分配到这个房间(Node)
      4. 如果可以就记录房间(Node)信息和对应要请出去的人员列表(Pods)
      5. 全部房间(Node)都检查完之后,选择里面要清退人数越少越好、清退的人员的会员等级越低越好,尽量减少对整个旅社(K8S)的影响
  3. 做完上述过程,旅社主管(Controller)就动真格开始操作

    1. 按照请出去人员(Pod)列表,将这些人员的房间(Node)号(nomiantedNodeName)设置为空
    2. 把预先算好的房间(Node)号(NodeName)分配给你(nomiantedNodeName)
    3. 安排一个下属(goroutine)去将需要请出去的人员,一个个请出来

以上的过程做完,应该是能入住房间(Node)了,不行的话只能再由旅社主管(Controller)再猛虎操作了

e. 旅社主管(Controller)的分配特殊情况处理

其实这里还需要注意,因为有这个抢房间(Node)过程的存在,是需要处理一些特殊情况

比如有个人申请入住,旅社主管(Controller)在对他进行分配房间(Node)的时候,在检查你(Pod)刚才分配的房间(Node),也会把你考虑进去

所以旅社主管(Controller)会进行以下两种情况进行分析判断

  1. 你在里面的时候,他会不会不要这个房间(Node),因为他可能不想跟你一起住(InterPodAntiAffinity)(Predicates)
  2. 不考虑你在里面的时候,他会不会在这个房间(Node)里面住(Predicates)
两次Predicates

模拟结束

以上就是通过你想住进旅社时的情景下,快速理解K8s调度策略、优先级、抢占机制流程。

想详细了解的话可以关注极客时间的张磊老师-深入剖析Kubernetes课程42、43讲内容


EdwardQ
36 声望14 粉丝

低调的运维研发Golang 工程师


引用和评论

0 条评论