污点:使节点能够排斥一类特定的 pod。Taint 和 toleration 相互配合,可以用来避免pod 被分配到不合适的节点上。
节点亲和性:是pod的一种属性(偏好或硬性要求),它使pod被吸引到一类特定的节点。
taints:污点,定义在节点上,是键值数据
tolerations:容忍度,定义在pod上,可以定义能容忍哪些污点
污点的查看
[root@master ~]# kubectl describe nodes master | grep Taints
Taints: node-role.kubernetes.io/master:NoSchedule
....
[root@master ~]# kubectl explain node.spec.taints
NoSchedule 不会被调度
PreferNoSchedule 尽量不调度
NoExecute 驱逐节点
污点的添加与删除
[root@master ~]# kubectl taint nodes node1 key=value:NoSchedule
[root@master ~]# kubectl taint nodes node1 key:NoSchedule-
key=value:NoSchedule key:NoSchedule-
它的 key 键是 key,value 值是 value,effect行为是 NoSchedule。这表示只有拥有和这个 taint 相匹配的 toleration 的 pod 才能够被分配到 node1 这个节点。当然你也可以给一个节点添加多个 taint ,也可以给一个 pod 添加多个 toleration。
容忍度(pod.spec.tolerations)
effect、key、operator、tolerationSeconds、value
一个 toleration和一个 taint 相“匹配”是指它们有一样的key和effect ,operator 默认是 Equal ,即value 相等才匹配。如果operator是Exists,则toleration 不能指定 value。
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
tolerations:
- key: "key"
operator: "Exists"
effect: "NoSchedule"
如果一个 toleration 的 effect 为空,则 key 值与之相同就能完成匹配 ,taint的effect可以是任意值。
tolerations:
- key: "key"
operator: "Exists"
如果这个pod的所在节点打了该污点,配置了tolerationSeconds那么pod 还将继续在节点上运行 一段时间,如下3600 秒
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoExecute"
tolerationSeconds: 3600
使用场景
专用节点:如果你想将某些节点专门分配给特定的一组用户使用,你可以给这些节点添加一个 taint。如果要使pod 只能被分配到专用节点,那么你可以给节点打个标签,将 pod 的节点亲和性与容忍结合使用。
配备了特殊硬件的节点:在部分节点配备了特殊硬件(比如 GPU)的集群中,我们希望不需要这类硬件的 pod 不要被分配到这些特殊节点,以便为后继需要这类硬件的 pod 保留资源。
节点问题:当某种条件为真时,node controller会自动给节点添加一个 taint。当前内置的 taint 包括:
node.kubernetes.io/not-ready:节点未准备好。这相当于节点状态 Ready 的值为 “False”。
node.kubernetes.io/unreachable:node controller 访问不到节点
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: 节点不可调度。
比如,一个使用了很多本地状态的应用程序在网络断开时,仍然希望停留在当前节点上运行一段较长的时间,愿意等待网络恢复以避免被驱逐。在这种情况下,pod 的 toleration 可能是下面这样的:
tolerations:
- key: "node.kubernetes.io/unreachable"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 6000
注意,Kubernetes 会自动给 pod 添加 key 为 node.kubernetes.io/not-ready 的 toleration 并配置 tolerationSeconds=300,和key为node.kubernetes.io/unreachable 的 toleration 并配置 tolerationSeconds=300,除非用户提供的 pod 配置中已经已存在了这两个key。这种自动添加 toleration 机制保证了在其中一种问题被检测到时 pod 默认能够继续停留在当前节点运行 5 分钟。
自 Kubernetes 1.8 起, DaemonSet 控制器自动为所有守护进程添加如下 NoSchedule toleration 以防 DaemonSet 崩溃
node.kubernetes.io/memory-pressure
node.kubernetes.io/disk-pressure
node.kubernetes.io/out-of-disk (只适合 critical pod)
node.kubernetes.io/unschedulable (1.10 或更高版本)
node.kubernetes.io/network-unavailable (只适合 host network)
这里查看了一下之前创建的daemonset,fluentd的容忍
[root@master ~]# kubectl describe pod -n kube-system fluentd-elasticsearch-
Tolerations: :NoSchedule op=Exists
:NoExecute op=Exists
CriticalAddonsOnly op=Exists
node.kubernetes.io/disk-pressure:NoSchedule op=Exists
node.kubernetes.io/memory-pressure:NoSchedule op=Exists
node.kubernetes.io/network-unavailable:NoSchedule op=Exists
node.kubernetes.io/not-ready:NoExecute op=Exists
node.kubernetes.io/pid-pressure:NoSchedule op=Exists
node.kubernetes.io/unreachable:NoExecute op=Exists
node.kubernetes.io/unschedulable:NoSchedule op=Exists
污点容忍的举例
给node1打污点,创建pod,此时 Events:告诉我们两个节点,0个可用。两个节点都有taints。pod的创建时一致处于Pending ,是失败的
[root@master ~]# kubectl taint nodes node1 name=lucky:NoSchedule
node/node1 tainted
[root@master ~]# vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
[root@master ~]# kubectl apply -f pod.yaml
pod/pod-nginx created
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod-nginx 0/1 Pending 0 5s
[root@master ~]# kubectl describe pod pod-nginx
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 16s default-scheduler 0/2 nodes are available: 1 node(s) had taint {name: lucky}, that the pod didn't tolerate, 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate.
我们删除污点后pod在node1上创建成功
[root@master ~]# kubectl taint nodes node1 name:NoSchedule-
node/node1 untainted
[root@master ~]# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED
pod-nginx 1/1 Running 0 12s 10.244.1.87 node1
我们重新添加污点,发现已存在的pod不受影响
[root@master ~]# kubectl taint nodes node1 name=lucky:NoSchedule
node/node1 tainted
[root@master ~]# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE
pod-nginx 1/1 Running 0 3m25s 10.244.1.87 node1
删除pod,创建一个带有容忍的pod
[root@master ~]# kubectl delete -f pod.yaml
[root@master ~]# vim pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations:
- key: name
value: lucky
effect: NoSchedule
[root@master ~]# kubectl apply -f pod-pvc.yaml
可以看到pod已经创建成功
[root@master ~]# kubectl get pod -owide
NAME READY STATUS RESTARTS AGE IP NODE pod-nginx 1/1 Running 0 6m33s 10.244.1.87 node1
[root@master ~]# kubectl describe nodes node1 | grep Taints
Taints: name=lucky:NoSchedule
[root@master ~]# kubectl taint nodes node1 name:NoSchedule-
node/node1 untainted
对于tolerations属性的写法:
其中的key、value、effect 与Node的Taint设置需保持一致:
1、如果operator的值是Exists,则value属性可省略。
2、如果operator的值是Equal,则表示其key与value之间的关系是equal(等于)。
3、如果不指定operator属性,则默认值为Equal。
另外,还有两个特殊值:
1、空的key 如果再配合Exists ,就能匹配所有的key与value ,也就是能容忍所有node上的所有Taints。
2、空的effect,匹配所有的effect