Kubernetes实战(六)-污点与容忍(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 node1 key=value:NoSchedule

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

然后,需要在 Pod 上生命 Toleration。下面的两个 Toleration 都被设置为可以容忍(Tolerate)具有该 Taint 的 Node,使得 Pod 能够被调度到 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,只要key能匹配上就可以)
  • 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 效果,但是有 PreferSchedule 效果,则调度器会尝试不把这个 Pod 指派给这个节点。
  • 如果在剩余的 Taint 中有 NoExecute效果,并且这个 Pod 已经在该节点上运行,则会被驱逐;如果没有在该节点上运行,则也不会再被调度到该节点上。

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

$ 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"
  effect: "NoExecute"

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

一般来说,如果给 Node 加上 effect=NoExecute 的 Taint,那么在该 Node 上正在运行的所有无对应 Toleration 的 Pod都会被立刻驱逐,而具有相应 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 nodename dedicated=groupName:NoSchedule

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

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

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

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

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

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

同时我们可以定义 Pod 驱逐行为,以应对节点故障(为 Alpha 版本的功能,Kubernetes 1.6版本开始引入),Pod 的 Toleration 可以这样定义:

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

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

如果没有为 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实战,Kubernetes)