今回は「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に配置したい場合、以下のような定義を利用して指定します。
nodeSelectornodeAffinitypodAffinityまたはpodAntiAffinity
上記の定義はいずれも Node Label との一致状況を確認するので、まずは Node Label から確認していきましょう。
Node Label
Podの配置にはNodeのラベルが使われます。 なので、何はともあれNodeのラベルとしてどんなものが定義されているのか、どう定義するのかなどを確認しておきます。
Labelの確認
現在 Node に付与されている ラベル を確認するには kubectl describe node NAME で確認できます。
[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:
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
… (以下省略) …
Labelの付与/削除
新たなラベルを Node に付与したい場合は kubectl label nodes NAME KEY=VALUE で付与します。
以下のコマンドでは「k8s-node01」に対して「disktype = ssd」を指定しています。
[root@k8s-master ~]# kubectl label nodes k8s-node01 disktype=ssd node/k8s-node01 labeled
付与したラベルを削除したい場合は kubectl label nodes NAME KEY- を指定します。
以下のコマンドでは「k8s-node01」に定義された「disktype」を削除しています。
[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 へ配置したい場合、以下のような指定をします。
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 と維持する動作も表現可能です。
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パターンの動作が考えられます。 どのような動作をさせたいかで選択します。
-
requiredDuringSchedulingIgnoredDuringExecutionPod配置時は必須条件とするが、すでに配置されているPodに対しては無視する。
-
preferredDuringSchedulingIgnoredDuringExecutionPod配置時にできるだけ配慮して配置する。すでに配置されているPodに対しては無視する。
-
requiredDuringSchedulingRequiredDuringExecutionPod配置時に必須条件とし、すでに配置されているPodがある場合は退去させる。 Kubernetes v1.14 時点では利用不可。 今後実装予定の機能。
-
preferredDuringSchedulingRequiredDuringExecution組み合わせ上は存在するが機能としては存在しない。
matchExpressions は key 、 operator 、 values で構成されます。
key には条件にしたいNodeのラベル名、values には値を指定します。
operator に使える演算子は以下の通りです。
InNotInExistsDoesNotExistGtLt
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 を配置する」動作になります。
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 に使える演算子は以下の通りです。
InNotInExistsDoseNotExist
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 の フォロー」 お願いします!!



