Docker 與 K8S學習筆記(二十五)—— Pod的各種排程策略(上)

2022-06-28 21:00:26

上一篇,我們學習了各種工作負載的使用,工作負載它會自動幫我們完成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的其他排程策略。