调度器和控制器

调度控制器

kube-scheduler 介绍

1697463931646

  • Qos: 怎么保证质量;

    kube-schedule 的两阶段

1697466501972

Predicated 策略

检查与过滤plugin

1697466520935

1697546895328

PRedicated plugin 工作原理

层层过滤

1697546981255

Priorities 策略

打分阶段的评分标准(Priorities)有7项:LeastRequestedPriority, BalancedResourceAllocation、SelectorSpreadPriority、NodeAffinityPriority、EqualPriority、ServiceSpreadingPriority和Image-LocalityPriority。每一项都对应一个范围是。0-10的分数,0代表最低优先级,10代表最高优先级。除了单项分数,每一项还需要再分配一个权值(weight )。

以default算法为例,它包含了LeastRequestedPriority, BalancedResourceAllocation, SelectorSpreadPriority和NodeAffmityPriority这三项,每一项的权值均为1。

所以一个工作节点最终的优先级得分是每个Priorities计算得分的加权和,即Sum(score*weight)。最终,scheduler调度器会选择优先级得分最高的那个工作节点作为pod调度的目的地,如果存在多个优先级得分相同的工作节点,则随机选取一个工作节点。

1697547021088

1697547251016

调度过程模拟

开始

将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

    可以看到,这个算法实际上就是在选择空闲资源(CPU 和 Memory)最多的宿主机。

  2. 用公式计算房间(Node)的基本配备设施使用率最均衡的分数

    BalancedResourceAllocation算法
    公式:score = 10 - variance(cpuFraction,memoryFraction,volumeFraction)*10
    每种资源的 Fraction 的定义是 :Pod 请求的资源 / 节点上的可用资源

    而 variance 算法的作用,则是计算每两种资源 Fraction 之间的“距离”。而最后选择的,则是资源 Fraction 差距最小的节点。

    所以说,BalancedResourceAllocation 选择的,其实是调度完成后,所有节点里各种资源分配最均衡的那个节点,从而避免一个节点上 CPU 被大量分配、而 Memory 大量剩余的情况。

  3. 此外还会有计算 房间(Node)与你要求的符合度分数(NodeAffinityPriority)、房间(Node)瑕疵与你可容受的符合度分数(TaintTolerationPriority)、房间(Node)里的人员与你共处的符合度分数(InterPodAffintityPriority)

    以上三个计算跟选出房间(Node)列表的规则(PodMatchNodeSelector、PodToleratesNodeTaints 和 PodAffinityPredicate)类似,但是作为符合度,规则符合的越多分数就越高

  4. 特殊的配备:如果你要的电脑(image镜像)在哪些房间(Node)里已经布置好了,那房间(Node)的分数就会比较高(ImageLocalityPriority)

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

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

Pod 的资源需求

LimitRange 对象

作用

1697548071578

如果pod资源未指定limit、request 等限制对象, 会使用上述限制;

也可以限制pod资源的上限

示例-提供默认限制

1697548754225

磁盘资源限制

1697549192219

init Container 的资源需求

1697549269170

如何把Pod 调度到指定的Node上

1697549389781

通过Node亲和性选择节点

相较于使用nodeSlector, 更具有普遍性和扩展性

1697550229461

通过Pod亲和性选择节点

1697550886708

示例

1697550931023

Taints 和 Tolerations

用来标记Node, 保证Pod不被调度到打了标的node上

1697551524292

示例

1
2
3
4
# 通过kubectl taint为node添加taint,如:
kubectl taint nodes k8s-node1 key=value:NoSchedule
# 删除taint
kubectl taint nodes k8s-node1 key=value:NoSchedule-

为node节点 k8s-node1增加一条taint(污点)。Taint(污点)的关键字为key,值为value,taint(污点)影响NoSchedule。意味着如果pod没有设置容忍该污点,pod将不会被调度到k8s-node1上,除非Pod它有设置匹配的toleration(容忍度)。

1
2
3
4
5
6
#可以为pod指定toleration(容忍度)。以下的两种toleration(容忍度)都与上文中创建的taint(污点)匹配,因此这个pod有可能被调试到k8s-node1上。
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"

通过taint 实现多租户

1697552495688

优先级调度

1697552751096

使用方式

  1. 定义PriorityClass

    1697552782075

  2. 建立pod 的时候关联ProrityClass

    高优先级的pod可以优先被调度, 也可以抢占其他pod资源

    1697552893274

多调度器

pod在调度的时候, 不指定的时候默认使用默认调度器。

基本调度器是one by one 的方式进行pod调度的, 如何需要并发调度, 或者批处理的调度器, 需要使用其他的增强调度器。

1697585744002

生产集群调度经验

1697585990665

kube-controller 控制器

控制器工作流程

1697588124842

  • informer: 监听某个api对象, 所有对象的变更事件会发送到informer
  • Lister:会维护一个Cache, apiserver的所有对象, 都会再Lister有一份本地缓存,worker通过Lister获取对象的状态;

控制器协同工作原理

1697588450971

通用的Controller

kube-controller-manager 默认开启控制器(部分 )

1697588489070

1697590776053

刘小恺(Kyle) wechat
如有疑问可联系博主