热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

13.调度器、预选策略及优选函数、高级调度方式

参见:调度器、预选策略与优选函数 https:www.cnblogs.comweiyiming007p10560518.html一、前言master上运行着三个最核心的组件,api

参见:调度器、预选策略与优选函数 https://www.cnblogs.com/weiyiming007/p/10560518.html


一、前言

master上运行着三个最核心的组件,apiserver、scheduler、controller manager。此外,master还依赖于ectd存储节点,最好ectd是有冗余能力的集群。


1、调度器(scheduler)

master上的scheduler控制着pod运行在哪个node上,默认用的default-scheduler(用describe时详情里可以看到用的哪个调度器);

调度器的调度信息存储在master上的etcd里面,apiserver负责和etcd通信;

kubelet运行在node节点上,监控着Node节点上的pod状态,并参与pod的创建等工作;

kube-proxy也运行在node节点上,它监控着service资源的变动, 然后将其在当前节点上创建为iptables或ipvs规则。Kube-proxy是管理service的组件;

kubelet和kube-proxy都要连接master上的apiserver去获取定义信息;


2、调度过程

预选策略(predicate):先排除那些完全不符合此pod运行法则的节点,有两个维度来排除,一个是最低资源需求(request),即节点必须满足此Pod的最低资源;第二个是资源限额(limit),即当前节点最多能给pod提供的资源;

优选(priority):在符合节点找到最佳匹配的节点;

选定(select):把pod绑定到优选的节点上,如果有多个最佳节点,就会随机选一个;


3、K8S的高级调度方式

nodeAffinity:表示node亲和性调度,表示这个pod对这个节点有一定的倾向性。我们通过nodeselector来完成这类调度;

podAffinity或podAntiAffinity:pod亲和性或者pod反亲和性调度,有时我们期望某些Pod运行在同一个节点上或者是相邻的节点上,或者我们期望某些Pod不要运行在某些节点上;

taints和tolerations:污点和污点容忍调度:可以在某些节点上打上污点,表示这些节点不让pod在其上面运行。容忍某节点上污点的子集,则可以该Pod可被调度到该节点上。taints是定义在节点之上的,tolerations是定义在pod之上的。

一般是基于最大资源的空闲率来调度。


二、预选策略

1.源码

https://github.com/kubernetes/kubernetes/blob/master/pkg/scheduler/algorithm/predicates/predicates.go   # 预选策略很多,参见源码。

定义的策略很多,但是很多策略默认是没有启用的,可以手动配置启用。


2.常用的预选策略

1、CheckNodeCondition:表示检查是否可以在节点磁盘、网络不可用,或未准备好的前提下,能够把pod调度到上去。

2、GeneralPredicates:通用预选策略,不是一个策略,包含好几个预选策略:

       HostName:表示如果pod定义了hostname属性(pod.spec.hostname),则检查节点的名字跟pod的hostname是否相匹配,但这里并不是定义这个pod必须运行在这些节点上;

       PodFitsHostPorts:如果节点定义了hostport属性(pod.spec.containers.ports.hostPort),表示指定在节点的哪个端口上。如果这个节点的端口被占用了,那么这个节点就不适合运行这个pod;

       MatchNodeSelector:检查pods.spec.nodeSelector这个字段你是否定义了,运行在携有这有这些标签选择器的节点上;没有对应的node,则pod无法运行。

       PodFitsResources:检查节点是否有足够的资源来支持这个pod运行;

3、NoDiskConfict:检查Pod所请求的存储卷类型在此节点上是否可用。比如需要glusterfs类型的资源,但该节点不能挂在该类型资源。NoDiskConfict调度策略默认没有启用。

4、PodToleratesNodeTaints:如果Pod定义了Tolerates(容忍度),即pods.spec.tolerations,那么就检查Pod上的spec.tolerations可容忍的污点是否完全包含节点上的污点,如果是,表示这个节点可以被选定;

5、PodToleratesNodeNoExecuteTaints:检查pod是否容忍节点上有NoExecute污点。NoExecute污点:如果一个pod上运行在一个没有污点的节点上,后来这个节点又给加上污点了,那么NoExecute表示这个新加污点的节点会去除其上正在运行的pod;此调度策略默认没有启用;

6、CheckNodeLabelPresence:检查节点上指定标签的存在性,如果节点有pod指定的标签,那么这个节点就被选中。 此调度策略默认没有启用;

7、CheckServiceAffinity:根据当前Pod对象所属的Service已有的其他Pod对象。一个service下可以有多个pod,比如这些pod都运行在1、2、3机器上,而没有运行在4、5、6机器上,那么CheckServceAffinity就表示新加入的pod都集中运行在1、2、3机器上,这样集中好处是一个service下pod之间内部通信的效率变高了。 这个策略默认是没有启用的。

8、CheckVolumeBinding:检查节点上的pvc是否被别的pod绑定了;

9、NoVolumeZoneConflict:区域限制的前提下,检查节点上的pod是否与pod的需求冲突;

