概述
taints 和 tolerations 是一个比较好理解的概念,taints 可以翻译为污点,给 node 打上 taints,就可以用来驱逐 pod,并防止 pod 调度到该节点上。就像是某个人有了一个坏习惯(taints),那么其他人的就会远离这个人。但是有些人可以容忍别人的坏习惯,那么就会不受影响。就像 pod 拥有了 tolerations,就可以免疫节点上对应的 taints。
taints 的官方说明为:
The node this Taint is attached to has the “effect” on any pod that does not tolerate the Taint.
也就是说,taint 会为所有不能忍受该 taint 的 pod 添加副作用(不调度,偏好不调度,不执行)
如果要让某些 pod 免疫这些 taints,可以使用 tolerations。
taints 的使用
在使用 taints 的时候很简单,我们只需要指定节点 taints 的 key 和 value 即可。比如:
$ kubectl taint nodes minikube onlyNginxPod=true:NoSchedule
其中,onlyNginxPod 是 taints 的 key,true 是 value,NoSchedule 是 effect。另外还有 PreferNoScheduler 和 NoExecute。这里顺便总结一下这三种 effect 的区别:
- NoSchedule: 表示不要将 Pod 向该节点调度。如果 Pod 已经调度到该节点了,则不受影响。
- PreferNoScheduler: 表示尽量不要往该节点调度,但是如果没有其他选择,还是会将 Pod 调度到该节点。
- NoExecute: Pod 不仅不能往上调度,所有已经运行在该节点上的 Pod 将会被驱逐。
这个时候,我们尝试创建一个普通的 pod,看看调度情况。
pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: default
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
$ kubectl apply -f pod-nginx.yaml
$ kubectl describe pods nginx
Warning FailedScheduling <unknown> default-scheduler 0/1 nodes are available: 1 node(s) had taint {onlyNginxPod: true}, that the pod didn't tolerate.
会出现上面的警告信息。表示因为 pod 没有容忍该 taint,所以没有办法调度上去。
我们可以用以下语句来删除 taint
$ kubectl taint node minikube onlyNginxPod=true:NoSchedule-
tolerations 的使用
某些情况下,我们仍然希望 Pod 可以调度到有 taint 的节点上,这时候就可以为 Pod 指定 tolerations。比如将上面的 Pod 改写成如下:
pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: default
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
tolerations:
- key: onlyNginxPod
operator: Equal
value: "true"
effect: NoSchedule
然后创建这个 Pod,
···yaml
kubectl apply -f pod.yaml kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 0/1 ContainerCreating 0 4s
···
说明该 pod 调度成功,tolerations 生效了。tolerations 会匹配 key 和 effect,只有一样的时候才会生效。tolerations 的 operator 字段除了 Equal
之外,还有 Exists
。
- Equal: 要求 value 也相同。
- Exists: 不需要设置 value 字段。
kubernetes 中使用 taints 和 tolerations 的常用场景
taints 和 tolerations 不仅仅是提供给用户使用的特性,kubernetes 本身也大量使用了 taints 和 tolerations。比如:
-
node.kubernetes.io/not-ready
: Node 还没准备好,对应的 NodeCondition 的Ready
为False
。比如在创建集群时,还没有安装 CNI 的话,节点就会有该 taint。对应的 effect 为 NoSchedule。 -
node.kubernetes.io/unreachable
: node controller 无法连接到 Node,此时 NodeCondition 的Ready
为Unknown
。对应的 effect 为 NoSchedule。 -
node.kubernetes.io/out-of-disk
: 磁盘用尽。对应的 effect 为 NoSchedule。 -
node.kubernetes.io/memory-pressure
: 节点有内存的压力。对应的 effect 为 NoSchedule。 -
node.kubernetes.io/disk-pressure
: 节点有磁盘压力。和四个参数有关:nodefs.available, nodefs.inodesFree, imagefs.available, imagefs.inodesFree。nodefs 是用来存储卷和 daemon 日志的,imagefs 是容器运行时用来存储镜像和容器可写层的。当这些值到达某个阈值,就会出现 disk-pressure。对应的 effect 为 NoSchedule。 -
node.kubernetes.io/network-unavailable
: 节点的网络还不可用。对应的 effect 为 NoSchedule。 -
node.kubernetes.io/unschedulable
: 节点是不可调度的。对应的 effect 为 NoSchedule。 -
node.kubernetes.io/pid-pressure
: 节点上的进程太多。对应的 effect 为 NoSchedule。