污点和容忍度
污点(Taint),它使节点能够排斥一类特定的 Pod。
容忍度(Toleration) 是应用于 Pod 上的,容忍度允许调度器调度带有对应污点的 Pod。 容忍度允许调度但并不保证调度:作为其功能的一部分, 调度器也会评估其它参数(Pod的优先级)。
Taint 和 Toleration 相互配合,可以用来避免 Pod 被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,如何Pod对节点没有添加对应的容忍,它是无法被成功分配到该节点上的。
添加污点
使用命令 kubectl taint 给节点增加一个污点
[root@k8s-master-1 ~]# kubectl taint nodes k8s-node-2 key1=value1:NoSchedule
给节点 k8s-node-2
增加一个污点,它的键名是 key1
,键值是 value1
,效果是 NoSchedule
。 这表示只有拥有和这个污点相匹配的容忍度的 Pod 才能够被分配到 node1
这个节点。
若要移除上述命令所添加的污点,可以执行:
[root@k8s-master-1 ~]# kubectl taint nodes k8s-node-2 key1=value1:NoSchedule-
在 Pod 规约中为 Pod 设置容忍度。
下面两个容忍度均与上面例子中使用 kubectl taint
命令创建的污点相匹配, 因此如果一个 Pod 拥有其中的任何一个容忍度,都能够被调度到 k8s-node-2
:
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
tolerations:
- key: "key1"
operator: "Exists"
effect: "NoSchedule"
手动调度的情况
默认的 Kubernetes 调度器在选择一个节点来运行特定的 Pod 时会考虑污点和容忍度。
然而,如果你手动为一个 Pod 指定了 .spec.nodeName
,那么选节点操作会绕过调度器;即使选择的节点上有 NoSchedule
的污点, 这个 Pod 也会绑定到你指定的节点上。
但是如果节点上设置了 NoExecute
的污点,kubelet 会将 Pod 驱逐出去,除非有适当的容忍度设置:
如果部署控制器是Deployment控制器进行Pod创建,在没有设置容忍度的情况下并且指定调
度节点的污点effect为NoExecute的时候,它会反复创建新的Pod到该节点上:
定义容忍度的pod
以下是定义了容忍度的pod模板:
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations:
- key: "key1"
operator: "Exists"
effect: "NoSchedule"
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoSchedule"
operator
的默认值是 Equal
。
一个容忍度和一个污点相“匹配”是指它们有一样的键名和效果,并且:
- 如果
operator
是Exists
(此时容忍度不能指定value
) - 如果
operator
是Equal
,则它们的值应该相等。
容忍任意污点
如果一个容忍度的 key
为空且 operator
为 Exists
, 表示这个容忍度与任意的 key、value 和 effect 都匹配,即这个容忍度能容忍任何污点。
tolerations:
- key: ""
operator: "Exists"
value: ""
effect: ""
effect
字段的允许值:
1. NoExecute
定义:
- NoExecute污点不仅阻止新的Pod被调度到带有该污点的节点上,还会驱逐已经存在于该节点上的不容忍该污点的Pod。
行为:
- 当节点被添加了NoExecute污点后,调度器将不会将任何没有相应容忍度的Pod调度到该节点上。
- 如果节点上已经运行了Pod,并且这些Pod没有设置容忍该NoExecute污点的容忍度,那么这些Pod将被kubelet驱逐出节点。
应用场景:
- 当节点需要维护、升级或存在严重问题时,可以使用NoExecute污点来确保不会有新的Pod被调度到该节点上,并且已经存在的Pod也会被安全地驱逐。
2. NoSchedule
定义:
- NoSchedule污点阻止所有不容忍该污点的Pod被调度到该节点上。
行为:
- 当节点被添加了NoSchedule污点后,调度器将不会将任何没有相应容忍度的Pod调度到该节点上。
- 但是,如果节点上已经运行了Pod,并且这些Pod没有设置容忍该NoSchedule污点的容忍度,这些Pod将继续在该节点上运行,不会被驱逐。
应用场景:
- 当节点被保留用于特定类型的Pod(如master节点通常不会被用于运行用户Pod)时,可以使用NoSchedule污点来确保只有具有相应容忍度的Pod才能被调度到该节点上。
3. PreferNoSchedule
定义:
- PreferNoSchedule污点表示Kubernetes会尽量避免将不容忍该污点的Pod调度到带有该污点的节点上,但如果没有其他可用节点,Pod仍可能被调度至此。
行为:
- 当节点被添加了PreferNoSchedule污点后,调度器会优先考虑将Pod调度到其他没有该污点或具有相应容忍度的节点上。
- 但是,如果集群中没有其他合适的节点可用,调度器仍然可能将Pod调度到带有PreferNoSchedule污点的节点上。
应用场景:
- 当节点具有某些不太理想的特性(如性能较低、资源较少等),但仍然可以作为备选节点时,可以使用PreferNoSchedule污点来指示调度器在可能的情况下避免使用该节点。