目录
[1、 案例演示](#1、 案例演示)
[2.2 pod节点反亲和性](#2.2 pod节点反亲和性)
[2.3 换一个topologykey](#2.3 换一个topologykey)
[2.3、Equal 与 Exists](#2.3、Equal 与 Exists)
一、node节点选择器
我们在创建pod资源的时候,pod会根据schduler进行调度,那么默认会调度到随机的一个工作节点,如果我们想要pod调度到指定节点或者调度到一些具有相同特点的node节点,怎么办呢?
可以使用pod中的nodeName或者nodeSelector字段指定要调度到的node节点。
1、nodeName
指定pod节点运行在哪个具体node上
案例:
编辑yaml文件
创建pod
cpp
[root@k8s-master pvc]# vim pod-node.yaml
apiVersion: v1
kind: Pod
metadata:
name: demo-pod1
namespace: default
labels:
app: myapp
env: dev
spec:
nodeName: k8s-node1 ##指向node节点的host主机名
containers:
- name: nginx-nodename
ports:
- containerPort: 80
image: nginx
imagePullPolicy: IfNotPresent
提交
cpp
[root@k8s-master pvc]# kubectl apply -f pod-node.yaml
pod/demo-pod1 created
查看pod运行在哪个节点
cpp
[root@k8s-master pvc]# kubectl get pod demo-pod1 -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-pod1 1/1 Running 0 22s 10.244.36.106 k8s-node1 <none>
2、nodeSelector
案例
指定pod调度到具有哪些标签的node节点上
cpp
#给node节点打标签,打个具有disk=ceph的标签
[root@k8s-master ~]# kubectl label nodes k8s-node1 node=worker01
#查看节点的详细信息
[root@hd1 node]# kubectl describe nodes k8s-node1
#定义pod的时候指定要调度到具有 node=worker01标签的node上
cpp
[root@k8s-master pvc]# vim pod-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: demo-pod-1
namespace: default
labels:
app: myapp1
env: dev
spec:
nodeSelector:
node: worker01
containers:
- name: nginx-nodename1
ports:
- containerPort: 8080
protocol: TCP
image: nginx
imagePullPolicy: IfNotPresent
提交
cpp
[root@k8s-master pvc]# kubectl apply -f pod-1.yaml
pod/demo-pod-1 created
查看pod是否运行在k8s-node1节点
cpp
[root@k8s-master pvc]# kubectl get po demo-pod-1 -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-pod-1 1/1 Running 0 72s 10.244.36.85 k8s-node1 <none> <none>
labels位置(标签),添加了标签 node=worker01

二、Pod亲和性
生产上为了保证应用的高可用性,需要将同一应用的不同pod分散在不同的宿主机上,以防宿主机出现宕机等情况导致pod重建,影响到业务的连续性。要想实现这样的效果,需要用到k8s自带的pod亲和性和反亲和性特性。
Pod 的亲和性与反亲和性有两种类型:
requiredDuringSchedulingIgnoredDuringExecution ##一定满足
preferredDuringSchedulingIgnoredDuringExecution ##尽量满足
**podAffinity(亲和性):**pod和pod更倾向腻在一起,把相近的pod结合到相近的位置,如同一区域,同一机架,这样的话pod和pod之间更好通信,比方说有两个机房,这两个机房部署的集群有1000台主机,那么我们希望把nginx和tomcat都部署同一个地方的node节点上,可以提高通信效率;
**podAntiAffinity(反亲和性):**pod和pod更倾向不腻在一起,如果部署两套程序,那么这两套程序更倾向于反亲和性,这样相互之间不会有影响。
第一个pod随机选则一个节点,做为评判后续的pod能否到达这个pod所在的节点上的运行方式,这就称为pod亲和性;我们怎么判定哪些节点是相同位置的,哪些节点是不同位置的;我们在定义pod亲和性时需要有一个前提,哪些pod在同一个位置,哪些pod不在同一个位置,这个位置是怎么定义的,标准是什么?以节点名称为标准,这个节点名称相同的表示是同一个位置,节点名称不相同的表示不是一个位置。
1、 案例演示
pod节点亲和性
编辑pod的yaml文件
cpp
[root@k8s-master pvc]# vim pod-required-affinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app2: myapp2
tier: frontend
spec:
containers:
- name: myapp
image: nginx
imagePullPolicy: IfNotPresent
cpp
[root@k8s-master pvc]# vim pod-required-affinity-demo1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-second
labels:
app: backend # 标签:应用为 backend
tier: db # 标签:层级为 db
spec:
containers:
- name: busybox
image: busybox:1.28
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 3600"] # 容器启动命令:运行 shell 并休眠 3600 秒
affinity: # 亲和性配置
podAffinity: # Pod 亲和性规则
requiredDuringSchedulingIgnoredDuringExecution: # 硬性要求(调度期间必须满足,执行期间忽略)
- labelSelector: # 标签选择器(用于选择目标 Pod)
matchExpressions: # 匹配表达式(用于更复杂的标签匹配)
- key: app2 # 标签键:app2
operator: In # 操作符:在...之中
values: # 值列表
- myapp2 # 值:myapp2 (要求目标 Pod 具有标签 app2=myapp2)
topologyKey: kubernetes.io/hostname # 拓扑域键:基于节点主机名 (要求目标 Pod 与当前 Pod 在同一个节点上)
上面表示创建的pod必须与拥有app=myapp2标签的pod在一个节点上
提交资源清单
cpp
[root@k8s-master pvc]# kubectl apply -f pod-required-affinity-demo.yaml
pod/pod-first created
[root@k8s-master pvc]# kubectl apply -f pod-required-affinity-demo1.yaml
pod/pod-second created
查看pod,在同一个节点上
cpp
[root@k8s-master pvc]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-first 1/1 Running 0 18s 10.244.36.97 k8s-node1 <none> <none>
pod-second 1/1 Running 0 15s 10.244.36.99 k8s-node1 <none>
2.2 pod节点反亲和性
先删除上面创建的pod
cpp
[root@k8s-master pvc]# kubectl delete pod pod-first
pod "pod-first" deleted
[root@k8s-master pvc]# kubectl delete pod pod-second
pod "pod-second" deleted
[root@k8s-master pvc]#
创建反亲和性的pod
cpp
[root@k8s-master pvc]# vim pod-required-affinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app2: myapp2
tier: frontend
spec:
containers:
- name: myapp
image: nginx
imagePullPolicy: IfNotPresent
cpp
[root@k8s-master pvc]# vim pod-required-affinity-demo1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-second
labels:
app: backend
tier: db
spec:
containers:
- name: busybox
image: busybox:1.28
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 3600"]
affinity:
podAntiAffinity: # Pod 反亲和性规则
preferredDuringSchedulingIgnoredDuringExecution: # 软性偏好(调度期间尽量满足,执行期间忽略)
- weight: 100 # 权重值(范围 1-100,值越高偏好越强)
podAffinityTerm:
labelSelector:
matchExpressions: # 匹配表达式
- key: app2
operator: In
values:
- myapp2
topologyKey: kubernetes.io/hostname
上面表示创建的pod与拥有app=myapp2标签的pod不会在同一个节点上
提交资源清单
cpp
[root@k8s-master pvc]# kubectl apply -f pod-required-affinity-demo.yaml
pod/pod-first created
[root@k8s-master pvc]# kubectl apply -f pod-required-affinity-demo1.yaml
pod/pod-second created
查看pod
结果表明两个pod不在同一节点上
cpp
[root@k8s-master pvc]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-first 1/1 Running 0 3m28s 10.244.36.100 k8s-node1 <none> <none>
pod-second 1/1 Running 0 11s 10.244.169.186 k8s-node2 <none> <none>
2.3 换一个topologykey
详细说明:
-
kubectl label
Kubernetes 管理标签的命令。 -
node k8s-node2
操作对象:名为k8s-node2
的节点。 -
zone=foo
标签内容:键为zone
,值为foo
。 -
--overwrite
强制覆盖:如果该节点已有zone
标签,则更新其值;若未指定此参数,对已存在的标签重复操作会报错。
创建pod
cpp
[root@k8s-master pvc]# vim pod-first-required-anti-affinity-demo-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod3-first
labels:
app3: myapp3
tier: frontend
spec:
containers:
- name: myapp
image: nginx
imagePullPolicy: IfNotPresent
cpp
[root@k8s-master pvc]# vim pod-second-required-anti-affinity-demo-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod3-second
labels:
app: backend # 标签:应用为 backend
tier: db # 标签:层级为 db
spec:
containers:
- name: busybox
image: busybox:1.28
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 3600"] # 容器启动命令:运行 shell 并休眠 3600 秒
affinity: # 亲和性配置
podAntiAffinity: # Pod 反亲和性规则
requiredDuringSchedulingIgnoredDuringExecution: # 硬性要求(调度期间必须满足,执行期间忽略)
- labelSelector: # 标签选择器(用于选择要避免的 Pod)
matchExpressions: # 匹配表达式
- key: app3 # 标签键:app3
operator: 'In' # 操作符:在...之中
values: ["myapp3"] # 值列表:myapp3 (要避免的 Pod 具有标签 app3=myapp3)
topologyKey: zone # 拓扑域键:基于自定义标签 zone (避免与目标 Pod 在同一个 zone 域内)
提交资源清单
cpp
[root@k8s-master pvc]# kubectl apply -f pod-first-required-anti-affinity-demo-1.yaml
pod/pod3-first created
[root@k8s-master pvc]# kubectl apply -f pod-second-required-anti-affinity-demo-2.yaml
pod/pod3-second created
查看pod
cpp
[root@k8s-master pvc]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod3-first 1/1 Running 0 14s 10.244.36.102 k8s-node1 <none> <none>
pod3-second 0/1 Pending 0 8s <none> <none> <none>
cpp
#发现第二个节点是pending,因为两个节点是同一个位置,现在不是同一个位置的了,而且我们要求反亲和性,所以就会处于pending状态,如果在反亲和性这个位置把required改成preferred,那么也会运行。
#podaffinity:pod节点亲和性,pod倾向于哪个pod
#nodeaffinity:node节点亲和性,pod倾向于哪个node
三、污点与容忍
核心思想:
- 污点(Taint): 打在节点(Node) 上。它表示该节点具有某种"排斥性"或"特性",拒绝那些不能"忍受"这种特性的 Pod 调度上来。
- 容忍(Toleration): 打在 Pod 上。它表示该 Pod 能够"忍受"一个或多个特定的污点。只有 Pod 容忍了节点上的污点,该 Pod 才有可能被调度到该节点上。
为什么需要污点和容忍?
污点和容忍提供了一种基于节点特性来排斥 Pod 的机制,常用于以下场景:
- 专用节点: 将某些节点(如 GPU 节点、高内存节点)保留给特定的工作负载(如 AI 训练、内存数据库)。给这些节点打上污点,只有声明了相应容忍的 Pod 才能使用它们。
- 节点隔离:
- 维护隔离: 准备对节点进行维护(如升级内核、更换硬件)时,给节点打上污点(如
effect: NoSchedule
),阻止新 Pod 调度上来。然后可以安全地驱逐或删除现有 Pod(可能需要结合effect: NoExecute
)。 - 问题隔离: 当节点出现硬件问题或软件异常时,打上污点阻止新 Pod 调度上来,防止问题扩散。
- 维护隔离: 准备对节点进行维护(如升级内核、更换硬件)时,给节点打上污点(如
- 基于节点特性调度: 比如区分云服务商的不同可用区(Availability Zone)、不同的硬件类型(SSD vs HDD)、不同的网络类型(高性能网络)等。通过污点标记节点特性,Pod 通过容忍来选择。
- 控制 Pod 驱逐: 使用
NoExecute
污点可以控制哪些 Pod 在节点出现问题时(如网络分区、磁盘压力)会被驱逐。
污点(Taint)的组成:
一个污点由三部分组成,格式为:key=value:effect
- **
key
:** 污点的键(字符串)。用于标识污点的类型或来源(如gpu
,dedicated
,zone
)。 - **
value
:** 污点的值(字符串,可选)。提供更具体的描述(如nvidia
,app-team-a
,east-1
)。如果key
相同但value
不同,则视为不同的污点。 - **
effect
: 污点的 效果**(必需)。定义了当 Pod 不能容忍该污点时,调度器或节点应如何行动。有三种效果:- **
NoSchedule
:**- 调度时: Kubernetes 调度器不会 将不能容忍 此污点的 Pod 调度到该节点上。
- 执行时: 不影响已经在该节点上运行的 Pod(即使它们不能容忍此污点)。
- 用途: 预留节点、开始维护前阻止新 Pod 调度。
- **
PreferNoSchedule
:**- 调度时: Kubernetes 调度器会尽量避免 将不能容忍此污点的 Pod 调度到该节点上。但如果没有其他合适的节点可用,调度器仍然会将 Pod 调度到该节点上。
- 执行时: 不影响已经在该节点上运行的 Pod。
- 用途: 软性偏好,建议但不强制 Pod 不要调度到某些节点。
- **
NoExecute
:**- 调度时: 与
NoSchedule
效果相同,调度器不会将不能容忍此污点的 Pod 调度到该节点上。 - 执行时: 影响 已经在该节点上运行的 Pod:
- 如果一个 Pod 不能容忍 一个
NoExecute
污点,那么该 Pod 会立即被该节点驱逐(Evicted)。 - 如果一个 Pod 能够容忍 一个
NoExecute
污点,但它没有在容忍度中指定tolerationSeconds
,则该 Pod 会一直运行在该节点上。 - 如果一个 Pod 能够容忍 一个
NoExecute
污点,并且指定了tolerationSeconds
,则该 Pod 会在该节点上继续运行指定的秒数(tolerationSeconds
),超过这个时间后也会被驱逐。
- 如果一个 Pod 不能容忍 一个
- 用途: 节点出现不可恢复的问题时(如硬件故障、网络断开),驱逐所有 Pod;或者给 Pod 一个宽限期(
tolerationSeconds
)让其优雅终止。
- 调度时: 与
- **
容忍(Toleration)的组成:
一个容忍度定义在 Pod 的 spec.tolerations
字段下。它告诉调度器该 Pod 可以容忍哪些污点。主要字段:
- **
key
:** (可选,但通常建议指定) 要匹配的污点的key
。如果为空,则匹配所有污点的key
。 - **
operator
:** (必需) 指定key
和value
之间的匹配关系。有两种操作符:- **
Equal
:** 要求污点的value
必须等于容忍度中指定的value
。这是最常用的操作符。 - **
Exists
: 只要污点存在指定的key
即可,不检查污点的value
。此时容忍度中的value
字段必须为空**。
- **
- **
value
: (当operator
是Equal
时必需;当operator
是Exists
时 不能**设置) 要匹配的污点的value
。 - **
effect
:** (可选) 要匹配的污点的effect
(NoSchedule
,PreferNoSchedule
,NoExecute
)。如果为空,则表示容忍所有effect
。 - **
tolerationSeconds
:** (仅当effect
是NoExecute
时相关,可选) 指定 Pod 在被NoExecute
污点驱逐前,可以在节点上继续运行的秒数。仅对NoExecute
污点有效。
关键点:
- 容忍不是"选择": 容忍只是让 Pod 有资格被调度到带有污点的节点上,但并不保证一定会调度上去。调度还受其他因素影响(如资源请求/限制、节点选择器、亲和性规则)。
- 污点与容忍的匹配: 一个 Pod 要被调度到一个带有污点的节点上,该 Pod 必须显式地容忍该节点上的所有污点 (除了
effect
为PreferNoSchedule
的污点,它只是偏好而非强制)。如果节点上有多个污点,Pod 需要容忍所有污点才能被调度。 - **
NoExecute
的特殊性:**NoExecute
污点不仅影响调度,还影响运行中的 Pod,可能导致驱逐。
操作命令:
-
给节点添加污点:
cppkubectl taint nodes <node-name> key=value:effect # 示例:给节点 node1 添加一个排斥所有不能容忍 gpu 的 Pod 的污点 kubectl taint nodes node1 gpu=true:NoSchedule # 示例:给节点 node2 添加一个 NoExecute 污点,驱逐所有不能容忍的 Pod kubectl taint nodes node2 unrecoverable=true:NoExecute
-
查看节点污点:
kubectl describe node <node-name> | grep Taints # 或者 kubectl get node <node-name> -o jsonpath='{.spec.taints}'
-
移除节点污点:
kubectl taint nodes <node-name> key:effect- # 示例:移除 node1 上 key 为 gpu, effect 为 NoSchedule 的污点 kubectl taint nodes node1 gpu:NoSchedule- # 移除 node1 上所有 key 为 gpu 的污点(不管 effect) kubectl taint nodes node1 gpu-
1、污点(Taints)
污点的优先级高于nodename和nade
设置污点后,一般Pod将不会调度到该节点上来。每次Pod都不会调度到master节点,那是因为搭建K8s集群的时候,K8s给master自带了一个污点。
1.1、查看污点
查看master上是否有污点,通过describe命令可以看到节点上的所有污点
cpp
[root@k8s-master pvc]# kubectl describe node k8s-master
详细解释:
-
污点键 (Key):
node-role.kubernetes.io/control-plane
-
这是 Kubernetes 内置的系统级标签/污点键。
-
它标识该节点是 控制平面节点 (Control Plane Node) ,即 Master 节点(如运行
kube-apiserver
,etcd
,kube-scheduler
,kube-controller-manager
的节点)。
-
-
污点效果 (Effect):
NoSchedule
-
调度时效果: Kubernetes 调度器 不会 将 不能容忍此污点 的 Pod 调度到该节点上。
-
执行时效果: 不影响 已在该节点上运行的 Pod(即使它们不能容忍此污点)。
-
发现master上自带了一个没有value的污点 node-role.kubernetes.io/control-plane ,effect 为 NoSchedule,由于我们的Pod都没有容忍这个污点,所以一直都不会调度到master
1.2、污点类别
上面我们看到了污点有一个effect 属性为NoSchedule,其实还有其它两种类别分别是 PreferNoSchedule与 NoExecute
-
NoSchedule: 如果没有容忍该污点就不能调度进来。
-
PreferNoSchedule: 相当于NoExecute的一个软限制,如果没有容忍该污点,尽量不要把Pod调度进来,但也不是强制的。
-
NoExecute: 如果没有设置容忍该污点,新的Pod肯定不会调度进来, 并且已经在运行的Pod没有容忍该污点也会被驱逐。
1.3、设置污点
污点分别由key、value(可以为空)、effect 组成,设置命令如下
cpp
# 设置污点并不允许Pod调度到该节点
$ kubectl taint node k8s-node1 key=value:NoSchedule
# 设置污点尽量不要让Pod调度到该节点
$ kubectl taint node k8s-node1 key=value:PreferNoSchedule
# 设置污点,不允许Pod调度到该节点,并且且将该节点上没有容忍该污点的Pod将进行驱逐
$ kubectl taint node k8s-node1 key=value:NoExecute
1.4、删除污点
cpp
# 删除该key的所有污点
$ kubectl taint node k8s-node1 key-
# 删除该key的某一个污点
$ kubectl taint node k8s-node1 key=value:NoSchedule-
# 删除该key的某一个污点可以不写value
$ kubectl taint node k8s-node1 key:NoSchedule-
1.5、污点测试
给k8s-node1节点设置一个污点,表示只有前台web应用才能调度,后端app应用不能调度
cpp
[root@k8s-master ~]# kubectl taint node k8s-node1 web=true:NoSchedule
node/k8s-node1 tainted
编写 web-taint.yaml 内容如下,有三个Pod均没有容忍该污点
cpp
apiVersion: v1
kind: Pod
metadata:
name: web-taint1
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent # 本地有不拉取镜像
---
apiVersion: v1
kind: Pod
metadata:
name: web-taint2
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent # 本地有不拉取镜像
---
apiVersion: v1
kind: Pod
metadata:
name: web-taint3
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent # 本地有不拉取镜像
启动Pod,观察Pod是否都被调度到k8s-node2节点
cpp
# 启动三个Pod
[root@k8s-master taint]# kubectl apply -f web-taint.yaml
pod/web-taint1 applyd
pod/web-taint2 applyd
pod/web-taint3 applyd
# 查看pod详情发现均被调度到k8s-node2节点
[root@k8s-master taint]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-taint1 1/1 Running 0 13s 10.244.2.35 k8s-node2 <none> <none>
web-taint2 1/1 Running 0 13s 10.244.2.34 k8s-node2 <none> <none>
web-taint3 1/1 Running 0 13s 10.244.2.36 k8s-node2 <none> <none>
给k8s-node2节点添加污点 app=true:NoExecute,表示只有后端服务才能调度进来,并且已经在k8s-node2节点上运行的不是后端服务的节点将被驱逐
cpp
# 设置污点
[root@k8s-master taint]# kubectl taint node k8s-node2 app=true:NoExecute
node/k8s-node2 tainted
# 查看Pod详情,发现三个Pod已经被驱逐
[root@k8s-master taint]# kubectl get pod -o wide
No resources found in default namespace.
从上面可以知道我们虽然设置了污点,但是我们的节点其实很正常,既然是正常节点,那么就可以有服务运行,这就需要用到容忍机制来运行这些Pod
2、容忍(Toletations)
如果需要Pod忽略Node上的污点,就需要给Pod设置容忍,并且是需要容忍该Pod上的所有污点。
通过 kubectl explain pod.spec.tolerations 可以查看容忍的配置项
2.1、配置项
cpp
tolerations: # 数组类型,可以设置多个容忍
- key: # 污点key
operator: # 操作符,有两个选项 Exists and Equal 默认是Equal
value: # 污点value,如果使用Equal需要设置,如果是Exists就不需要设置
effect: # 可以设置为NoSchedule、PreferNoSchedule、NoExecute,如果为空表示匹配该key下所有污点,
tolerationSeconds: # 如果污点类型为NoExecute,还可以设置一个时间,表示这一个时间段内Pod不会被驱逐,过了这个时间段会立刻驱逐,0或者负数会被立刻驱逐
2.2、设置容忍
给Pod设置容忍k8s-node1节点的污点web=true:NoSchedule
编写 web-tolerations.yaml 内容如下,容忍污点web=true:NoSchedule
cpp
apiVersion: v1
kind: Pod
metadata:
name: web-tolerations
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent # 本地有不拉取镜像
tolerations:
- key: web
operator: Equal
value: "true"
effect: NoSchedule
启动web-tolerations,观察Pod是否正常运行
cpp
# 启动web-tolerations
[root@k8s-master taint]# kubectl apply -f web-tolerations.yaml
pod/web-tolerations applyd
# Pod正常运行,且运行在k8s-node1节点
[root@k8s-master taint]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-tolerations 1/1 Running 0 8s 10.244.1.92 k8s-node1 <none> <none>
查看该Pod上的容忍
cpp
[root@k8s-master taint]# kubectl describe pod web-tolerations
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
web=true:NoSchedule
可以看到我们设置的Tolerations在里边,除了我们自己的,K8s还会给每个Pod设置两个默认Tolerations,并且Tolerations时间为五分钟,表示某些节点发生一些临时性问题,Pod能够继续在该节点上运行五分钟等待节点恢复,并不是立刻被驱逐,从而避免系统的异常波动。
编写 app-tolerations.yaml 内容如下,容忍污点app=true:NoExecute,并且只容忍60s
cpp
apiVersion: v1
kind: Pod
metadata:
name: app-tolerations
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations:
- key: app
operator: Exists
effect: NoExecute
tolerationSeconds: 60
启动app-tolerations,查看Pod是否能够正常运行,且运行在k8s-node2节点,等待60秒,查看Pod是否已被驱逐
cpp
# 启动app-tolerations
[root@k8s-master taint]# kubectl apply -f app-tolerations.yaml
pod/app-tolerations applyd
# 查看详情,已经运行成功并且调度到了k8s-node2节点,此时运行59秒
[root@k8s-master taint]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
app-tolerations 1/1 Running 0 59s 10.244.2.37 k8s-node2 <none> <none>
# 运行60秒查看,状态已经变为Terminating
[root@k8s-master taint]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
app-tolerations 1/1 Terminating 0 60s 10.244.2.37 k8s-node2 <none> <none>
# 立刻再次查看,已经被驱逐
[root@k8s-master taint]# kubectl get pod -o wide
No resources found in default namespace.
如果一个节点没有任何污点,另一个节点有污点,并且Pod容忍了该污点,那么最终会调度到哪个节点呢?
删除k8s-node2节点的污点app=true:NoExecute,保留k8s-node1节点的web=true:NoSchedule,再次启动之前的web-tolerations.yaml 观察Pod所在节点
cpp
# 删除k8s-node2上的污点
[root@k8s-master taint]# kubectl taint node k8s-node2 app:NoExecute-
node/k8s-node2 untainted
# 启动Pod web-tolerations
[root@k8s-master taint]# kubectl apply -f web-tolerations.yaml
pod/web-tolerations applyd
# Pod正常运行,并且运行在k8s-node2节点
[root@k8s-master taint]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-tolerations 1/1 Running 0 2s 10.244.2.38 k8s-node2 <none> <none>
上面表明,即使是容忍了该污点,如果有其它节点不需要容忍就可以调度的话,那还是会优先选择没有污点的机器,但是生产上往往设置污点就是为了给你这个Pod使用的,不能调度到其它节点,这个时候需要配合节点亲和性调度一起使用。
2.3、Equal 与 Exists
Equal (等于) 精确匹配
Exists (存在) 模糊匹配
Exists (存在)表示key是否存在所以无需设置value,Equal 则必须设置value需要完全匹配,默认为Equal
空的key配合Exists 可以匹配所有的key-value,也就是容忍所有的污点,生产上非常不建议使用