0%

K8s-污点和容忍

污点和容忍

K8s-污点和容忍

概述

Pod 中存在属性 Node selector / Node affinity,用于将 Pod 指定到合适的节点。

相对的,节点中存在属性 污点 taints,使得节点可以排斥某些 Pod。

污点和容忍(taints and tolerations)成对工作,以确保 Pod 不会被调度到不合适的节点上。

  • 可以为节点增加污点(taints,一个节点可以有 0-N 个污点)
  • 可以为 Pod 增加容忍(toleration,一个 Pod 可以有 0-N 个容忍)
  • 如果节点上存在污点,则该节点不会接受任何不能容忍(tolerate)该污点的 Pod

向节点添加污点

  • 执行 kubectl taint 命令,可向节点添加污点,如下所示:

    1
    kubectl taint nodes node1 key=value:NoSchedule

    该命令为节点 node1 添加了一个污点。污点是一个键值对,在本例中,污点的键为 key,值为 value,污点效果为 NoSchedule。此污点意味着 Kubernetes 不会向该节点调度任何 Pod,除非该 Pod 有一个匹配的容忍(toleration)

  • 执行如下命令可以将本例中的污点移除:

    1
    kubectl taint nodes node1 key:NoSchedule-

向 Pod 添加容忍

PodSpec 中有一个 tolerations 字段,可用于向 Pod 添加容忍。下面的两个例子中定义的容忍都可以匹配上例中的污点,包含这些容忍的 Pod 也都可以被调度到 node1 节点上:

容忍1:

1
2
3
4
5
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"

容忍2:

1
2
3
4
tolerations:
- key: "key"
operator: "Exists"
effect: "NoSchedule"

下面这个 Pod 的例子中,使用了容忍:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations:
- key: "example-key"
operator: "Exists"
effect: "NoSchedule"

污点与容忍的匹配

当满足如下条件时,Kubernetes 认为容忍和污点匹配:

  • 键(key)相同

  • 效果(effect)相同

  • 污点的 operator 为:

    • Exists (此时污点中不应该指定 value
    • 或者 Equal (此时容忍的 value 应与污点的 value 相同)
  • 如果不指定 operator,则其默认为 Equal

一个节点上可以有多个污点,同时一个 Pod 上可以有多个容忍。Kubernetes 使用一种类似于过滤器的方法来处理多个节点和容忍:

  • 对于节点的所有污点,检查 Pod 上是否有匹配的容忍,如果存在匹配的容忍,则忽略该污点;
  • 剩下的不可忽略的污点将对该 Pod 起作用

例如:

  • 如果存在至少一个不可忽略的污点带有效果 NoSchedule,则 Kubernetes 不会将 Pod 调度到该节点上
  • 如果没有不可忽略的污点带有效果 NoSchedule,但是至少存在一个不可忽略的污点带有效果 PreferNoSchedule,则 Kubernetes 将尽量避免将该 Pod 调度到此节点
  • 如果存在至少一个忽略的污点带有效果 NoExecute,则:
    • 假设 Pod 已经在该节点上运行,Kubernetes 将从该节点上驱逐(evict)该 Pod
    • 假设 Pod 尚未在该节点上运行,Kubernetes 将不会把 Pod 调度到该节点

使用场景

污点和容忍使用起来非常灵活,可以用于:

  • 避免 Pod 被调度到某些特定的节点
  • 从节点上驱逐本不应该在该节点运行的 Pod

具体的场景可能有:

  • 专属的节点: 如果您想将一组节点专门用于特定的场景,您可以为这些节点添加污点(例如 kubectl taint nodes nodename dedicated=groupName:NoSchedule)然后向对应的 Pod 添加容忍。带有这些容忍的 Pod 将可以使用这一组专属节点,同时也可以使用集群中的其他节点。如果您想进一步限制这些 Pod 只能使用这一组节点,那么您应该为这一组节点添加一个标签(例如 dedicated=groupName),并为这一组 Pod 添加 node affinity(或 node selector)以限制这些 Pod 只能调度到这一组节点上。
  • 带有特殊硬件的节点: 集群中,如果某一组节点具备特殊的硬件(例如 GPU),此时非常有必要将那些不需要这类硬件的 Pod 从这组节点上排除掉,以便需要这类硬件的 Pod 可以得到资源。此时您可以为这类节点添加污点(例如:kubectl taint nodes nodename special=true:NoSchedule 或者 kubectl taint nodes nodename special=true:PreferNoSchedule)并为需要这类硬件的 Pod 添加匹配的容忍。
  • 基于污点的驱逐 当节点出现问题时,可以使用污点以 Pod 为单位从节点上驱逐 Pod。

基于污点的驱逐(TaintBasedEviction)

如果有 NoExecute 的污点效果,该效果将对已经运行在节点上的 Pod 施加如下影响:

  • 不容忍该污点的 Pod 将立刻被驱逐
  • 容忍该污点的 Pod 在未指定 tolerationSeconds 的情况下,将继续在该节点上运行
  • 容忍该污点的 Pod 在指定了 tolerationSeconds 的情况下,将在指定时间超过时从节点上驱逐

tolerationSeconds 字段可以理解为 Pod 容忍该污点的 耐心

  • 超过指定的时间,则达到 Pod 忍耐的极限,Pod 离开所在节点
  • 不指定 tolerationSeconds,则认为 Pod 对该污点的容忍是无期限的