Kubernetes高级调度- Taint和Toleration、Node Affinity分析

此文分享了污点和Node Affinity实际使用过程当中的细节、坑和思惟误区。同时整理且回答了诸多细节问题,尤为那些在官方文档中未曾说起的细节。html

阅读提示:文中的节点指Nodejava

(避免Pod和Node同时出如今一小段文字中,因此Node以节点汉字表述)node

Taint和Toleration数组

污点的理论支撑app

0410_1.jpg

1.1 污点设置有哪些影响效果测试

使用效果(Effect):ui

  • PreferNoSchedule:调度器尽可能避免把Pod调度到具备该污点效果的节点上,若是不能避免(如其余节点资源不足),Pod也能调度到这个污点节点上。htm

  • NoSchedule:不容忍该污点效果的Pod永不会被调度到该节点上,经过kubelet管理的Pod(static Pod)不受限制;以前没有设置污点的Pod若是已运行在此节点(有污点的节点)上,能够继续运行。blog

  • NoExecute: 调度器不会把Pod调度到具备该污点效果的节点上,同时会将节点上已存在的Pod驱逐出去。内存

污点设置的第一前提是: 节点上的污点key和Pod上的污点容忍key相匹配。

1.2 设置污点的效果实测

0410_2.jpg

 

当Pod未设置污点容忍而节点设置了污点时

  • 当节点的污点影响效果被设置为:PreferNoSchedule时,已存在于此节点上的Pod不会被驱逐;新增但未设置污点容忍的Pod仍然能够被调度到此节点上。

  • 当节点的污点影响效果被设置为:NoSchedule时,已存在于此节点上的Pod不会被驱逐;同时,新增的Pod不会被调度此节点上。

  • 当节点的污点影响效果被设置为:NoExecute时,已存在于此节点上的Pod会发生驱逐(驱逐时间由tolerationSeconds字段肯定,小于等于0会当即驱逐);新增的Pod不会调度到此节点上。

当Node设置了污点且Pod设置了对应的污点容忍时,实测效果以下表:

0410_3.jpg

 

污点容忍设置, Exists和Equal这两个操做符之间的区别是什么?

在配置上:

  • Exists必须把值设置为空字符串,而只关心key与节点的污点key是否匹配。

  • Equal须要同时设置key和value来匹配污点节点的Key和value。

二者之间的理解加深:

  • 若一个节点存在多个污点, Pod使用Exists只容忍了其中一个污点, 仍然不能调度此节点, 缘由在于Pod不容忍此节点的其余污点。

  • 若一个节点存在多个污点, Pod使用Equal只容忍了其中一个污点, 仍然不能调度此节点, 缘由在于Pod仍是不容忍此节点的其余污点。

  • 若想要一个Pod可以调度到含有多个污点的节点上, 那么此Pod须要容忍此节点的全部污点。

1.3 污点容忍里的一些小窍门:

  • 在污点容忍设置时,若key,value是空字符且操做符是Exists 那么能Pod容忍节点的全部污点。(注意:仍然听从于容忍效果的等级设置)。例如:一个Pod在设置污点容忍时,key,value为空且操做符是Exists,容忍效果为:NoExecute,那么该Pod不会调度到污点效果为:NoSchedule的节点上。

  • 在设置污点容忍时, 若Pod的容忍效果(effect)被设置为空字符,那么Pod能匹配全部的容忍效果。

  • 在设置污点容忍时, 若key,value为空、操做符是Exists且容忍效果(effect)也为空时,则等于没有设置。

默认状况下,操做符是Equal。

若是节点的影响效果是NoExecute,且不想Pod被当即驱逐,那么能够设置TolerationSeconds(延迟驱逐时间),若值是0或者负数会当即驱逐,若值大于0,则在此时间后开始驱逐。

从测试结果来看,只要节点设置了污点且效果是:NoExecute,无论Pod是否容忍了该污点都不能在对应节点上正常运行(一直处于删除,重建的过程),缘由是能被调度到节点上是调度器选择的结果,Pod被杀掉是本地kubelet决策的结果,这是两个组件分管不一样工做产生的效果,下面这种配置除外。

tolerations:      
    - operator: Exists

#此Pod的污点配置可以容忍全部的污点,全部的影响效果,全部能调度到全部的节点上(包括影响效果被设置为:NoExecute的Node).

1.4 认知误区

1.4.1当一个节点设置了污点,那么只要设置Pod对此污点容忍就能调度上去且能正常运行。(错)

