调度控制器
kube-scheduler 介绍
Predicated 策略
检查与过滤plugin
PRedicated plugin 工作原理
层层过滤
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调度的目的地,如果存在多个优先级得分相同的工作节点,则随机选取一个工作节点。
调度过程模拟
开始
将K8S当成一个旅社,旅社有很多的房间(Node),房间(Node)有相应的基础配套设施可以用(CPU、GPU、内存等资源)
这时你(Pod)想要住在旅社(K8S)
旅社(K8S)的旅社主管(默认调度器Controller)就会对你(Pod)的请求进行审核(Predicates + Priortiy)
审核过程(Predicates + Priortiy)
一、初筛房间(Node)列表(Predicates)
首先旅社主管(Controller)将会按以下规则(SchedulerRule)进行过滤筛选(Filter)出符合你要求的现在的房间(Node) -> (Predicates)
检查哪些房间(Node)符合你(Pod)的入住基本需求(GeneralPredicates)
检查房间(Node)里的当前可用的配套设施(CPU、GPU、内存等资源)是否符合你的要求
PodFitsResources算法
检查房间(Node)的房号(NodeName)是否符合你(Pod)要求的指定的房号(spec.nodeName),如果没指定就不判定
PodFitsHost算法
检查房间(Node)里的窗口位置是否符合你(Pod)要求的位置(spec.nodePort),如果没有指定就不判定
PodFitsHostPort算法
检查房间(Node)的位置、装修等是否符合你的要求(NodeSelector或NodeAffinity
PodMatchNodeSelector算法
检查哪些房间(Node)还能放你想配备的储物箱(Volume) (VolumePredicates)
检查想要配备的储物箱(Volume)是否已经被在房间(Node)里的其他人(Pod)使用中了
NoDiskConfict算法
检查想要配备的储物箱(Volume)的牌子(类型)是否在房间(Node)里面已经被烂大街了
MaxPDVolumeCountPredicate算法
检查想要配备的储物箱(Volume)是不是跟房间(Node)同属于一个区域(Zone)
VolumeZonePredicate算法
检查想要配备的储物箱(Volume)是不是符合你想要放置的房间(Node)里
VolumeBindingPredicate算法
你想要用房间(Node)里面的已经配备的储物箱(Local Persistent Volume)的话,就必须要先在要求(nodeAffinity)中指定好,这样好给你分配相应的房间(Node)
检查哪些房间(Node)能真的给你入住
检查房间(Node)的瑕疵(Taint)是否你(Pod)能忍受
PodToleratesNodeTaints算法
这里要求你需在要求清单里面写上可忍受的瑕疵(Toleration)检查房间(Node)的入住体验是否已经很差
NodeMemoryPressurePredicate算法
如果已经很差了,肯定就不想住这个房间(Node)了
检查哪些房间(Node)里有哪类人、哪个人(Pod)你不想跟TA住的(anti-affinity),或者房间(Node)里应该有哪类人、哪个人(Pod)你想跟TA住的(affinity)
这里会在旅社主管(Controller)给你安排房间(Node)的时候进行调配,如果你已经入住了,里面有人突然变成你不想要住的那类人时,你还是得继续住
IngoredDuringExecution
通过以上4个检查流程对每个房间(Node)进行检查,基本可以确定哪个房间(Node)可以给你入住
这个过程负责的旅社主管(Controller)会吩咐16个其他下属(派生Goroutine)一起检查,然后得到你可以入住的房间(Node)列表(Nodes)
二、对房间(Node)评分(Priorities)
在得到房间(Node)列表后,现在得在这里选个最好的房间(Node)给你入住,所以接下来将会用以下规则给房间(Node)打分(0-10)(Priorities)
用公式计算 房间(Node)的最低基本配备设施使用率(CPU、内存)的分数
LeastRequestedPriority算法
公式:score = (cpu((capacity-sum(requested))10/capacity) + memory((capacity-sum(requested))10/capacity))/2可以看到,这个算法实际上就是在选择空闲资源(CPU 和 Memory)最多的宿主机。
用公式计算房间(Node)的基本配备设施使用率最均衡的分数
BalancedResourceAllocation算法
公式:score = 10 - variance(cpuFraction,memoryFraction,volumeFraction)*10
每种资源的 Fraction 的定义是 :Pod 请求的资源 / 节点上的可用资源而 variance 算法的作用,则是计算每两种资源 Fraction 之间的“距离”。而最后选择的,则是资源 Fraction 差距最小的节点。
所以说,BalancedResourceAllocation 选择的,其实是调度完成后,所有节点里各种资源分配最均衡的那个节点,从而避免一个节点上 CPU 被大量分配、而 Memory 大量剩余的情况。
此外还会有计算 房间(Node)与你要求的符合度分数(NodeAffinityPriority)、房间(Node)瑕疵与你可容受的符合度分数(TaintTolerationPriority)、房间(Node)里的人员与你共处的符合度分数(InterPodAffintityPriority)
以上三个计算跟选出房间(Node)列表的规则(PodMatchNodeSelector、PodToleratesNodeTaints 和 PodAffinityPredicate)类似,但是作为符合度,规则符合的越多分数就越高
特殊的配备:如果你要的电脑(image镜像)在哪些房间(Node)里已经布置好了,那房间(Node)的分数就会比较高(ImageLocalityPriority)
如果房间(Node)里配备的电脑是少数的时候,会适当的调低这些房间(Node)的优先级,因为房间(Node)里可以住很多人的,这样可以避免人员挤在一起(堆叠的风险)
通过上述的过程,这里就会得到所有房间(Node)的分数,而其中最高分的房间(Node)就是你该入住的房间(Node),完成了房间(Node)的分配问题。
Pod 的资源需求
LimitRange 对象
作用
如果pod资源未指定limit、request 等限制对象, 会使用上述限制;
也可以限制pod资源的上限
示例-提供默认限制
磁盘资源限制
init Container 的资源需求
如何把Pod 调度到指定的Node上
通过Node亲和性选择节点
相较于使用nodeSlector, 更具有普遍性和扩展性
通过Pod亲和性选择节点
示例
Taints 和 Tolerations
用来标记Node, 保证Pod不被调度到打了标的node上
示例
1 | 通过kubectl taint为node添加taint,如: |
为node节点 k8s-node1增加一条taint(污点)。Taint(污点)的关键字为key,值为value,taint(污点)影响NoSchedule。意味着如果pod没有设置容忍该污点,pod将不会被调度到k8s-node1上,除非Pod它有设置匹配的toleration(容忍度)。
1 | #可以为pod指定toleration(容忍度)。以下的两种toleration(容忍度)都与上文中创建的taint(污点)匹配,因此这个pod有可能被调试到k8s-node1上。 |
通过taint 实现多租户
优先级调度
使用方式
定义PriorityClass
建立pod 的时候关联ProrityClass
高优先级的pod可以优先被调度, 也可以抢占其他pod资源
多调度器
pod在调度的时候, 不指定的时候默认使用默认调度器。
基本调度器是one by one 的方式进行pod调度的, 如何需要并发调度, 或者批处理的调度器, 需要使用其他的增强调度器。
生产集群调度经验
kube-controller 控制器
控制器工作流程
- informer: 监听某个api对象, 所有对象的变更事件会发送到informer
- Lister:会维护一个Cache, apiserver的所有对象, 都会再Lister有一份本地缓存,worker通过Lister获取对象的状态;
控制器协同工作原理
通用的Controller
kube-controller-manager 默认开启控制器(部分 )