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など付与したラベルってどういう利用方法があるのって思っていましたが、なかなか便利ですね!
特に規模の大きな商用環境などになると、ラベルの管理が重要になってくるので追加検証の部分が役に立ちそうです。