Opensourcetechブログ

OpensourcetechによるNGINX/Kubernetes/Zabbix/Neo4j/Linuxなどオープンソース技術に関するブログです。

nodeSelectorによるPod起動ノードの制御(kubernetes)


LinuCエヴァンジェリスト・Open Source Summit Japan 2022ボランティアリーダー鯨井貴博@opensourcetechです。


はじめに
今回は、kubernetesにおけるnodeSelectorを使ったPod起動ノートの制御をしてみます。


nodeSelectorとは
仕組みとしてはシンプルで、
ノードに付与されたラベルを指定して、そのノード上にPodを起動するというものです。
https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/


nodeSelectorを使ってみる
では、実際にやってみましょう!
まず、ラベルを付与する前のノードの状態を確認。

kubeuser@master01:~/nodeSelector$ kubectl get node --show-labels
NAME       STATUS   ROLES           AGE    VERSION   LABELS
master01   Ready    control-plane   153d   v1.27.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master01,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
worker01   Ready    <none>          153d   v1.27.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker01,kubernetes.io/os=linux
worker02   Ready    <none>          153d   v1.27.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker02,kubernetes.io/os=linux


続いて、worker01にdisktype=ssd・cpu=high、worker02にdisktype=hdd・cpu=lowというラベルを付与します。
※worker01はハイスペック、worker02はロースペックと仮定したもの。

kubeuser@master01:~/nodeSelector$ kubectl label node worker01 disktype=ssd
node/worker01 labeled

kubeuser@master01:~/nodeSelector$ kubectl label node worker02 disktype=hdd
node/worker02 labeled

kubeuser@master01:~/nodeSelector$ kubectl label node worker01 cpu=high
node/worker01 labeled

kubeuser@master01:~/nodeSelector$ kubectl label node worker02 cpu=low
node/worker02 labeled

kubeuser@master01:~/nodeSelector$ kubectl get node --show-labels
NAME       STATUS   ROLES           AGE    VERSION   LABELS
master01   Ready    control-plane   153d   v1.27.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master01,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
worker01   Ready    <none>          153d   v1.27.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,cpu=high,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker01,kubernetes.io/os=linux
worker02   Ready    <none>          153d   v1.27.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,cpu=low,disktype=hdd,kubernetes.io/arch=amd64,kubernetes.io/hostname=worker02,kubernetes.io/os=linux


続いて、Podを起動するためのyaml作成。
※disktype: ssdを指定したので、worker01上で起動する想定。

kubeuser@master01:~/nodeSelector$ vi testpod.yaml 

kubeuser@master01:~/nodeSelector$ cat testpod.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: nginx
    name: testpod
  nodeSelector:
    disktype: ssd
  dnsPolicy: ClusterFirst
  restartPolicy: Always


そしてPodのデプロイ(起動)。
想定通り、worker01上で起動しました。

kubeuser@master01:~/nodeSelector$ kubectl apply -f testpod.yaml 
pod/testpod created

kubeuser@master01:~/nodeSelector$ kubectl get pods testpod -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP          NODE       NOMINATED NODE   READINESS GATES
testpod   1/1     Running   0          14s   10.0.5.60   worker01   <none>           <none>



nodeSelectorの追加検証
せっかくなので、以下の2パターンについても検証しておきます。
①ちぐはぐ(どのノードか特定出来ない)なラベル指定だとどうなる?
②複数のラベル指定は可能?

まずは①から。

kubeuser@master01:~/nodeSelector$ vi testpod.yaml 

kubeuser@master01:~/nodeSelector$ cat testpod.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: nginx
    name: testpod
  nodeSelector:
    disktype: ssd
    cpu: low
  dnsPolicy: ClusterFirst
  restartPolicy: Always

kubeuser@master01:~/nodeSelector$ kubectl apply -f testpod.yaml 
pod/testpod created

kubeuser@master01:~/nodeSelector$ kubectl get pods testpod -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
testpod   0/1     Pending   0          16s   <none>   <none>   <none>           <none>

kubeuser@master01:~/nodeSelector$ kubectl describe pod testpod
Name:             testpod
Namespace:        default
Priority:         0
Service Account:  default
Node:             <none>
Labels:           run=testpod
Annotations:      <none>
Status:           Pending
IP:               
IPs:              <none>
Containers:
  testpod:
    Image:        nginx
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-pvjr9 (ro)
Conditions:
  Type           Status
  PodScheduled   False 
Volumes:
  kube-api-access-pvjr9:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              cpu=low
                             disktype=ssd
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
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  23s   default-scheduler  0/3 nodes are available: 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: }, 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/3 nodes are available: 3 Preemption is not helpful for scheduling..

kubeuser@master01:~/nodeSelector$ kubectl get pods testpod -o wide
NAME      READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
testpod   0/1     Pending   0          34s   <none>   <none>   <none>           <none>


0/3 nodes are available: 1 node(s) had untolerated taint {node-role.kubernetes.io/control-plane: }, 2 node(s) didn't match Pod's node affinity/selector. preemption: 0/3 nodes are available: 3 Preemption is not helpful for scheduling..(Podを起動出来るノードがないぞ!)って怒られましたw
Podはステータス"Pending"のままです。

続いて②。

kubeuser@master01:~/nodeSelector$ vi testpod.yaml 

kubeuser@master01:~/nodeSelector$ cat testpod.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  containers:
  - image: nginx
    name: testpod
  nodeSelector:
    disktype: hdd
    cpu: low
  dnsPolicy: ClusterFirst
  restartPolicy: Always

kubeuser@master01:~/nodeSelector$ kubectl apply -f testpod.yaml 
pod/testpod created

kubeuser@master01:~/nodeSelector$ kubectl get pods testpod -o wide
NAME      READY   STATUS    RESTARTS   AGE    IP           NODE       NOMINATED NODE   READINESS GATES
testpod   1/1     Running   0          102s   10.0.30.79   worker02   <none>           <none>


こちらは複数ラベルが一致するノード(worker02)で起動されました。


おわりに
kubernetesのノードやPodなど付与したラベルってどういう利用方法があるのって思っていましたが、なかなか便利ですね!
特に規模の大きな商用環境などになると、ラベルの管理が重要になってくるので追加検証の部分が役に立ちそうです。

Opensourcetech by Takahiro Kujirai