当节点的一个污点的影响效果被设置为:NoExecute,此时Pod对此污点的容忍效果也是NoExecute时, Pod能调度上去,可是也会被Terminating,不断的处于Terminating,ContainerCreating的过程。

对Node设置污点:

kubectl taint nodes 1xx status=unavailable:NoExecute

Pod设置的污点容忍:

tolerations:
     - effect: NoExecute
        key: status
        operator: Equal 
        tolerationSeconds: 0
         value: unavailable

效果:

tolerations:      
    - operator: Exists
#此Pod的污点配置可以容忍全部的污点,全部的影响效果,全部能调度到全部的节点上(包括影响效果被设置为:NoExecute的Node).

1.4.2 当一个节点设置了多个污点,只要使用Exists操做符匹配到其中一个污点,此Pod就能调度到对应的节点上。(错)

缘由在于Pod只能匹配到其中一个污点,可是仍是不能匹配到其余污点。因此,不能调度上去。

1.4.3 在设置Pod容忍时,只要匹配到key和value就好了,不用关心容忍效果的设置。(错)

容忍效果的设置和key/value的设置同样重要,甚至更加剧要。若是容忍效果不匹配。也会致使Pod调度不能到对应节点上。

1.4.4 若是Pod没有设置任何的污点容忍,Pod就不能调度到有污点的节点上。(错)

若是节点的污点效果是: PreferNoSchedule, 没有设置任何污点容忍的Pod也能调度到此节点上。缘由在于:PreferNoSchedule的意思是优先不调度,可是当没有节点可用时,Pod仍然能调度到此节点。

Node Affinity

Node Affinity可让指定应用调度到指定的节点,这有利于应用的稳定性,减小重要业务和不重要业务之间相互抢占资源的可能,同时也能够下降不重要业务对重要业务的影响,另外一方面,也可以进行多租户之间的隔离。根据租户需求为租户提供特定的运行环境。

2.1 NodeAffinity配置要点

NodeAffinity配置分类两大部分:

requiredDuringSchedulingIgnoredDuringExecution (强亲和性)

preferredDuringSchedulingIgnoredDuringExecution (首选亲和性)

可是,在真实的配置环节时,又会犯迷糊:

  • 强亲和性到底多强算强?

  • 首选亲和性中的首选体如今那些方面?

  • 强亲和性配置时,有两种配置方式,两种的区别是什么?

  • 首选亲和性中的权重值究竟是什么规则? 值越大权重值越高么?仍是值越小越高(1最大)?

  • 首选亲和性配置中, 若是Pod能匹配A节点的多个Label,也能匹配B节点的一个Label(A的Label权重之和等于B单个Label的权重),这时Pod会优先调度到A节点么?

  • 缩容时,是先从低权重的节点上开始杀么? 这些问题, 咱们都不能全靠注释和理解去揣测答案,必须通过实测获得真实答案,不然一旦上了生产再想修改就须要付出更大的成本。

  • 若是Pod是以强亲和性的方式绑定在节点上且Pod已经正常运行在此节点上,此时删除节点的标签是否会致使Pod重启发生漂移。

强亲和性:

requiredDuringSchedulingIgnoredDuringExecution

例子Node Labels设定:

level: important(重要),general(通常),unimportant(不重要)

0410_4.jpg

Pod与运算的配置:

注意: 强亲和性的配置分为: 与运算、或运算两部分

requiredDuringSchedulingIgnoredDuringExecution:
           nodeSelectorTerms:
              - matchExpressions:
              - key: level
                  operator: In
                  values:    
                   - important
               - key: app
                   operator: In
                   values:
                   - 1

在与运算的配置中,咱们发现,在同一个matchExpressions中既须要匹配level=important的标签也须要匹配app=1的标签。也就是说:Pod只会选择同时匹配这两个Label的节点。

根据上面Pod的Node亲和性设置,两个Label求一个交集,只有同时知足两个Label的节点才会归入这个Pod的调度池,显而易见,只有10.x.x.80这个节点。因此,此Pod只能调度到这个节点,若是这个节点资源不足,那么此Pod调度失败。

Pod或运算配置:

requiredDuringSchedulingIgnoredDuringExecution:
           nodeSelectorTerms:
           - matchExpressions:
              - key: level 
               operator: In
               values:
               - important
            - matchExpressions:
              - key: level 
               operator: In
               values:
               - unimportant

在或运算的配置中,咱们发现有一个matchExpressions数组,里面的Label列表求并集。也就是说:Pod能够选择只要匹配其中一个Label的节点就行,不用全匹配。

