背景
在日常使用k8s集群中,有时候需要某些节点只运行某些pod,既不希望有其他的pod调度过来,也不希望这些pod调度到别的其他节点上。比如说,有NodeA,只希望运行一个PodA,不想要PodB也调度到NodeA上,并且,不希望PodA会调度到NodeB上
针对上面的问题,其实我们可以使用标签+污点的方式去实现,而当使用多组标签+污点时,也就把节点资源划分一个个池了
接下来,我们看看标签和污点如何使用
1. 标签label
node资源的metadata.labels
属性,给节点加上标签,比如test=test
,pod通过nodeAffinity
或nodeSelector
配置test: test
,则pod会调度到含有该标签的节点上
用kubectl label
命令时,label的格式为key=value
1.1 示例
- 先给主机打上label
root@10 ~]# kubectl get no
NAME STATUS ROLES AGE VERSION
10.10.101.170-master Ready master 7d21h v1.17.2
10.10.101.171-slave Ready <none> 7d21h v1.17.2
10.10.101.172-slave Ready <none> 7d21h v1.17.2
10.10.101.173-slave Ready <none> 7d20h v1.17.2
10.10.101.174-build Ready <none> 7d20h v1.17.2
10.10.101.176-share Ready <none> 7d20h v1.17.2
10.10.103.108-share Ready <none> 6d23h v1.17.2
[root@10 ~]# kubectl get no -l test=test
No resources found in default namespace.
// 删除该label的命令是kubectl label no 10.10.101.176-share test-
[root@10 ~]# kubectl label no 10.10.101.176-share test=test
node/10.10.101.176-share labeled
[root@10 ~]# kubectl get no -l test=test
NAME STATUS ROLES AGE VERSION
10.10.101.176-share Ready <none> 7d20h v1.17.2
- 部署一个pod不指定和
nodeAffinity
和nodeSelector
预期:随机调度到一个节点上
// 未指定label的yaml文件
apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: default
labels:
app: test-pod
spec:
containers:
- name: test-container
image: busybox
command: ['sh', '-c', 'echo Hello Harmonycloud! && sleep 3600']
[root@10 ~]# kubectl create -f busybox.yaml
pod/test-pod created
[root@10 ~]# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-pod 1/1 Running 0 38s 10.168.216.168 10.10.103.108-share <none> <none>
多删除创建几次,可以发现test-pod
会调度到不同的节点
- 部署一个pod指定
nodeAffinity
或nodeSelector
预期:只调度到10.10.101.176-share
节点上
// 通过nodeSelector指定label的yaml文件如下
apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: default
labels:
app: test-pod
spec:
containers:
- name: test-container
image: busybox
command: ['sh', '-c', 'echo Hello Harmonycloud! && sleep 3600']
nodeSelector:
test: test
// 按照上面的yaml添加nodeSelector
[root@10 ~]# kubectl edit po test-pod
pod "test-pod" edited
[root@10 ~]# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-pod 1/1 Running 0 52s 10.168.216.170 10.10.101.176-share <none> <none>
无论test-pod
删除再创建多少次,都会调度到10.10.101.176-share
节点上
2. 污点taint
node资源的spec.taints
属性,给节点加上污点,比如说node-role.kubernetes.io/slave=:NoSchedule
,则只有配置了容忍该污点(tolerations
)的pod
才能调度到该节点上
污点的格式分为三段,key=value:effect
,其中 effect 有三个策略:
- NoSchedule:表示 pod 不会被调度到标记为 taints 的节点
- PreferNoSchedule:NoSchedule 的软策略版本,表示尽量不调度到污点节点上去
- NoExecute:该选项意味着一旦 Taint 生效,如该节点内正在运行的 pod 没有对应 tolerations 设置,会直接被逐出
示例
- 给
10.10.101.176-share
加上污点node-role.kubernetes.io/slave=:NoSchedule
[root@10 ~]# kubectl describe no 10.10.101.176-share | grep -E '(Roles|Taints)'
Roles: <none>
Taints: <none>
[root@10 ~]# kubectl taint node 10.10.101.176-share node-role.kubernetes.io/slave=:NoSchedule
node/10.10.101.176-share tainted
[root@10 ~]# kubectl describe no 10.10.101.176-share | grep -E '(Roles|Taints)'
Roles: <none>
Taints: node-role.kubernetes.io/slave:NoSchedule
- 部署
pod-test
,通过label指定调度到10.10.101.176-share
节点
由于是NoSchedule
策略,之前已在该节点上的podpod-test
不会被驱逐,所以我们先把pod删了再创建
预期:pod-test
处于Pending状态
// 先删除原本的pod再创建
[root@10 ~]# kubectl delete po test-pod
pod "test-pod" deleted
[root@10 ~]# kubectl create -f busybox.yaml
pod/test-pod created
[root@10 ~]# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-pod 0/1 Pending 0 14s <none> <none> <none> <none>
// 查看Pending原因
[root@10 ~]# kubectl describe po test-pod
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 49s (x2 over 49s) default-scheduler 0/7 nodes are available: 1 node(s) had taints that the pod didn't tolerate, 6 node(s) didn't match node selector.
- 给
test-pod
加上tolerations
apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: default
labels:
app: test-pod
spec:
containers:
- name: test-container
image: busybox
command: ['sh', '-c', 'echo Hello Harmonycloud! && sleep 3600']
nodeSelector:
test: test
tolerations:
- key: "node-role.kubernetes.io/slave"
operator: "Exists"
value: ""
effect: "NoSchedule"
// 按照上面的yaml去添加tolerations
[root@10 ~]# kubectl edit po test-pod
pod "test-pod" edited
[root@10 ~]# kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-pod 1/1 Running 0 16s 10.168.216.171 10.10.101.176-share <none> <none>
可以看到,test-pod
调度到10.10.101.176-share
节点上了
节点资源池划分
节点资源池,是对k8s集群的所有节点进行逻辑层面的划分,每个池里的pod,应该要做到无论重启多少次,只会在该池的节点上,如何对pod调度进行控制,通过上面的示例,我们知道了:
- 使用标签,可以使pod调度到预期的节点上
- 使用污点,可以避免未容忍该污点的pod调度到节点上
如果只使用标签,固然我们可以把自己想要的pod调度到预期节点上,但是其他的pod也有可能调度到上面,因此只靠标签还不够,我们需要把其他的pod都驱逐,避免资源被占用。
反过来,如果只使用污点,的确能够避免其他的pod调度到预期节点上,但是我们自己的pod也可能调度到其他无污点的节点上,并不能保证只调度到我们的预期的节点上
至此,使用 标签 + 污点 ,我们的节点资源池划分也就可以实现了!
网友评论