2.6. 使用节点污点控制 pod 放置
通过污点和容限,节点可以控制哪些 Pod 应该(或不应该)调度到节点上。
2.6.1. 了解污点和容限
通过使用污点(taint),节点可以拒绝调度 pod,除非 pod 具有匹配的容限(toleration)。
您可以通过节点规格 (NodeSpec
) 将污点应用到节点,并通过 pod 规格 (PodSpec
) 将容限应用到 pod。节点上的污点指示节点排斥所有不容许该污点的 pod。
污点与容限由 key、value 和 effect 组成。运算符允许您将其中一个参数留空。
参数 | 描述 | ||||||
---|---|---|---|---|---|---|---|
|
| ||||||
|
| ||||||
| effect 的值包括:
| ||||||
|
|
容限与污点匹配:
如果
operator
参数设为Equal
:-
key
参数相同; -
value
参数相同; -
effect
参数相同。
-
如果
operator
参数设为Exists
:-
key
参数相同; -
effect
参数相同。
-
Kubernetes 中内置了以下污点:
-
node.kubernetes.io/not-ready
:节点未就绪。这与节点状况Ready=False
对应。 -
node.kubernetes.io/unreachable
:节点无法从节点控制器访问。这与节点状况Ready=Unknown
对应。 -
node.kubernetes.io/out-of-disk
:节点上的可用空间不足,无法添加新 pod。这与节点状况OutOfDisk=True
对应。 -
node.kubernetes.io/memory-pressure
:节点存在内存压力问题。这与节点状况MemoryPressure=True
对应。 -
node.kubernetes.io/disk-pressure
:节点存在磁盘压力问题。这与节点状况DiskPressure=True
对应。 -
node.kubernetes.io/network-unavailable
:节点网络不可用。 -
node.kubernetes.io/unschedulable
:节点不可调度。 -
node.cloudprovider.kubernetes.io/uninitialized
:当节点控制器通过外部云提供商启动时,在节点上设置这个污点来将其标记为不可用。在云控制器管理器中的某个控制器初始化这个节点后,kubelet 会移除此污点。
2.6.1.1. 了解如何使用容限秒数来延迟 pod 驱除
您可以通过在 pod 规格中指定 tolerationSeconds
参数,指定 pod 在被驱除前可以保持与节点绑定的时长。如果将具有 NoExecute
effect 的污点添加到某个节点,则所有不容许该污点的 pod 都被立即驱除(容许该污点的 pod 不会被驱除)。但是,如果要被驱除的 pod 具有 tolerationSeconds
参数,则只有该时限到期后 pod 才会被驱除。
例如:
tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoExecute" tolerationSeconds: 3600
在这里,如果此 pod 正在运行但没有匹配的污点,pod 保持与节点绑定 3600 秒,然后被驱除。如果污点在这个时间之前移除,pod 就不会被驱除。
2.6.1.2. 了解如何使用多个污点
您可以在同一个节点中放入多个污点,并在同一 pod 中放入多个容限。OpenShift Container Platform 按照如下所述处理多个污点和容限:
- 处理 pod 具有匹配容限的污点。
其余的不匹配污点在 pod 上有指示的 effect:
-
如果至少有一个不匹配污点具有
NoSchedule
effect,则 OpenShift Container Platform 无法将 pod 调度到该节点上。 -
如果没有不匹配污点具有
NoSchedule
effect,但至少有一个不匹配污点具有PreferNoSchedule
effect,则 OpenShift Container Platform 尝试不将 pod 调度到该节点上。 如果至少有一个未匹配污点具有
NoExecute
effect,OpenShift Container Platform 会将 pod 从该节点驱除(如果它已在该节点上运行),或者不将 pod 调度到该节点上(如果还没有在该节点上运行)。- 不容许污点的 Pod 会立即被驱除。
-
如果 Pod 容许污点,且没有在容限规格中指定
tolerationSeconds
,则会永久保持绑定。 -
如果 Pod 容许污点,且指定了
tolerationSeconds
,则会在指定的时间里保持绑定。
-
如果至少有一个不匹配污点具有
例如:
节点具有以下污点:
$ oc adm taint nodes node1 key1=value1:NoSchedule $ oc adm taint nodes node1 key1=value1:NoExecute $ oc adm taint nodes node1 key2=value2:NoSchedule
pod 具有以下容限:
tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoSchedule" - key: "key1" operator: "Equal" value: "value1" effect: "NoExecute"
在本例中,pod 无法调度到节点上,因为没有与第三个污点匹配的容限。如果在添加污点时 pod 已在节点上运行,pod 会继续运行,因为第三个污点是三个污点中 pod 唯一不容许的污点。
2.6.1.3. 防止因为节点问题而发生 pod 驱除
OpenShift Container Platform 可以配置为用污点来代表节点不可访问和节点未就绪状况。这样,就可以对每个 pod 设置在节点变得不可访问或未就绪时保持与节点绑定的时长,而不是使用默认的五分钟。
Taint-Based Evictions 功能默认为启用。污点由节点控制器自动添加,而且会禁用从就绪
节点驱除 pod 的一般逻辑。
-
如果节点进入未就绪状态,则添加
node.kubernetes.io/not-ready:NoExecute
污点,并且无法将 pod 调度到该节点上。现有 pod 在容限秒数期限内保留。 -
如果节点进入不可访问状态,则添加
node.kubernetes.io/unreachable:NoExecute
污点,并且无法将 pod 调度到该节点上。现有 pod 在容限秒数期限内保留。
此功能与 tolerationSeconds
相结合,可以允许 pod 指定它应当在多久时间内保持与具有一个或多个这种问题的节点的绑定。
2.6.1.4. 了解 pod 调度和节点状况(根据条件设置污点节点)
OpenShift Container Platform 会自动将报告内存压力和磁盘压力等状况的节点变成污点。如果某个节点报告一个状况,则添加一个污点,直到状况被清除为止。这些污点具有 NoSchedule
effect;即,pod 无法调度到该节点上,除非 pod 有匹配的容限。此功能称为 根据条件设置污点节点(Taint Nodes By Condition),默认为启用。
在调度 pod 前,调度程序会检查节点上是否有这些污点。如果污点存在,则将 pod 调度到另一个节点。由于调度程序检查的是污点而非实际的节点状况,因此您可以通过添加适当的 Pod 容限,将调度程序配置为忽略其中一些节点状况。
DaemonSet 控制器会自动将下列容限添加到所有守护进程,以保证向后兼容性:
- node.kubernetes.io/memory-pressure
- node.kubernetes.io/disk-pressure
- node.kubernetes.io/out-of-disk(仅限关键 pod)
- node.kubernetes.io/unschedulable(1.10 或更高版本)
- node.kubernetes.io/network-unavailable(仅限主机网络)
您还可以在 DaemonSet 中添加任意容限。
2.6.1.5. 了解根据状况驱除 pod (基于污点的驱除)
基于污点的驱除(Taint-Based Evictions)功能默认为启用,可以从遇到特定状况(如未就绪
和无法访问
)的节点驱除 pod。当节点遇到其中一个状况时,OpenShift Container Platform 会自动给节点添加污点,并开始驱除 pod 以及将 pod 重新调度到其他节点。
Taint Based Evictions 具有 NoExecute
effect,不容许污点的 pod 都会被立即驱除,而容许污点的 pod 则永不会被驱除。
OpenShift Container Platform 会以限速方式驱除 pod,从而防止在主控机从节点分离等情形中发生大量 pod 驱除。
此功能与 tolerationSeconds
相结合,允许您指定 pod 应当在多久时间内保持与具有某一节点状况的节点的绑定。如果在 tolerationSections
到期后状况仍然存在,则污点会保持在节点上,并且 pod 会以限速方式被驱除。如果状况在 tolerationSeconds
到期前清除,则 pod 不会被移除。
OpenShift Container Platform 会自动为 node.kubernetes.io/not-ready
和 node.kubernetes.io/unreachable
添加容限并设置 tolerationSeconds=300
,除非 pod 配置中已指定了其中任一种容限。
spec tolerations: - key: node.kubernetes.io/not-ready operator: Exists effect: NoExecute tolerationSeconds: 300 - key: node.kubernetes.io/unreachable operator: Exists effect: NoExecute tolerationSeconds: 300
这些容限确保了在默认情况下,pod 在检测到这些节点条件问题中的任何一个时,会保持绑定 5 分钟。
您可以根据需要配置这些容限。例如,如果您有一个具有许多本地状态的应用程序,您可能希望在发生网络分区时让 pod 与节点保持绑定更久一些,以等待分区恢复并避免 pod 驱除行为的发生。
DaemonSet pod 创建时具有以下污点的 NoExecute 容限,但没有设置 tolerationSeconds:
-
node.kubernetes.io/unreachable
-
node.kubernetes.io/not-ready
这可以确保 DaemonSet pod 不会因为这些节点状况而被驱除,即使 DefaultTolerationSeconds
准入控制器已被禁用。
2.6.2. 添加污点和容限
您可以给节点添加污点并给 pod 添加容限,让节点能够控制哪些 pod 应该(或不应该)调度到节点上。
流程
在以下命令中使用污点和容限组件表中描述的参数:
$ oc adm taint nodes <node-name> <key>=<value>:<effect>
例如:
$ oc adm taint nodes node1 key1=value1:NoExecute
本例在
node1
上放置一个键为key1
且值为value1
的污点,污点效果是NoExecute
。通过编辑 pod 规格以使其包含一个
tolerations
部分,给 pod 添加容限:使用
Equal
运算符的 pod 配置文件示例tolerations: - key: "key1" 1 operator: "Equal" 2 value: "value1" 3 effect: "NoExecute" 4 tolerationSeconds: 3600 5
例如:
使用
Exists
运算符的 pod 配置文件示例tolerations: - key: "key1" operator: "Exists" effect: "NoExecute" tolerationSeconds: 3600
这两个容限都与上述
oc adm taint
命令创建的污点匹配。具有任一容限的 pod 可以调度到node1
。
2.6.2.1. 使用污点和容限为用户指定专用节点
您可以指定一组节点供一组特定用户独占使用。
流程
指定专用节点:
给这些节点添加污点:
例如:
$ oc adm taint nodes node1 dedicated=groupName:NoSchedule
通过编写自定义准入控制器,给 pod 添加对应的容限。
只有具有这些容限的 pod 才可以使用专用节点。
2.6.2.2. 使用污点和容限将用户绑定到节点
您可以配置节点,使特定用户只能使用专用节点。
流程
配置节点以使用户只能使用该节点:
给这些节点添加污点:
例如:
$ oc adm taint nodes node1 dedicated=groupName:NoSchedule
通过编写自定义准入控制器,给 pod 添加对应的容限。
准入控制器应该添加一个节点关联性,使得 pod 只能调度到具有
key:value
标签 (dedicated=groupName
) 的节点。-
给专用节点添加与污点类似的标签(如
key:value
标签)。
2.6.2.3. 使用污点和容限控制具有特殊硬件的节点
如果集群中有少量节点具有特殊的硬件(如 GPU),您可以使用污点和容限让不需要特殊硬件的 pod 与这些节点保持距离,从而将这些节点保留给那些确实需要特殊硬件的 pod。您还可以要求需要特殊硬件的 pod 使用特定的节点。
流程
确保 pod 被禁止使用特殊硬件:
使用以下命令之一,给拥有特殊硬件的节点添加污点:
$ oc adm taint nodes <node-name> disktype=ssd:NoSchedule $ oc adm taint nodes <node-name> disktype=ssd:PreferNoSchedule
- 给利用准入控制器来使用特殊硬件的 pod 添加对应的容限。
例如,准入控制器可以使用 pod 的一些特征来决定是否应该允许 pod 通过添加容限来使用特殊节点。
要确保 pod 只能使用特殊硬件,您需要一些额外的机制。例如,您可以给具有特殊硬件的节点打上标签,并在需要该硬件的 pod 上使用节点关联性。
2.6.3. 删除污点和容限
您可以根据需要,从节点移除污点并从 pod 移除容限。
流程
移除污点和容限:
从节点移除污点:
$ oc adm taint nodes <node-name> <key>-
例如:
$ oc adm taint nodes ip-10-0-132-248.ec2.internal key1- node/ip-10-0-132-248.ec2.internal untainted
要从 pod 移除某一容限,请编辑 pod 规格来移除该容限:
tolerations: - key: "key2" operator: "Exists" effect: "NoExecute" tolerationSeconds: 3600