今回は「Podを配置するNodeの選択/制限方法」のうち「NodeSelector」「Node Affinity」「Pod Affinity / Anti-Affinity」についてまとめます。 「Taints & Tolerations」は次回まとめます。
Selector または Affinity 、 Taints & Tolerations など似たようなものがいくつかあり、分かりづらいのでまとめてみました。
関連記事
- Podを指定したNodeに配置する方法(この記事)
- Nodeに決められたPod以外配置させない方法
概要
NodeにはあらかじめLabelが指定されています。 Podに対して「NodeのどのLabelと一致させるか」を指定し、Labelが一致するNodeに対してPodを配置していくものです。
Podを意図したNodeに配置したい場合、以下のような定義を利用して指定します。
nodeSelector
nodeAffinity
podAffinity
またはpodAntiAffinity
上記の定義はいずれも Node Label との一致状況を確認するので、まずは Node Label から確認していきましょう。
Node Label
Podの配置にはNodeのラベルが使われます。 なので、何はともあれNodeのラベルとしてどんなものが定義されているのか、どう定義するのかなどを確認しておきます。
Labelの確認
現在 Node に付与されている ラベル を確認するには kubectl describe node NAME
で確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | [root@k8s-master ~]# kubectl describe node k8s-node01 Name: k8s-node01 Roles: worker Labels: beta.kubernetes.io/arch=amd64 beta.kubernetes.io/os=linux kubernetes.io/arch=amd64 kubernetes.io/hostname=k8s-node01 kubernetes.io/os=linux node-role.kubernetes.io/worker= Annotations: flannel.alpha.coreos.com/backend-data: { "VtepMAC" : "9e:14:d6:92:02:02" } flannel.alpha.coreos.com/backend- type : vxlan flannel.alpha.coreos.com/kube-subnet-manager: true flannel.alpha.coreos.com/public-ip: 10.51.1.101 kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock node.alpha.kubernetes.io/ttl: 0 volumes.kubernetes.io/controller-managed-attach-detach: true CreationTimestamp: Sun, 02 Jun 2019 17:49:09 +0900 Taints: <none> Unschedulable: false Conditions: Type Status LastHeartbeatTime LastTransitionTime Reason Message ---- ------ ----------------- ------------------ ------ ------- MemoryPressure False Mon, 10 Jun 2019 23:39:18 +0900 Sun, 02 Jun 2019 17:49:09 +0900 KubeletHasSufficientMemory kubelet has sufficient memory available DiskPressure False Mon, 10 Jun 2019 23:39:18 +0900 Sun, 02 Jun 2019 17:49:09 +0900 KubeletHasNoDiskPressure kubelet has no disk pressure PIDPressure False Mon, 10 Jun 2019 23:39:18 +0900 Sun, 02 Jun 2019 17:49:09 +0900 KubeletHasSufficientPID kubelet has sufficient PID available Ready True Mon, 10 Jun 2019 23:39:18 +0900 Sun, 02 Jun 2019 17:49:19 +0900 KubeletReady kubelet is posting ready status … (以下省略) … </none> |
Labelの付与/削除
新たなラベルを Node に付与したい場合は kubectl label nodes NAME KEY=VALUE
で付与します。
以下のコマンドでは「k8s-node01
」に対して「disktype = ssd
」を指定しています。
1 2 | [root@k8s-master ~]# kubectl label nodes k8s-node01 disktype=ssd node/k8s-node01 labeled |
付与したラベルを削除したい場合は kubectl label nodes NAME KEY-
を指定します。
以下のコマンドでは「k8s-node01
」に定義された「disktype
」を削除しています。
1 2 | [root@k8s-master ~]# kubectl label nodes k8s-node01 disktype- node/k8s-node01 labeled |
デフォルトLabel
Node作成時にデフォルトで付与されるラベルは以下の通りです。
- kubernetes.io/hostname
- failure-domain.beta.kubernetes.io/zone
- failure-domain.beta.kubernetes.io/region
- beta.kubernetes.io/instance-type
- kubernetes.io/os
- kubernetes.io/arch
kubernetes.io/hostname は基本的に Node 名 と一致します。
Node Selector
nodeSelector
はその名の通り「Podを配置したいNodeラベル」をキーバリュー形式で指定します。
例えば disktype: ssd
というラベルのある Node へ配置したい場合、以下のような指定をします。
1 2 3 4 5 6 7 8 9 10 11 12 13 | apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd |
この nodeSelector
はいずれなくなるようです。
理由は、この後に説明する nodeAffinity
で代替できるからとのことです。
Node Affinity
nodeAffinity
は nodeSelector
よりも柔軟な Node 指定ができます。
Anti Affinity や、この後に紹介する Taints & Tolerations と維持する動作も表現可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/e2e-az-name operator: In values: - e2e-az1 - e2e-az2 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: another-node-label-key operator: In values: - another-node-label-value |
Node選択する際、「配置する時(DuringScheduling)の必須度合(required または preferred)」と「既に配置されて実行されているPod(DuringExecution)の対応(Ignore または Required)」の組み合わせで4パターンの動作が考えられます。 どのような動作をさせたいかで選択します。
-
requiredDuringSchedulingIgnoredDuringExecution
Pod配置時は必須条件とするが、すでに配置されているPodに対しては無視する。
-
preferredDuringSchedulingIgnoredDuringExecution
Pod配置時にできるだけ配慮して配置する。すでに配置されているPodに対しては無視する。
-
requiredDuringSchedulingRequiredDuringExecution
Pod配置時に必須条件とし、すでに配置されているPodがある場合は退去させる。 Kubernetes v1.14 時点では利用不可。 今後実装予定の機能。
-
preferredDuringSchedulingRequiredDuringExecution組み合わせ上は存在するが機能としては存在しない。
matchExpressions
は key
、 operator
、 values
で構成されます。
key
には条件にしたいNodeのラベル名、values
には値を指定します。
operator
に使える演算子は以下の通りです。
In
NotIn
Exists
DoesNotExist
Gt
Lt
preferredDuringScheduling
には上記の条件に加えて weight
が 1 ~ 100 の範囲で指定できます。
この weight は Node 選択時の演算で利用します。
各 Node においてラベルマッチした個数分 weight
を加算し、最終的に点数の高い Node に Pod を配置します。
Pod Affinity / Anti-Affinity
podAffinity
および podAffinity
はすでに動いているPodをもとにどこへPodを配置するかを定義するものになります。
podAffinity
は「指定されたラベルに一致する Pod が動作している Node がもつ topologyKey
が同一の Node に Pod を配置させる」動作になります。 podAffinity
は「topologyKey
の範囲内に 指定されたラベルに一致するPodが動作していなければ、Pod を topologyKey
範囲内のNodeのいずれかに Pod を配置する」動作になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | apiVersion: v1 kind: Pod metadata: name: with-pod-affinity spec: containers: - name: with-pod-affinity image: k8s.gcr.io/pause:2.0 affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: security operator: In values: - S1 topologyKey: failure-domain.beta.kubernetes.io/zone podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: security operator: In values: - S2 topologyKey: failure-domain.beta.kubernetes.io/zone |
podAffinity
やpodAntiAffinity
はその性質(Nodeに配置されたPodのラベルマッチを行う)ので処理が重くなります。
そのため、数百Nodeもあるようなサービスでは使わないほうが良いようです。
labelSelector
は key
、 operator
、 values
で構成されます。
key
には条件にしたいPodのラベル名、values
には値を指定します。
operator
に使える演算子は以下の通りです。
In
NotIn
Exists
DoseNotExist
topologyKey
は基本的に Node に設定されたラベルになります。
なので、意図的にすべての Node に対して付与しているラベルがないのであれば標準的に付与される以下のようなラベルを利用します。
- kubernetes.io/hostname
- failure-domain.beta.kubernetes.io/zone
- failure-domain.beta.kubernetes.io/region
- beta.kubernetes.io/instance-type
- kubernetes.io/os
- kubernetes.io/arch
今回は「NodeSelector」「Node Affinity」「Pod Affinity / Anti-Affinity」についてまとめました。 参考になったでしょうか? 本記事がお役に立っていると嬉しいです!!
参考記事
最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!