調度之nodeSelector


1.簡介:

一般情況下我們部署的 Pod 是通過集群的自動調度策略來選擇節點的,默認情況下調度器考慮的是資源足夠,並且負載盡量平均,但是有的時候我們需要能夠更加細粒度的去控制 Pod 的調度,比如我們希望一些機器學習的應用只跑在有 GPU 的節點上;但是有的時候我們的服務之間交流比較頻繁,又希望能夠將這服務的 Pod 都調度到同一個的節點上。這就需要使用一些調度方式來控制 Pod 的調度了,主要有兩個概念:親和性和反親和性,親和性又分成節點親和性(nodeAffinity)和 Pod 親和性(podAffinity)。

2.nodeSelector:

在了解親和性之前,我們先來了解一個非常常用的調度方式:nodeSelector。我們知道 label 標簽是 kubernetes 中一個非常重要的概念,用戶可以非常靈活的利用 label 來管理集群中的資源,比如最常見的 Service 對象通過 label 去匹配 Pod 資源,而 Pod 的調度也可以根據節點的 label 來進行調度。

我們可以通過下面的命令查看我們的 node 的 label:

[root@k8s-master01 ~]# kubectl get nodes --show-labels
NAME           STATUS   ROLES    AGE   VERSION   LABELS
k8s-master01   Ready    <none>   11d   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master01,kubernetes.io/os=linux,node.kubernetes.io/node=
k8s-master02   Ready    <none>   11d   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master02,kubernetes.io/os=linux,node.kubernetes.io/node=
k8s-master03   Ready    <none>   11d   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master03,kubernetes.io/os=linux,node.kubernetes.io/node=
k8s-node01     Ready    <none>   11d   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node01,kubernetes.io/os=linux,node.kubernetes.io/node=
k8s-node02     Ready    <none>   11d   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node02,kubernetes.io/os=linux,node.kubernetes.io/node=

現在我們先給節點k8s-node01增加一個cm=test的標簽,命令如下:

[root@k8s-master01 ~]# kubectl label nodes k8s-node01 cm=test # 創建標簽
node/k8s-node01 labeled
[root@k8s-master01 ~]# kubectl label nodes k8s-node01 cm- # 刪除標簽
node/k8s-node01 labeled

[root@k8s-master01 ~]# kubectl get nodes --show-labels
NAME           STATUS   ROLES    AGE   VERSION   LABELS
k8s-master01   Ready    <none>   11d   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master01,kubernetes.io/os=linux,node.kubernetes.io/node=
k8s-master02   Ready    <none>   11d   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master02,kubernetes.io/os=linux,node.kubernetes.io/node=
k8s-master03   Ready    <none>   11d   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master03,kubernetes.io/os=linux,node.kubernetes.io/node=
k8s-node01     Ready    <none>   11d   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,cm=test,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node01,kubernetes.io/os=linux,node.kubernetes.io/node=
k8s-node02     Ready    <none>   11d   v1.20.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node02,kubernetes.io/os=linux,node.kubernetes.io/node=

我們可以通過上面的 --show-labels 參數可以查看上述標簽是否生效。當節點被打上了相關標簽后,在調度的時候就可以使用這些標簽了,只需要在 Pod 的 spec 字段中添加 nodeSelector 字段,里面是我們需要被調度的節點的 label 標簽,比如,下面的 Pod 我們要強制調度到 node2 這個節點上去,我們就可以使用 nodeSelector 來表示了:(node-selector-demo.yaml)

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: busybox-pod
  name: test-busybox
spec:
  containers:
  - command:
    - sleep
    - "3600"
    image: busybox
    imagePullPolicy: Always
    name: test-busybox
  nodeSelector:
    com: test # 這里可以寫我們定義的標簽,或者hostname

我們可以通過命令查看調度結果

[root@k8s-master01 ~]# kubectl apply  -f node-selector-demo.yaml 
pod/test-busybox created
[root@k8s-master01 ~]# kubectl get  pods -owide
NAME                     READY   STATUS    RESTARTS   AGE     IP               NODE           NOMINATED NODE   READINESS GATES
busybox                  1/1     Running   261        11d     172.17.125.9     k8s-node01     <none>           <none>
nginx-68db656dd8-qjhs9   1/1     Running   1          10d     172.25.244.200   k8s-master01   <none>           <none>
nginx-68db656dd8-znwgp   1/1     Running   1          10d     172.18.195.11    k8s-master03   <none>           <none>
test-busybox             1/1     Running   0          19s     172.27.14.215    k8s-node02     <none>           <none>
web                      2/2     Running   0          3d17h   172.18.195.14    k8s-master03   <none>           <none>

[root@k8s-master01 ~]# kubectl describe pod test-busybox 
Name:         test-busybox
Namespace:    default
Priority:     0
Node:         k8s-node02/192.168.0.111
Start Time:   Tue, 30 Mar 2021 18:37:27 +0800
Labels:       app=busybox-pod
Annotations:  <none>
Status:       Running
IP:           172.27.14.215
IPs:
  IP:  172.27.14.215
Containers:
  test-busybox:
    Container ID:  docker://f85fa6688eb7b014b5c710354243528c6c0df555b3300f168773bc0f461581d1
    Image:         busybox
    Image ID:      docker-pullable://busybox@sha256:ce2360d5189a033012fbad1635e037be86f23b65cfd676b436d0931af390a2ac
    Port:          <none>
    Host Port:     <none>
    Command:
      sleep
      3600
    State:          Running
      Started:      Tue, 30 Mar 2021 18:37:44 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-pn9sp (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-pn9sp:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-pn9sp
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  cm=test # 
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  55s   default-scheduler  Successfully assigned default/test-busybox to k8s-node02
  Normal  Pulling    54s   kubelet            Pulling image "busybox"

我們可以看到 Events 下面的信息,我們的 Pod 通過默認的 default-scheduler 調度器被綁定到了 node2 節點。不過需要注意的是nodeSelector 屬於強制性的,如果我們的目標節點沒有可用的資源,我們的 Pod 就會一直處於 Pending 狀態。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM