污点与容忍

亲和性/反亲和性无论是硬策略还是软策略方式,都是调度 pod 到预期节点上,而Taints恰好与之相反,如果一个节点标记为 Taints ,除非 pod 也被标识为可以容忍污点节点,否则该 Taints 节点不会被调度 pod。

​ 污点:taints

​ 容忍:tolerations

污点策略

污点策略有以下选项:

  • NoSchedule:表示 pod 不会被调度到标记为 taints 的节点
  • PreferNoSchedule:NoSchedule 的软策略版本,表示尽量不调度到污点节点上去
  • NoExecute:该选项意味着一旦 Taint 生效,如该节点内正在运行的 pod 没有对应 Tolerate 设置,会直接被逐出

污点 taint 标记节点的命令如下:

1
2
$ kubectl taint nodes node02 test=node02:NoSchedule
node "node02" tainted

容忍

上面的命名将 node02 节点标记为了污点,影响策略是 NoSchedule,只会影响新的 pod 调度,如果仍然希望某个 pod 调度到 taint 节点上,则必须在 Spec 中做出Toleration定义,才能调度到该节点

比如现在我们想要将一个 pod 调度到 node02节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: apps/v1
kind: Deployment
metadata:
name: taint
labels:
app: taint
spec:
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: taint
template:
metadata:
labels:
app: taint
spec:
containers:
- name: nginx
image: nginx
ports:
- name: http
containerPort: 80
tolerations:
- key: "test"
operator: "Equal"
value: "node02"
effect: "NoSchedule"

由于 node02节点被标记为了污点节点,所以我们这里要想 pod 能够调度到 node02 节点去,就需要增加容忍的声明,以下两种方法均可:

1
2
3
4
5
6
7
8
9
10
tolerations:
- key: "test"
operator: "Equal"
value: "node02"
effect: "NoSchedule"
############################
tolerations:
- key: "test"
operator: "Exists"
effect: "NoSchedule"

一个容忍度和一个污点相“匹配”是指它们有一样的键名和效果,并且:

  • 如果 operatorExists (此时容忍度不能指定 value
  • 如果 operatorEqual ,则它们的 value 应该相等
  • 如果 operator 不指定,则默认为Equal

另外:

  • 空的 key 如果再配合 Exists 就能匹配所有的 key 与 value,也是是能容忍所有 node 的所有 Taints
  • 空的 effect 匹配所有的 effect

然后创建上面的资源,查看结果会发现有的pod会落在node02上

设置NoExcute 的驱逐时间

通常情况下,如果给一个节点添加了一个 effect 值为NoExecute的污点, 则任何不能忍受这个污点的 Pod 都会马上被驱逐, 任何可以忍受这个污点的 Pod 都不会被驱逐。

但是,如果 Pod 存在一个 effect 值为NoExecute的容忍度指定了可选属性tolerationSeconds的值,则表示 Pod 还能继续在节点上运行的时间。

1
2
3
4
5
6
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600

这表示如果这个 Pod 正在运行,这时候被打上了NoExecute的污点, 那么 Pod 还将继续运行 3600 秒,然后被驱逐。 如果在3600秒内污点被删除了,Pod就不会被驱逐。

取消污点

取消节点的污点标记,只需要在刚刚创建污点命令的结尾添加个“-”即可:

1
2
$ kubectl taint nodes node02 test=node02:NoSchedule-
node "node02" untainted

查看污点

1
2
3
kubectl describe node <node>|grep Taints

Taints: deploy=node4:NoSchedule

驱逐维护

挂维护,禁止调度

1
# kubectl cordon node02

设置node02不可调度,通过get node查看各节点状态,发现node02为SchedulingDisabled,此时新的pod不会调度到该节点上,但是现有的pod还是正常运行。

驱逐

1
# kubectl drain node02 --delete-local-data --ignore-daemonsets --force

参数说明:

--delete-emptydir-data 即使有使用emptyDir的pod也删除

--ignore-daemonsets 删除daemonsets管理的pod

--force 强制驱逐

--pod-selector 条件标签

  • --pod-selector="app in (test1, test2)" 驱逐app=test1和test2的pod
  • --pod-selector="app!=test1, app!=test2" 驱逐app!=test1和app!=test2的pod

我们可以通过不断kubectl get pod -o wide 观察到pod在驱逐迁移的过程

解除维护,解除禁止调度

1
# kubectl uncordon node02

解除后新的pod可以调度到node2节点,但是之前驱逐走的不会主动回来,需要重启pod后通过系统调度选择才有可能回到此节点

Node label

添加

语法:
kubectl label nodes kube-node label_name=label_value

样例:

先查看node列表

1
2
3
[root]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready <none> 16d v1.19.4

node1添加标签

1
kubectl label nodes node1 gpu=true

查询

1
2
3
4
5
# 根据label条件筛选node
kubectl get node -a -l gpu=true

# 查询node并展示label
kubectl get node --show-labels

删除

删除一个Label,只需在命令行最后指定Label的key名并与一个减号相连即可:

1
$ kubectl label nodes node1 gpu-

修改

修改一个Label的值,需要加上--overwrite参数:

1
$ kubectl label nodes node1 gpu=false --overwrite

或者也可以直接kubectl edit就可以编辑这个node的配置,保存退出就可以了!