Taint(污点)和Toleration(容忍度)可以作用于node和pod上,其目的是优化pod在集群间的调度,这跟节点亲和性类似;
只不过它们作用的方式相反,其用作确保pod不会被调度在指定的节点上。
为了可以让大家更简单、更直观的了解到污点和容忍度的意思,我这里画了个趣图。
如图所示,node节点上分别有云、五角星、十字架这三个不同组合的污点;Pod-A上有云和五角星的污点容忍度,Pod—B上则没有容忍度。
最终调度结果为:
1.Pod-A:调度至node-1和node-3
2.Pod-B:只会调度至node-3
注意:Taints(污点)存在于node,Tolerations(容忍度)存在于pod
再举个例子,3d的射击类游戏一般会让人有头晕目眩的感觉(这就是污点),如果你是长期射击类游戏的玩家(这就是容忍度),就不会有问题,且愿意尝试这块游戏(这就是完成匹配,准备调度)
此时,你对污点和容忍度应该有了较基础的了解了。
污点的容忍度配置主要有三个字段:key、value和effect,其中:
1>key:表示字段名,如图形
2>value:表示字段值,如云、五角星、十字架
3>effect:表示调度规则,其又细分:Noschedule、PreferNoSchedule和NoExecute三种
具体描述可参考下面的表格:
参数 | 描述 |
---|---|
key | string类型,最大长度253个字符,必须小写或数字开头 |
value | string类型,最大长度63个字符,必须小写或数字开头 |
effect:Noschedule | 1.不允许非法pod调度上来。2.taints变更后,不会驱离非法的pod |
effect:PreferNoSchedule | 1.最好不要把非法pod调度上来。2.taints变更后,不会驱离非法的pod |
effect:NoExecute | 1.不允许非法pod调度上来。2.taints变更后,会驱离非法的pod,驱离时间为tolerationSeconds |
就如我上面所说,无论是Taints还是Tolerations(污点和容忍度),都有三个字段:key、value和effect,那么他们是如何匹配工作的呢?
此时会用到一个判断控制器operator,具体匹配规则如下:
operator | 描述 |
---|---|
Equal | (默认) key、value和effect必须都相同 |
Exists | key和effect必须相同 |
需要注意operator没指定的话,默认是Equal。
另外,这里还有两个特殊用法:
tolerations:
- operator: "Exists"
1>Exists:空字段key,会匹配所有的keys, values and effects,意味着容忍所有
tolerations:
- key: "key"
operator: "Exists"
2>Exists:空effect,会匹配所有的键为"key"的effect
从K8S1.6开始支持了很多封装好的驱离式effect,node controller会根据实际情况,自动给node节点打上对应污点,保证了Pod调度的合理性和安全性,从而对生产环境保驾护航。
具体如下所示:
taint effect | 描述 |
---|---|
node.kubernetes.io/not-ready | 节点未就绪 |
node.kubernetes.io/unreachable | 节点不可达 |
node.kubernetes.io/out-of-disk | 节点地盘耗尽 |
node.kubernetes.io/memory-pressure | 内存存在压力 |
node.kubernetes.io/disk-pressure | 磁盘存在压力 |
node.kubernetes.io/network-unavailable | 网络不可用 |
node.kubernetes.io/unschedulable | 节点不可调度 |
node.cloudprovider.kubernetes.io/uninitialized | 节点未初始化,不可用 |
试想一下,如果没有这些内置的effect帮助会怎么样呢?
如果节点还未就绪,就有pod调度上来,又比如节点的硬盘资源已经满了,pod再调度上来?等等;
这是不是很不合理,也很可怕呢?
命令 | 说明 |
---|---|
kubectl taint -h | taint的帮助命令 |
kubectl taint nodes foo dedicated=special-user:NoSchedule | 给node打污点,修改时需要使用–overwrite=true进行覆盖 |
kubectl taint nodes foo dedicated:NoSchedule- | 移除taint污点 |
1)首先给centos-3这个节点打上污点,其key=department,value=ops,effect=NoSchedule
kubectl taint nodes centos-3.shared department=ops:NoSchedule
我们再来回顾一下NoSchedule的策略:
1.不允许非法pod调度上来。
2.taints变更后,不会驱离非法的pod。
2)接着,我们编辑filebeat-ds,并apply
注意:这时候的ds应该不会调度至我们打了污点的centos-3.shared节点上。
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: filebeat-ds
labels:
app: filebeat
spec:
selector:
matchLabels:
app: filebeat
template:
metadata:
labels:
app: filebeat
spec:
containers:
- name: filebeat
image: prima/filebeat:6.4.2
env:
- name: REDIS_HOST
value: db.ikubernetes.is:6379
- name: LOG_LEVEL
value: info
3)发现ds并没有部署到centos-3节点,污点配置生效,且和预期一致
[root@centos-1 dingqishi]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
filebeat-ds-tg7gf 0/1 ContainerCreating 0 3m2s centos-2.shared
4)接着,我们delete之前的yaml,重新编辑file-ds-tolerations.yaml(增加相关容忍度,希望能容忍centos-3.shared节点的污点),并apply
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: filebeat-ds
labels:
app: filebeat
spec:
selector:
matchLabels:
app: filebeat
template:
metadata:
labels:
app: filebeat
spec:
containers:
- name: filebeat
image: prima/filebeat:6.4.2
env:
- name: REDIS_HOST
value: test.db:6379
- name: LOG_LEVEL
value: info
tolerations:
- key: "department"
operator: "Equal"
value: "ops"
effect: "NoSchedule"
5)观察pod,发现centos-3.shared已经运行pod,新增的容忍度功能成功
[root@centos-1 dingqishi]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
filebeat-ds-l2png 0/1 ContainerCreating 0 2m43s centos-2.shared
filebeat-ds-qq2nc 0/1 ContainerCreating 0 2m43s centos-3.shared
6)接下来我们修改node3污点,测试Noschedule策略是否如期一致,是否会在taints变更后,不会驱离非法的pod?
kubectl taint nodes centos-3.shared department=test:NoSchedule --overwrite=true
7)我们发现pod还是在运行,并不会驱离,和预期一致
[root@centos-1 dingqishi]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
filebeat-ds-l2png 0/1 ContainerCreating 0 5m18s centos-2.shared
filebeat-ds-qq2nc 0/1 ContainerCreating 0 5m18s centos-3.shared
8)最后,我们将node3的污点effect修改为NoExecute,观察pod是否被驱离
如果没指定tolerationSeconds,就会马上驱离
kubectl taint nodes centos-3.shared department=test:NoExecute --overwrite=true
9)发现centos-3.shared上已经没有pod了,和预期一致
[root@centos-1 dingqishi]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
filebeat-ds-l2png 0/1 ImagePullBackOff 0 7m37s 10.244.1.7 centos-2.shared