10、CheckNodeMemoryPressure:检查节点内存是否存在压力;

11、CheckNodePIDPressure:检查节点pid数量是否压力过大,但一般pid是可以重复使用的;

12、CheckNodeDiskPressure:检查内存/磁盘 IO是否压力过大;

13、MatchInterPodAffinity:检查Pod是否满足亲和性或者反亲和性;

14、MaxCSIVolumeCountPred:检查节点上挂载的附加存储的数量是否超出了最大的设定值。

 

pod在调度的时候,启用的所有预选策略要逐一评估。(都要满足,一票否决)


三、优选函数

1.源码

https://github.com/kubernetes/kubernetes/tree/master/pkg/scheduler/algorithm/priorities

https://github.com/kubernetes/kubernetes/blob/master/pkg/scheduler/algorithm/priorities/priorities.go


2.常用的优选函数

每一个优选函数的最大得分是10分。(得分范围是0-10)

1、LeastRequest:最少请求,空闲比例。对cpu来说,用cpu((capacity-sum(requested))*10/capacity)方式进行评估,得分最高的胜出;内存同样。(cpu得分+mem得分)/2=优选函数得分

2、BalanceResourceAllocation:均衡资源的使用方式,表示以cpu和内存占用率的相近程度(均衡)作为评估标准,二者占用越接近,得分就越高,得分高的胜出。

3、NodePreferAvoidPods:看节点是否有注解信息"scheduler.alpha.kubernetes.io/preferAvoidPods"。没有这个注解信息,说明这个节点是适合运行这个pod的,得分为10。优先级很高。

4、TaintToleration:将pod对象的spec.toleration与节点的taint列表项进行匹配度检查,匹配的条目越多,得分越低;

5、SelectorSpreading:查找当前pod对象对应的service,statefulset,replicatset等所匹配的标签选择器,在节点上运行的带有这样标签的pod越少得分越高。 这就是说我们要把同一个标签选择器下运行的pod散开(spreading)到多个节点上;

6、InterPodAffinity:遍历Pod对象亲和性的条目,并将那些能够匹配到节点权重相加,值越大的得分越高,得分高的胜出;

7、NodeAffinity:根据pod对象中的nodeselector,对节点进行匹配度检查,能够成功匹配的数量越多,得分就越高;

8、MostRequest:表示尽可能的把一个节点的资源先用完,这个和least_requested相反,二者不能同时使用;默认未启用;

9、NodeLabel:根据节点是否拥有标签,不关注标签值,来评估分数;默认未启用;

10、ImageLocality:表示根据满足当前pod运行需要的已有镜像体积大小之和来选择节点的;默认未启用。

 

启用的优选函数会逐一评估,最后得分相加,根据最终得分来优!!


四、高级调度设置方式

两类调度方式

节点选择器:nodeSelector,nodeName

节点亲和调度:nodeAffinity


(一)、节点选择器nodeSelector(强约束)


[root@master ~]# kubectl explain pod.spec.nodeSelector

 技术分享图片

技术分享图片

Pod处于Pending状态,因为调度失败,没有节点拥有disk:ssh标签。


[root@master ~]# kubectl label node node2 disk=ssd # 给node2打上需要的标签。

技术分享图片

可以看到刚才Pending的pod运行到了节点2上。


(二)、节点亲和性调度nodeAffinity


[root@master ~]# kubectl explain pod.spec.affinity.nodeAffinity
requiredDuringSchedulingIgnoredDuringExecution:硬亲和性,必须满足
preferredDuringSchedulingIgnoredDuringExecution:软亲和性,不是必须,尽量满足,优先运行在满足条件的节点上。

软亲和性和硬亲和性资源清单定义不相同,不能单独改个单词就是。


1、硬亲和性


[root@master ~]# kubectl explain pod.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms

 技术分享图片

目前没有节点拥有zOne=foo或者zOne=bar。


[root@master ~]# kubectl label node node1 zOne=foo #给node1打个标签

技术分享图片

Pod状态变为Running。


2、软亲和性


[root@master ~]# kubectl label node node1 zone- # 先删除node1上的zone标签

技术分享图片

目前是没有节点有拥有pod所需要的标签的,但是Pod一经创建马上运行,因为软亲和性,满足最好,不能满足也能将就。


三、Pod亲和性调度podAffinity,podAntiAffinity

比如在机房中,我们可以将一个机柜中的机器都打上标签,让pod调度的时候,对此机柜有亲和性;或者将机柜中某几台机器打上标签,让pod调度的时候,对这几个机器有亲和性;

通过节点亲和性,也能让一组pod运行在一起,但需要对节点进行精心编排,节点拥有的标签,想在一起pod使用相同的标签选择器,不想在一起的pod使用不同的标签选择器,比较麻烦。

Pod亲和性,第一个Pod随机调度,后面的Pod都以此为标准,运行在相近节点上,不需要考虑节点标签配置。但仍需要有一个逻辑条件预先设置好哪些节点是属于相近节点,同一位置,让pod去判断。


