默认情况下,Pod的调度完全由Master节点的Scheduler组件经过一系列的算法计算得出的,这个过程是不能人工干预的。但是实际情况中业务逻辑是非常复杂,可能需要自己控制Pod到达某个节点,k8s也提供了一些更加细粒度的调度策略设置。如NodeSelector,NodeAffinity,PodAffinity,污点和容忍等。
本文主要介绍定向调度 NodeSelector ,其它调度方式后续文章更新。
定向调度可以将Pod调度到指定的Node上,这个过程是强制的,如果调度的目标节点不存在,那么Pod会运行失败,并不会调度到其它节点。
定向调度有两种方式
查看当前集群的所有节点。
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready control-plane,master 49d v1.23.9
node01 Ready 49d v1.23.9
node02 Ready 49d v1.23.9
编写 nginx-nodename.yaml 内容如下,通过nodeName调度到node01节点。
apiVersion: v1
kind: Pod
metadata:
name: nginx-nodename
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeName: node01
启动Pod,查看Pod详情注意观察NODE信息。
# 启动
# kubectl create -f nginx-nodename.yaml
pod/nginx-nodename created
# 查看Pod详情 已经运行成功并且调度到了node01
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-nodename 1/1 Running 0 11s 10.244.1.69 node01
上面流程是node节点存在,pod被成功调度。
前面提到,这个调度是强制性的,如果没有该node节点是否运行不成功,下面来验证下,修改上面yaml,将 nodeName: node01修改为 nodeName: node03。
apiVersion: v1
kind: Pod
metadata:
name: nginx-nodename
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeName: node03
启动Pod,观察详情
# kubectl apply -f nginx-nodename.yaml
pod/nginx-nodename apply
# 查看pod看到Node虽然在node03但是并没有运行成功
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-nodename 0/1 Pending 0 14s node03
# 等待一会,因为没有节点的原因,该pod会自动删除
# kubectl get pod -o wide
No resources found in default namespace.
在Pod创建之前,会通过 MatchNodeSelector 调度策略进行节点标签匹配,如果找到对应节点含有此标签,则调度到该节点,如果找到多个挑选一个即可,如果没有找到则Pod运行失败(前面提到了该机制是强制性的)
通过kubectl label命令给node01打上北京机房的标签,给node02打上上海机房的标签。
kubectl label nodes node01 area=bj
kubectl label nodes node02 area=shanghai
# 查看标签是否设置成功
kubectl get nodes --show-labels
编写 nginx-nodeselector.yaml 内容如下 通过 nodeSelector指定调度到bj机房
apiVersion: v1
kind: Pod
metadata:
name: nginx-nodeselector
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
area: bj #指定调度到北京机房
北京机房测试
启动Pod,查看Pod详情注意观察NODE信息
# 启动Pod
# kubectl create -f nginx-nodeselector.yaml
pod/nginx-nodeselector created
# 查看详情,调度到了node01
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-nodeselector 1/1 Running 0 41s 10.244.1.70 node01
上海机房测试
修改area为shanghai 再次启动Pod,查看Pod详情注意观察NODE信息
# 删除之前的pod
# kubectl delete -f nginx-nodeselector.yaml
pod "nginx-nodeselector" deleted
# 启动修改后的Pod
# kubectl create -f nginx-nodeselector.yaml
pod/nginx-nodeselector created
# 查看详情,调度到了node02
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-nodeselector 1/1 Running 0 5s 10.244.2.23 node02
无匹配机房测试
修改area为changsha 再次启动Pod,查看Pod详情
# 删除之前的pod
# kubectl delete -f nginx-nodeselector.yaml
pod "nginx-nodeselector" deleted
# 启动修改后的Pod
# kubectl create -f nginx-nodeselector.yaml
pod/nginx-nodeselector created
# 查看详情,并没有启动成功
# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-nodeselector 0/1 Pending 0 12s
# 查看启动过程,报错了
# kubectl describe pod nginx-nodeselector|grep -A 100 Event
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 64s default-scheduler 0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector.
由于找不到匹配的node节点,前面提到了该机制是强制性的,所以pod是运行不起来的,这种方式调度失败了是不会删除pod,需要手动删除下。
如果需要删除节点标签,执行如下命令
kubectl label node node01 area-
kubectl label node node02 area-
Pod的定向调度只是一个简单的限制了Pod所在节点的方法,相比于亲和性调度,它极大的扩展了Pod的调度能力。