K8S中的调度策略---节点选择器
正常情况下,Pod被调度到哪一个节点是通过scheduler完成,但在一些场景中,时常需要将一些pod指定在某一个node上运行。那此时就可以通过nodeName和nodeSelector完成
nodeName
nodeName <string>
NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.
[root@master-worker-node-1 pod]# cat test-node-name.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-node-name
labels:
function: test-node-name
spec:
nodeName: only-worker-node-3
containers:
- name: test-ndoe-name-container
image: busybxox:latest
imagePullPolicy: IfNotPresent
command: ['/bin/sh','-c','sleep 1234']
创建pod
[root@master-worker-node-1 pod]# kubectl apply -f test-node-name.yaml
pod/test-node-name created
pod被调度到了only-worker-node-3
[root@master-worker-node-1 pod]# kubectl get pods --show-labels -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
test-node-name 1/1 Running 0 62s 10.244.31.7 only-worker-node-3 <none> <none> function=test-node-name
nodeSelector
nodeSelector和后面要学习的亲和性都是根据node的label进行选择。
因为nodeSelector是和标签有关,先给其中一个worker node打上一个标签
[root@master-worker-node-1 pod]# kubectl label nodes only-worker-node-3 test-nodeselector=target-node
node/only-worker-node-3 labeled
[root@master-worker-node-1 pod]# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
master-worker-node-1 Ready control-plane 3d22h v1.25.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master-worker-node-1,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
master-worker-node-2 Ready control-plane 3d21h v1.25.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master-worker-node-2,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
only-worker-node-3 Ready worker 3d21h v1.25.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=only-worker-node-3,kubernetes.io/os=linux,node-role.kubernetes.io/worker=,test-nodeselector=target-node
only-worker-node-4 Ready worker 3d21h v1.25.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=only-worker-node-4,kubernetes.io/os=linux,node-role.kubernetes.io/worker=
[root@master-worker-node-1 pod]# cat test-node-selector.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-node-selector
labels:
function: test-node-selector
spec:
nodeSelector:
test-nodeselector: target-node
containers:
- name: test-node-selector
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ['/bin/sh','-c','sleep 1234']
创建pod
[root@master-worker-node-1 pod]# kubectl apply -f test-node-selector.yaml
pod/test-node-selector created
pod被调度到含有nodeslector中关联的label的node上。
[root@master-worker-node-1 pod]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-node-name 1/1 Running 0 18m 10.244.31.7 only-worker-node-3 <none> <none>
test-node-selector 1/1 Running 0 11s 10.244.31.8 only-worker-node-3 <none> <none>
将only-worker-node-4也打上对应的标签test-nodeselector=target-node
[root@master-worker-node-1 pod]# kubectl label nodes only-worker-node-4 test-nodeselector=target-node
node/only-worker-node-4 labeled
重新新增一个pod,该pod具有相同的nodeSelector
[root@master-worker-node-1 pod]# kubectl apply -f test-node-selector-2.yaml
pod/test-node-selector-2 created
此时pod被scheduler在具有test-nodeselector这个label的node之间进行调度。结果显示被调度到only-worker-node-4
[root@master-worker-node-1 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-node-name 1/1 Running 1 (12m ago) 33m 10.244.31.7 only-worker-node-3 <none> <none>
test-node-selector 1/1 Running 0 14m 10.244.31.8 only-worker-node-3 <none> <none>
test-node-selector-2 1/1 Running 0 10m 10.244.54.7 only-worker-node-4 <none> <none>
nodeName和nodeSelector优先级对比
测试前,现将only-worker-node-4的label去除
[root@master-worker-node-1 pod]# kubectl label nodes only-worker-node-4 test-nodeselector-
node/only-worker-node-4 unlabeled
[root@master-worker-node-1 pod]# cat compare-nodename-with-node-selector.yaml
apiVersion: v1
kind: Pod
metadata:
name: compare
labels:
function: compare-nodeName-with-nodeSelector
spec:
nodeName: only-worker-node-4 # nodeName选择only-worker-node-4
nodeSelector:
test-nodeselector: target-node # nodeSelector选择only-worker-node-3
containers:
- name: compare
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ['/bin/sh','-c','sleep 1234']
[root@master-worker-node-1 pod]# kubectl apply -f compare-nodename-with-node-selector.yaml
pod/compare created
发现pod不能正常运行
[root@master-worker-node-1 pod]# kubectl get pods -o wide | grep compare
compare 0/1 NodeAffinity 0 105s <none> only-worker-node-4 <none> <none>
查看pod详情发现nodeAffnity调度失败
[root@master-worker-node-1 pod]# kubectl describe pods compare | tail -4
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning NodeAffinity 2m23s kubelet Predicate NodeAffinity failed
[root@master-worker-node-1 pod]# cat compare-nodename-with-node-selector-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: compare-2
labels:
function: compare-nodeName-with-nodeSelector
spec:
nodeName: only-worker-node-3 # nodeName选择only-worker-node-3
nodeSelector:
test-nodeselector: target-node # nodeSelector也选择only-worker-node-3
containers:
- name: compare-2
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ['/bin/sh','-c','sleep 1234']
[root@master-worker-node-1 pod]# kubectl apply -f compare-nodename-with-node-selector-2.yaml
pod/compare-2 created
pod可以运行
[root@master-worker-node-1 pod]# kubectl get pods -o wide | grep compare
compare 0/1 NodeAffinity 0 8m56s <none> only-worker-node-4 <none> <none>
compare-2 1/1 Running 0 17s 10.244.31.9 only-worker-node-3 <none> <none>
小结
nodeName是通过node的名称进行调度,nodeSelector是通过node的标签进行调度。
当nodeName和nodeSelector的标签同时存在,且选择不同的node时,pod将因为nodeAffinity创建失败
当nodeName和nodeSelector的标签同时存在,但可以选出相同的node时,pod可以正常运行