1、Pod亲和性podAffinity


[root@master ~]# kubectl explain pod.spec.affinity.podAffinity
preferredDuringSchedulingIgnoredDuringExecution:软亲和性
requiredDuringSchedulingIgnoredDuringExecution:硬亲和性


硬亲和性


[root@master ~]# kubectl explain pod.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution

技术分享图片

第二个Pod定义的podAffinity意思为:当前这个pod要跟一个有着标签app=myapp(要和上面pod-first的metadata里面的标签一致)的pod在一起。

topologyKey: kubernetes.io/hostname意思为:节点标签kubernetes.io/hostname相同的为相近节点。

由于定义的是硬亲和性,如果调度器找不到运行着app=myapp标签资源的节点,则Pod状态应该是Pending。

注意:要考虑到所有存在此标签的Pod,预期结果不同可能是因为当前名称空间已经存在app=myapp标签的Pod。


软亲和性

类似,不多介绍。


2、Pod反亲和性podAntiAffinity


[root@master ~]# kubectl explain pod.spec.affinity.podAntiAffinity
preferredDuringSchedulingIgnoredDuringExecution:软亲和性
requiredDuringSchedulingIgnoredDuringExecution:硬亲和性

资源清单定义类似于podAffinity。


硬亲和性

 技术分享图片

这样展现出来的效果不明显,如果只有一个节点可用的话,应该是第二个Pod会Pending。

再次实验:


[root@master ~]# kubectl label nodes node1 zOne=foo
[root@master
~]# kubectl label nodes node2 zOne=foo
# 给node1,node2打标签,这样node1,node2以此为标签属于一组相近节点,创建Pod时以zone为topologyKey。

技术分享图片

技术分享图片

与预期结果相符,调度失败提示也很明显。


软亲和性

类似,不过多实验。


四、污点调度

给节点选择了让哪些Pod运行的权利。

污点(taint)定义在节点上。

Tolerations:定义在pod上,定义容忍度。


[root@master ~]# kubectl get node node1 -o yaml
[root@master
~]# kubectl explain node.spec.taints

在Pod上定义容忍度有两种方式


[root@master schedule]# kubectl explain deployment.spec.template.spec.tolerations.operator
等值比较Equal: key,value,effect完全匹配
存在性判断Exists:key,effect完全匹配,value可以为空,不关注。

逐一匹配节点上的污点是否被容忍,只要有一个污点没有被容忍,并且effect为NoSchedule,则一定不能被调度过来。


[root@master ~]# kubectl describe node master #一般pod不被调度到master的原因是Master上存在污点。

技术分享图片


1、node.spec.taints.effect

taints上的effect定义对Pod的排斥效果:

NoSchedule:仅影响调度过程,对现存pod不产生影响,不能容忍就不能调度过来。

PreferNoSchedule:仅影响调度过程,不能容忍就不能调度过来,但是实在没办法也是能调度过来的。对节点新加了污点,那么对节点上现存的pod没有影响。

NoExecute:既影响调度过程,也影响现存的Pod对象。不容忍污点的Pod对象将被驱逐。


2、定义污点及容忍度


定义污点:


[root@master ~]# kubectl taint --help
[root@master schedule]# kubectl taint node node1 node
-type=production:NoSchedule #给node1打上污点

技术分享图片

所有的pod都被调度到了node2,因为pod不能容忍污点。在node2上也打上污点,并且effect为NoExecute,则已调度的Pod会被驱逐,然后因为所有节点上都有pod容忍不了的污点,pod就pending了。效果如下:

[root@master schedule]# kubectl taint node node2 node-type=dev:NoExecute

 技术分享图片


定义容忍度:


[root@master schedule]# kubectl explain pod.spec.tolerations
[root@master schedule]# kubectl explain deployment.spec.template.spec.tolerations

技术分享图片

在Pod上定义容忍度(容忍node-type=production:NoSchedule)后,之前Pending的pod被调度到了node1上,符合预期。

技术分享图片

修改资源清单,定义容忍node-type的所有effect,则pod能容忍node1,node2上的node-type污点,不管effect是什么。

注意:

       容忍度定义,等值比较(Equal)必须key,value,effect三者完全相匹配;如果effect,key定义为空,代表匹配所有的effect和key

       修改了资源清单的容忍度,Pod会被重新调度。


[root@master ~]# kubectl describe nodes node1 |grep -E (Roles|Taints) #查看节点上的污点
[root@master
~]# kubectl taint node node1 node-type- #删除节点上的污点
[root@master
~]# kubectl taint node node2 node-type-


五、Tips:

Protocol Buffer:组件之间内部对象序列化格式。

Json:资源对象序列化格式。

键值数据对:

       Labels:标签

       Annotations:注解

       Taints:污点,用在节点上的。


推荐阅读
author-avatar
蒲小平2502897955
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有