此文分享了污点和Node Affinity实际使用过程中的细节、坑和思维误区。同时整理且回答了诸多细节问题,尤其那些在官方文档中不曾提及的细节。

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

(避免Pod和Node同时出现在一小段文字中,所以Node以节点汉字表述)

Taint和Toleration

污点的理论支撑

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

使用效果(Effect):

  • PreferNoSchedule:调度器尽量避免把Pod调度到具有该污点效果的节点上,如果不能避免(如其他节点资源不足),Pod也能调度到这个污点节点上。

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

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

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

1.2 设置污点的效果实测

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

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

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

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

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

污点容忍设置, 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(不重要)

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设置沿用上一个例子的, 根据上面的配置,我们会看到:

如表所示, 最终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的使用总结

  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

Kubernetes高级调度- Taint和Toleration、Node Affinity分析的更多相关文章

  1. Kubernetes对Pod调度指定Node以及Node的Taint 和 Toleration

    由于博客园不支持markdown,推荐以下url阅读: 原创url:https://blog.csdn.net/weixin_42495873/article/details/103364868 ## ...

  2. Kubernetes 配置 Taint 和 Toleration(污点和容忍)

    通过污点和容忍让pod运行在特定节点上 参考官网:https://k8smeetup.github.io/docs/concepts/configuration/taint-and-toleratio ...

  3. Kubernetes之调度器和调度过程

    scheduler 当Scheduler通过API server 的watch接口监听到新建Pod副本的信息后,它会检查所有符合该Pod要求的Node列表,开始执行Pod调度逻辑.调度成功后将Pod绑 ...

  4. kubernetes 亲和性调度详解

    文章目录 1 概述: 2 场景一:调度到一组具有相同特性的主机上(label+nodeSelector) 3 场景二:部署的应用不想调度到某些节点上(nodeaffinity) 4 场景三:部署的应用 ...

  5. 第十四章 kubernetes 核心技术-调度器

    一.概述 一个容器平台的主要功能就是为容器分配运行时所需要的计算,存储和网络资源.容器调 度系统负责选择在最合适的主机上启动容器,并且将它们关联起来.它必须能够自动的处 理容器故障并且能够在更多的主机 ...

  6. 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解

    欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者:腾讯云容器服务团队 源码为 k8s v1.6.1 版本,github 上对应的 commit id 为 b0b7a323cc5a4a ...

  7. 从相亲的角度理解 K8S 的 Node Affinity, Taints 与 Tolerations

    这是昨天晚上阅读园子里的2篇 k8s 博文时产生的想法,在随笔中记录一下. 这2篇博文是 K8S调度之节点亲和性 与 K8S调度之Taints and Tolerations . 如果我们把 node ...

  8. Kubernetes容器集群管理环境 - Node节点的移除与加入

    一.如何从Kubernetes集群中移除Node比如从集群中移除k8s-node03这个Node节点,做法如下: 1)先在master节点查看Node情况 [root@k8s-master01 ~]# ...

  9. Kubernetes Pod 调度约束

    Kubernetes Pod 调度约束 可以将pod调度到指定的节点Node内 默认:根据节点资源利用率等分配Node节点. nodeName用于将Pod调度到指定的Node名称上 nodeSelec ...

随机推荐

  1. BladeX 2.0.7.RELEASE版本git后,在idea中导入项目,结果无法运行FlowApplication等几个服务的错误

    问题:2.0.7.RELEASE版本git后,在Intellij IDEA运行项目,结果无法运行FlowApplication等几个服务的错误 描述:打开IDEA,点击Check out from V ...

  2. mongoDB主从和集群

    主从(windows下的配置) 主服务器设置 mongod --dbpath=F:\mongoDB\db --master \\dbpath是设定数据存放路径 --master是指定为主库 从服务器设 ...

  3. (转)Java中的String为什么是不可变的? -- String源码分析

    背景:被问到很基础的知识点  string  自己答的很模糊 Java中的String为什么是不可变的? -- String源码分析 ps:最好去阅读原文 Java中的String为什么是不可变的 什 ...

  4. python面试题100道

    python 100道面试题 1.一行代码实现1--100之和 利用sum()函数求和 2.如何在一个函数内部修改全局变量 函数内部global声明 修改全局变量 3.列出5个python标准库 os ...

  5. c#动态类转json,再由json转xml

    直接上代码了,多说无意了. using System; using System.Collections; using System.Collections.Generic; using System ...

  6. SVN:修改文件后提示感叹号消失了处理办法

    使用SVN发现文件修改后,默认的修改标记红色感叹号不见了 重新显示设置方法: [右键]——[TortoiseSVN]——[Setting] 在[Icon Overlays]中选择[Default]即可 ...

  7. mysql网文收录

    1.分布式事务 1)  聊聊分布式事务,再说说解决方案 https://www.cnblogs.com/savorboard/p/distributed-system-transaction-cons ...

  8. JOIN的区别

    CREATE TABLE `j1` (  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  `c1` varchar(20) NOT NULL DEFAU ...

  9. 全栈项目|小书架|微信小程序-首页水平轮播实现

    首页效果 首页功能主要有 搜索(下篇文章介绍) 图书列表 图书列表 分析一波: 列表是水平滑动 点击列表会有按压效果:布局整体缩小 每个布局的信息从上到下排列分别是:图片.书名.作者.出版社 每个布局 ...

  10. Non-Maximum Suppression(非极大值抑制)

    定义与介绍(NMS 以及soft-NMS也有简单的介绍): https://www.cnblogs.com/makefile/p/nms.html IoU的介绍这篇写的不错: https://oldp ...