带你玩转kubernetes-k8s(第18篇:k8s-深入掌握Pod-Node亲和性调度,Taints和Tolerations[污点和容忍])

       上节介绍的NodeAffinity节点亲和性,是在Pod上定义的一种属性,使得Pod能够被调度到某些Node上运行(优先选择或强制要求)。Taint则正好相反,它让Node拒绝Pod的运行。

      Taint需要和Toleration配合使用,让Pod避开那些不合适的Node。在Node上设置一个或多个Taint之后,除非Pod明确声明能够容忍这些污点,否则无法在这些Node上运行。Toleration是Pod的属性,让Pod能够(注意,只是能够,而非必须)运行在标注了Taint的Node上。

  可以使用kubectl taint命令为Node设置Taint信息:

kubectl taint nodes k8s-node1 key=value:NoSchedule

    这个设置为node1加上了一个Taint。该Taint的键为key,值为value,Taint的效果是NoSchedule。这意味着除非Pod明确声明可以容忍这个Taint,否则就不会被调度到node1上。

tolerations:
- key: "key"
  operator: "Equal"
  value: "value"
  effect: "NoSchedule"

或

tolerations:
- key: "key"
  operator: "Exists"
  effect: "NoSchedule"  

    Pod的Toleration声明中的key和effect需要与Taint的设置保持一致,并且满足以下条件之一。

◎ operator的值是Exists(无须指定value)。
◎ operator的值是Equal并且value相等。
如果不指定operator,则默认值为Equal。
另外,有如下两个特例。
◎ 空的key配合Exists操作符能够匹配所有的键和值。
◎ 空的effect匹配所有的effect。

       在上面的例子中,effect的取值为NoSchedule,还可以取值为PreferNoSchedule,这个值的意思是优先,也可以算作NoSchedule的软限制版本,一个Pod如果没有声明容忍这个Taint,则系统会尽量避免把这个Pod调度到这一节点上,但不是强制的。后面还会介绍另一个effect“NoExecute”。
       系统允许在同一个Node上设置多个Taint,也可以在Pod上设置多个Toleration。Kubernetes调度器处理多个Taint和Toleration的逻辑顺序为:首先列出节点中所有的Taint,然后忽略Pod的Toleration能够匹配的部分,剩下的没有忽略的Taint就是对Pod的效果了。下面是几种特殊情况。
◎ 如果在剩余的Taint中存在effect=NoSchedule,则调度器不会把该Pod调度到这一节点上。
◎ 如果在剩余的Taint中没有NoSchedule效果,但是有PreferNoSchedule效果,则调度器会尝试不把这个Pod指派给这个节点。
◎ 如果在剩余的Taint中有NoExecute效果,并且这个Pod已经在该节点上运行,则会被驱逐;如果没有在该节点上运行,则也不会再被调度到该节点上。

例如,我们则以对一个节点进行Taint设置:

kubectl taint nodes k8s-node1 key1=value1:NoSchedule
kubectl taint nodes k8s-node1 key1=value1:NoExecute
kubectl taint nodes k8s-node1 key2=value2:NoSchedule

之后在Pod上设置两个Toleration:

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"

    这样的结果是该Pod无法被调度到node1上,这是因为第3个Taint没有匹配的Toleration。但是如果该Pod已经在node1上运行了,那么在运行时设置第3个Taint,它还能继续在node1上运行,这是因为Pod可以容忍前两个Taint。

 

    一般来说,如果给Node加上effect=NoExecute的Taint,那么在该Node上正在运行的所有无对应Toleration的Pod都会被立刻驱逐,而具有相应Toleration的Pod永远不会被驱逐。不过,系统允许给具有NoExecute效果的Toleration加入一个可选的tolerationSeconds字段,这个设置表明Pod可以在Taint添加到Node之后还能在这个Node上运行多久(单位为s):

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
  tolerationSeconds: 3600

      上述定义的意思是,如果Pod正在运行,所在节点都被加入一个匹配的Taint,则这个Pod会持续在这个节点上存活3600s后被逐出。如果在这个宽限期内Taint被移除,则不会触发驱逐事件。

      Taint和Toleration是一种处理节点并且让Pod进行规避或者驱逐Pod的弹性处理方式,下面列举一些常见的用例。

