上一篇,我們學習了各種工作負載的使用,工作負載它會自動幫我們完成Pod的排程和部署,但有時我們需要自己定義Pod的排程策略,這個時候該怎麼辦呢?今天我們就來看一下如何定義Pod排程策略。
一、NodeSelector:節點定向排程
Kubernetes的Scheduler服務在排程Pod的時候會通過一系列複雜的演演算法自動計算出每一個Pod的最佳目標節點,但有的時候,我們需要將Pod指定的到一些Node上,比如我們有的Node安裝了SSD,磁碟讀寫高,可以部署一些IO密集型應用,這個時候,我們就需要給這些Node打標籤,然後在Pod中定義NodeSelector就可以實現。接下來我們來看一些如何實現:
1、我們通過kubectl label命令給叢集中kubevm2打標籤:disk=ssd,標示我們kubevm2的磁碟使用SSD。
[root@kubevm1 ~]# kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME kubevm1 Ready master 33d v1.19.16 192.168.56.120 <none> CentOS Linux 7 (Core) 3.10.0-1160.el7.x86_64 docker://1.13.1 kubevm2 Ready <none> 33d v1.19.16 192.168.56.121 <none> CentOS Linux 7 (Core) 3.10.0-1160.el7.x86_64 docker://1.13.1 kubevm3 Ready <none> 33d v1.19.16 192.168.56.122 <none> CentOS Linux 7 (Core) 3.10.0-1160.el7.x86_64 docker://1.13.1 [root@kubevm1 ~]# kubectl label nodes kubevm2 disk=ssd
2、我們在之前deployment的例子中的Pod定義中增加nodeSelector設定:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 nodeSelector: disk: ssd
3、建立此Deployment,檢視pod部署位置:我們發現三個副本都部署在kubevm2上。
[root@kubevm1 workspace]# kubectl create -f demo_deployment.yml deployment.apps/nginx-deployment created [root@kubevm1 workspace]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-deployment-758754644-d2qg5 1/1 Running 0 101s 10.244.1.26 kubevm2 <none> <none> nginx-deployment-758754644-tsf9f 1/1 Running 0 101s 10.244.1.27 kubevm2 <none> <none> nginx-deployment-758754644-vxdkm 1/1 Running 0 101s 10.244.1.25 kubevm2 <none> <none>
如果我們給多個Node都定義了相同的標籤,則Scheduler會從這組Node中挑選一個可用的Node。我們可以看到通過給Node打標籤的方式,我們可以描述叢集中具有不同特點的Node,在部署應用時通過結合應用的需求設定NodeSelector進行指定Node範圍的排程。這裡要注意,如果我們指定了NodeSelector條件,但叢集中不存在包含相應標籤的Node,即使叢集中還有其他可供使用的node,這個Pod也無法被成功排程,就那上面的例子來說,我們希望應用部署在SSD節點上,但如果叢集中沒有SSD的節點了,使用機械硬碟的節點也能部署,這樣的話,使用NodeSelector就無法滿足這一需求了。這個時候我們就需要使用節點親和性排程了。
二、NodeAffinity:節點親和性排程
NodeAffinity是用於替換NodeSelector的全新排程策略,目前該策略有兩種表達方式:
RequiredDuringSchedulingIgnoredDuringExecution:排程器只有在規則被滿足的時候才能執行排程。此功能類似於 nodeSelector,但其語法表達能力更強
PreferredDuringSchedulingIgnoredDuringExecution:排程器會嘗試尋找滿足對應規則的節點。如果找不到匹配的節點,排程器仍然會排程該 Pod。
我們可以看到RequiredDuringSchedulingIgnoredDuringExecution 的特性跟NodeSelector很像,而PreferredDuringSchedulingIgnoredDuringExecution更加靈活一些,我們接下來看一下二者的用法:
1、RequiredDuringSchedulingIgnoredDuringExecution使用
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: disk operator: In values: - ssd
我們建立此Deployment,可以看到Pod豆部署在kubevm2上:
[root@kubevm1 workspace]# kubectl create -f demo_deployment.yml deployment.apps/nginx-deployment created [root@kubevm1 workspace]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-deployment-6ff7bf994d-9dhl2 1/1 Running 0 63s 10.244.1.28 kubevm2 <none> <none> nginx-deployment-6ff7bf994d-c8xzh 1/1 Running 0 63s 10.244.1.29 kubevm2 <none> <none> nginx-deployment-6ff7bf994d-xlpg8 1/1 Running 0 63s 10.244.1.30 kubevm2 <none> <none>
2、PreferredDuringSchedulingIgnoredDuringExecution的使用
我們將kubevm2、kubevm3打標籤:disk=sata:
[root@kubevm1 workspace] kubectl label nodes kubevm2 disk=sata node/kubevm2 labeled [root@kubevm1 workspace] kubectl label nodes kubevm3 disk=sata node/kubevm3 labeled
修改deployment設定:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 3 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: disk operator: In values: - ssd - key: disk operator: In values: - ssd
我們建立此Deployment可以看到,即使當前叢集中沒有ssd的node,Pod仍然可以部署:
[root@kubevm1 workspace]# kubectl create -f demo_deployment.yml deployment.apps/nginx-deployment created [root@kubevm1 workspace]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-deployment-cff9b7cf7-26hww 1/1 Running 0 81s 10.244.2.15 kubevm3 <none> <none> nginx-deployment-cff9b7cf7-k9x47 1/1 Running 0 81s 10.244.1.31 kubevm2 <none> <none> nginx-deployment-cff9b7cf7-xtrq4 1/1 Running 0 81s 10.244.1.32 kubevm2 <none> <none>
在上面的例子中,我們使用到了In操作符,NodeAffinity支援的操作符包括In、NotIn、Exists、DoesNotExist、Gt、Lt等。
OK,以上就是今天的內容了,後面我們繼續學習Pod的其他排程策略。