举个例子:

节点的Label设置沿用上一个例子的。 节点的标签只要能知足Pod的其中一个标签, 节点就能归入这个Pod的调度池,显而易见,这个Pod可选的节点有:10.x.x.78, 10.x.x.79,10.x.x.80, 10.x.x.86, 10.x.x.87, 10.x.x.88。

首选亲和性: 

preferredDuringSchedulingIgnoredDuringExecution

它的使用风格应该是:若是Pod能调度到指定Label的节点最好,若是不能,也不强求,Pod选择其余的节点也行,即便这个节点根本没有Label或者节点的Label和我彻底不匹配。

Pod首选亲和性设置:

preferredDuringSchedulingIgnoredDuringExecution:
         - preference:
              matchExpressions:
             - key: level 
               operator: In 
               values:
               - important
            weight: 5
         - preference: 
             matchExpressions:
             - key: app
                operator: In 
               values:
               - "1"
           weight: 4
         - preference:
              matchExpressions:
             - key: master
                operator: In
                values:
               - "1"
           weight: 10

示例: Node的Label设置沿用上一个例子的, 根据上面的配置,咱们会看到:

0410_5.jpg

如表所示, 最终Pod优先调度到10.x.x.85, 缘由在于app=1的权重是4, level=important的权重是5, 因此:节点 10.x.x.80的权重是:9,可是仍然小于节点:10.x.x.85的权重。

2.2 问题总结

  1. 其实强亲和性和首选亲和性区别体如今:Pod对节点的选择上。就强亲和性而言,若是节点不能匹配Pod对Label的要求, Pod永远不会调度到这类节点上,即便是Pod调度失败(没错,就是头铁),就首选亲和性来讲,能调度到最优节点是一件很是值得开心的事情,若是不能调度到最优节点能够退而求其次,总有适合本身的。 (回答问题1)

  2. 首选亲和性体如今PodLabel的权重值上,而与节点Label的匹配个数无关。(回答问题2)

  3. 在首选亲和性配置中会多一个权重值的字段(weight),这个值越大,权重越大,Pod调度到对应此Label的节点的几率越高。(回答问题4)

  4. 一个节点有多个Label且节点能知足Pod所要求的全部Label,若是多个Label的权重值相加仍然小于某单个Label的节点,那么Pod首选是权重值高的节点;若是Pod能匹配到A 节点的全部Label,同时也能匹配到B 节点某一个Label.可是,A节点 Label的权重之和恰好等于B 节点的单个Label的权重,这时,Pod优先选择的A仍是B这是随机的(只针对亲和性来讲是随机的,实际状况还要考虑其余状况)。而不会管Label的匹配个数。(回答问题5)

  5. 建立或扩容Pod时,优先选择Label匹配权重值大的节点,若此节点的其余条件不知足(好比内存不足),选择次权重的,最后选择Label不匹配或者根本没有Label的节点。

  6. (回答问题6)缩容时,随机选择Pod杀掉,而不是咱们预想的从低权重的节点开始杀,这点值得注意。

  7. (回答问题7)答案是不会,正在运行的Pod不会被调度到新的节点去, 当Pod由于某种缘由重启(指Pod名字改变,触发重调度,名字不改变,意味着不触发调度器调度,只是原地重启)后,会自动调度到符合亲和性选择的节点上。

污点和Node Affinity的使用总结

0410_6.jpg

  1. 就污点而言,它的使用一般是负向的, 也就说, 污点经常使用在某Node不让大多数Pod调度只让少部分Pod调度时,又或者节点根本不参加工做负载时。好比:咱们常见的master节点上不调度负载pod,保证master组件的稳定性;节点有特殊资源,大部分应用不须要而少部分应用须要,如GPU。

  2. 就Node Affinity来讲,他的使用能够正向的,也就是说,咱们想让某个应用的Pod部署在指定的一堆节点上。固然,也能够是负向的,好比说咱们常说的Node 反亲和性,只须要把操做符设置为NotIn就能达成预期目标。

  3. 就污点而言,若是节点设置的污点效果是NoSchedule或者NoExecute,意味着没有设置污点容忍的Pod毫不可能调度到这些节点上。

  4. 就Node Affinity而言,若是节点设置了Label,可是Pod没有任何的Node Affinity设置,那么Pod是能够调度到这些节点上的。

 

相关服务请访问:https://support.huaweicloud.com/cce/index.html?utm_content=cce_helpcenter_2019

相关文章
相关标签/搜索