1.独占节点

如果想要拿出一部分节点专门给一些特定应用使用,则可以为节点添加这样的Taint:

kubectl taint nodes  dedlicated=groupName:NoSchedule

    然后给这些应用的Pod加入对应的Toleration。这样,带有合适Toleration的Pod就会被允许同使用其他节点一样使用有Taint的节点。


     通过自定义Admission Controller也可以实现这一目标。如果希望让这些应用独占一批节点,并且确保它们只能使用这些节点,则还可以给这些Taint节点加入类似的标签dedicated=groupName,然后Admission Controller需要加入节点亲和性设置,要求Pod只会被调度到具有这一标签的节点上。

2.具有特殊硬件设备的节点

   在集群里可能有一小部分节点安装了特殊的硬件设备(如GPU芯片),用户自然会希望把不需要占用这类硬件的Pod排除在外,以确保对这类硬件有需求的Pod能够被顺利调度到这些节点。

可以用下面的命令为节点设置Taint:

kubectl taint nodes  special=true:NoSchedule
kubectl taint nodes  special=true:PreferNoSchedule

然后在Pod中利用对应的Toleration来保障特定的Pod能够使用特定的硬件。

和上面的独占节点的示例类似,使用Admission Controller来完成这一任务会更方便。

3.定义Pod驱逐行为,以应对节点故障(为Alpha版本的功能)

前面提到的NoExecute这个Taint效果对节点上正在运行的Pod有以下影响。

◎ 没有设置Toleration的Pod会被立刻驱逐。
◎ 配置了对应Toleration的Pod,如果没有为tolerationSeconds赋值,则会一直留在这一节点中。
◎ 配置了对应Toleration的Pod且指定了tolerationSeconds值,则会在指定时间后驱逐。
◎ Kubernetes从1.6版本开始引入一个Alpha版本的功能,即把节点故障标记为Taint(目前只针对node unreachable及node not ready,相应的NodeCondition "Ready"的值分别为Unknown和False)。激活TaintBasedEvictions功能后(在--feature-gates参数中加入TaintBasedEvictions=true),NodeController会自动为Node设置Taint,而在状态为Ready的Node上,之前设置过的普通驱逐逻辑将会被禁用。注意,在节点故障的情况下,为了保持现存的Pod驱逐的限速(rate-limiting)设置,系统将会以限速的模式逐步给Node设置Taint,这就能避免在一些特定情况下(比如Master暂时失联)大量的Pod被驱逐。这一功能兼容tolerationSeconds,允许Pod定义节点故障时持续多久才被逐出。

     例如,一个包含很多本地状态的应用可能需要在网络发生故障时,还能持续在节点上运行,期望网络能够快速恢复,从而避免被从这个节点上驱逐。

Pod的Toleration可以这样定义:

tolerations:
- key: "node.alpa.kubernetes.io/nureachable"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds:6000

      对于Node未就绪状态,可以把Key设置为node.alpha.kubernetes.io/notReady。


      如果没有为Pod指定node.alpha.kubernetes.io/notReady的Toleration,那么Kubernetes会自动为Pod加入tolerationSeconds=300的node.alpha.kubernetes.io/notReady类型的Toleration。 

     同样,如果Pod没有定义node.alpha.kubernetes.io/unreachable的Toleration,那么系统会自动为其加入tolerationSeconds=300的node.alpha.kubernetes.io/unreachable类型的Toleration。
    这些系统自动设置的toleration在Node发现问题时,能够为Pod确保驱逐前再运行5min。这两个默认的Toleration由Admission Controller“DefaultTolerationSeconds”自动加入。

   

   小结:

          今天的内容到此为止,明天为大家讲解Pod优先调度。

你可能感兴趣的:(kubernetes)