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


    参见:调度器、预选策略与优选函数 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:污点,用在节点上的。

  • 相关阅读:
    python GUI
    Python 博客网站资源
    Python 100 天学习计划
    pycharm基本设置
    MySQL 57安装部署(Zip版)(Windows版)
    nginx在centos下的安装
    仓位计算
    python笔记
    vue(一)--监听事件
    Hibernate(五)--级联
  • 原文地址:https://www.cnblogs.com/cmxu/p/12255993.html
Copyright © 2020-2023  润新知