Kubernetes 污点与容忍详解

阅读数:232 2019 年 11 月 20 日 19:06

Kubernetes 污点与容忍详解

Taint(污点)和 Toleration(容忍)可以作用于 node 和 pod 上,其目的是优化 pod 在集群间的调度,它们相互配合,可以用来避免 pod 被分配到不合适的节点上。本文作者通过代码实践讲述了他学习 K8s 容点和污点的经历。

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

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"

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 定义节点故障时持续多久才被逐出。

多污点与多容忍配置

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

  • 如果剩余的 Taint 中存在 effect=NoSchedule,则调度器不会把该 pod 调度到这一节点上。
  • 如果剩余的 Taint 中没有 NoSchedule 的效果,但是有 PreferNoSchedule 效果,则调度器会尝试不会 pod 指派给这个节点
  • 如果剩余 Taint 的效果有 NoExecute 的,并且这个 pod 已经在该节点运行,则会被驱逐;如果没有在该节点运行,也不会再被调度到该节点上。

示例如下:

复制代码
kubectltaint 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" effect: "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 被移除,则不会触发驱逐事件。

常见应用场景节点独占

如果想要拿出一部分节点,专门给特定的应用使用,则可以为节点添加这样的 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 special=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"
tolerationSeconds: 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" 自动加入。

添加小助手微信,加入【容器魔方】技术社群。
Kubernetes 污点与容忍详解

评论

发布