[译] Kubernetes 污点与容忍详解

前言

Taint(污点)和 Toleration(容忍)可以作用于 node 和 pod 上,其目的是优化 pod 在集群间的调度,它们 相互配合,可以用来避免 pod 被分配到不合适的节点上。

本文作者通过代码实践讲述了他学习K8s容点和污点的经历。

K8s每个节点上都可以应用一个或多个 taint ,这表示对于那些不能容忍这些 taint 的 pod,是不会被该节点接受的。如果将 toleration 应用于 pod 上,则表示这些 pod 可以(但不要求)被调度到具有相应 taint 的节点上。

No.1

Taint 基本用法

  • 设置污点: kubectl taint node [node] key=value:[effect]

    其中[effect] 可取值: [ NoSchedule | PreferNoSchedule | NoExecute ]:

  • NoSchedule :一定不能被调度。

  • PreferNoSchedule:尽量不要调度。

  • NoExecute:不仅不会调度,还会驱逐Node上已有的Pod。

  • 去除污点: kubectl taint node [node] key:[effect]-

#比如设置污点:

kubectl taint node test test=16:NoSchedule

kubectl taint node test test=16:NoExecute

#去除指定key及其effect:

kubectl taint nodes node_name key:[effect]-    #(这里的key不用指定value)

#去除指定key所有的effect:

kubectl taint nodes node_name key-

#示例:

kubectl taint node test test:NoSchedule-

kubectl taint node test test:NoExecute-

kubectl taint node test test-

下面是一个简单的示例:在node1上加一个Taint,该Taint的键为key,值为value,Taint的效果是NoSchedule。这意味着除非pod明确声明可以容忍这个Taint,否则就不会被调度到node1上:

kubectl taint nodes node1  key=value:NoSchedule

然后需要在pod上声明Toleration。下面的Toleration设置为可以容忍具有该Taint的Node,使得pod能够被调度到node1上:

apiVersion: v1

kind: Pod

metadata:

name: pod-taints

spec:

tolerations:

- key: "key"

operator : "Equal"

value: "value"

effect: "NoSchedule"

containers:

- name: pod-taints

image: busybox:latest

也可以写成如下:

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

No.2

Toleration基本用法

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

  • operator的值为Exists,这时无需指定value

  • operator的值为Equal并且value相等

    如果不指定operator,则默认值为Equal。

另外还有如下两个特例:

  • 空的key配合Exists操作符能够匹配所有的键和值

  • 空的effect匹配所有的effect

上面的例子中effect的取值为NoSchedule,下面对effect的值作下简单说明:

  • NoSchedule:如果一个pod没有声明容忍这个Taint,则系统不会把该Pod调度到有这个Taint的node上

  • PreferNoSchedule:NoSchedule的软限制版本,如果一个Pod没有声明容忍这个Taint,则系统会尽量避免把这个pod调度到这一节点上去,但不是强制的。

  • NoExecute:定义pod的驱逐行为,以应对节点故障。

NoExecute这个Taint效果对节点上正在运行的pod有以下影响:

  • 没有设置Toleration的Pod会被立刻驱逐

  • 配置了对应Toleration的pod,如果没有为tolerationSeconds赋值,则会一直留在这一节点中

  • 配置了对应Toleration的pod且指定了tolerationSeconds值,则会在指定时间后驱逐

从kubernetes1.6版本开始引入了一个alpha版本的功能,即把节点故障标记为Taint(目前只针对node unreachable及node not ready,相应的NodeCondition "Ready"的值为Unknown和False)。

激活TaintBasedEvictions功能后(在--feature-gates参数中加入TaintBasedEvictions=true),NodeController会自动为Node设置Taint,而状态为"Ready"的Node上之前设置过的普通驱逐逻辑将会被禁用。

注意, 在节点故障情况下,为了保持现存的pod驱逐的限速设置,系统将会以限速的模式逐步给node设置Taint,这就能防止在一些特定情况下(比如master暂时失联)造成的大量pod被驱逐的后果。这一功能兼容于tolerationSeconds,允许pod定义节点故障时持续多久才被逐出。

No.3

多污点与多容忍配置

系统允许在同一个node上设置多个taint,也可以在pod上设置多个Toleration。Kubernetes调度器处理多个Taint和Toleration能够匹配的部分,剩下的没有忽略掉的Taint就是对Pod的效果了。下面是几种特殊情况:

  • 如果剩余的Taint中存在effect=NoSchedule,则调度器不会把该pod调度到这一节点上。

  • 如果剩余的Taint中没有NoSchedule的效果,但是有PreferNoSchedule效果,则调度器会尝试不会pod指派给这个节点

  • 如果剩余Taint的效果有NoExecute的,并且这个pod已经在该节点运行,则会被驱逐;如果没有在该节点运行,也不会再被调度到该节点上。

示例如下:

kubectl taint nodes node1 key1=value1:NoSchedule

kubectl taint nodes node1 key1=value1:NoExecute

kubectl taint nodes node1 key2=value2:NoSchedule

在pod上设置两个toleration:

tolerations:

- key: "key1"

operator: "Equal"

value: "value1"

effect: "NoSchedule"

- key: "key1"

operator: "Equal"

value: "value1"

"NoExecute"

这样的结果是该pod无法被调度到node1上,因为第三个taint没有匹配的toleration。但是如果这个Pod已经在node1上运行了,那么在运行时设置上第三个Taint,它还能继续运行,因为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: "NoSchedule"

tolerationSeconds: 3600

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

No.4

常见应用场景节点独占

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

kubectl taint nodes test dedicated=groupName:NoSchedule

然后给这些应用的pod加入相应的toleration,则带有合适toleration的pod就会被允许同使用其他节点一样使用有taint的节点。然后再将这些node打上指定的标签,再通过nodeSelector或者亲和性调度的方式,要求这些pod必须运行在指定标签的节点上。

1) 具有特殊硬件设备的节点

在集群里,可能有一小部分节点安装了特殊的硬件设备,比如GPU芯片。用户自然会希望把不需要占用这类硬件的pod排除在外。以确保对这类硬件有需求的pod能够顺利调度到这些节点上。可以使用下面的命令为节点设置taint:

kubectl taint nodes test special= true :NoSchedule

kubectl taint nodes test

true

:PreferNoSchedule

然后在pod中利用对应的toleration来保障特定的pod能够使用特定的硬件。然后同样的,我们也可以使用标签或者其他的一些特征来判断这些pod,将其调度到这些特定硬件的服务器上。

2) 应对节点故障

之前说到,在节点故障时,可以通过TaintBasedEvictions功能自动将节点设置Taint,然后将pod驱逐。但是在一些场景下,比如说网络故障造成的master与node失联,而这个node上运行了很多本地状态的应用即使网络故障,也仍然希望能够持续在该节点上运行,期望网络能够快速恢复,从而避免从这个node上被驱逐。Pod的Toleration可以这样定义:

tolerations:

- key: "node.alpha.kubernetes.io/unreachable"

operator: "Exists"

effect: "NoExecute"

6000

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

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

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

这些系统自动设置的toleration用于在node发现问题时,能够为pod确保驱逐前再运行5min。这两个默认的toleration由Admission Controller "DefaultTolerationSeconds"自动加入。

原文地址:

https://ops.fwy.pub/taint-and-toleration-in-k8s/

活动预告

扫码加群

Kubernetse、Istio、KubeEdge、Volcano

多个云原生技术社群等你来嗨聊

扫码并备注想要加入的技术群

小助手邀您进群

微信号 : k8s2222

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章