一、应用场景
我们部署的kubernetes集群可能存在跨地区、跨机房以及不同服务器配置的情况,比如配置了GPU的服务器用于部署AI相关应用。因此我们希望kubernetes创建的Pod能够按照我们的意愿进行部署,比如GPU服务器节点只用于AI应用部署,而其他应用不要部署到该节点上。
此时我们或许可以用NodeSelector来满足上面的需求,采用打标签的方式,在不同节点打上不同的标签,比如GPU节点打上gpu-server标签,普通节点打上normal-server节点,我们定义Pod时通过nodeSelector选择要部署的节点标签。但是这种方案存在一个漏洞,就是Pod如果一时疏忽忘记配置了nodeSelector,那么Pod是可以随意部署的,因为kubernetes不会根据node节点上的标签去主动调度Pod的创建。
kubernetes提供了更好的方案来满足我们的需求,就是采用污点机制,我们可以在node节点上创建污点并指定污点效果,当Pod不能容忍该node污点时,kubernetes会根据污点效果进行调度。比如我们的gpu node节点创建污点gpu-server=true:NoExecute,那么我们的Pod如果不能容忍该污点的话,就会被从该节点上驱逐出去,且不再进行调度到该节点。
二、简单使用
污点Taint和容忍度Toleration是配套使用的,当node节点创建了污点,那么如果Pod要在该节点上调度的话,则需要在Pod配置中添加对应的容忍度。
1、 创建污点
kubectl taint node 节点名称 key=value:污点效果
(1)其中value值是可选的,如果不指定value值的话,可以这样配置:key:污点效果
(2)污点效果包括:
(a)NoSchedule:不调度Pod到该节点上。
(b)PreferNoSchedule:尽量不调度,但也不是不可以。
(c)NoExecute:不能在该节点上运行Pod,如果已经运行了,会被驱逐出去。
kubectl taint node test-99 gpu-server=true:NoExecute
2、查看污点
可以通过kubectl describe node 节点名称,从具体的配置描述中找到污点配置信息。
[root@test-99 deployments]# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
develop Ready work 5d3h v1.21.0 172.16.1.15 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 docker://20.10.8
test-99 Ready master 5d3h v1.21.0 172.16.1.17 <none> CentOS Linux 7 (Core) 4.19.12-1.el7.elrepo.x86_64 docker://20.10.22
[root@test-99 deployments]# kubectl describe node test-99
Name: test-99
Roles: master
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/arch=amd64
kubernetes.io/hostname=test-99
kubernetes.io/os=linux
node-role.kubernetes.io/master=
node.kubernetes.io/node=
Annotations: node.alpha.kubernetes.io/ttl: 0
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Mon, 26 Dec 2022 16:51:14 +0800
Taints: gpu-server=true:NoExecute
... ...
3、修改污点配置
创建污点时通过 --overwrite 来覆盖原来的污点。
[root@test-99 deployments]# kubectl taint node test-99 gpu-server=1:NoExecute --overwrite
node/test-99 modified
4、 删除污点
通过减号-来删除污点,也就是 污点 key:污点效果-
[root@test-99 deployments]# kubectl taint node test-99 gpu-server:NoExecute-
node/test-99 untainted
5、创建容忍度
通过tolerations来配置容忍度,tolerations的每一项包括key、operator、value、effect,其中key对应污点的key,value对应污点的value,effect对应污点的effect(污点效果),而operator包括Equal和Exists。其中Equal表示相等,也就是key、operator和effect等各项配置完全相等,Exists表示存在,比如只配置key,那么表示只存在key对应的污点即可。
tolerations:
- key: "gpu-server"
operator: "Equal"
value: "1"
effect: "NoExecute"
一个配置了容忍度的Deployment定义
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
tolerations:
- key: "gpu-server"
operator: "Equal"
value: "1"
effect: "NoExecute"
(1)完全匹配
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
(2)匹配Key和effect
tolerations:
- key: "key"
operator: "Exists"
effect: "NoSchedule"
(3)匹配Key
tolerations:
- key: "key"
operator: "Exists"
(4)匹配所有污点
tolerations:
- perator: "Exists"
(5)删除/修改容忍度
通过修改Pod配置,然后执行kubectl apply -f覆盖配置。
(6)配置容忍时间
tolerations:
- key: "key"
operator: "Exists"
effect: "NoExecute"
tolerationSeconds: 60
通过tolerationSeconds来配置容忍时间,也就是Pod在被驱逐前可以停留的时间,单位为秒。
三、kubernetes系统添加的污点
kubernetes 的节点控制器在碰到某些特定的条件时,将自动为节点添加污点,包括如下:
- node.kubernetes.io/not-ready: 节点未就绪。对应着 NodeCondition Ready 为 False 的情况
- node.kubernetes.io/unreachable: 节点不可触达。对应着 NodeCondition Ready 为 Unknown 的情况
- 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:如果 kubelet 是由 “外部” 云服务商启动的,该污点用来标识某个节点当前为不可用的状态。在“云控制器”(cloud-controller-manager)初始化这个节点以后,kubelet将此污点移除。