Podを指定したNodeに配置する方法

0 件のコメント

今回は「Podを配置するNodeの選択/制限方法」のうち「NodeSelector」「Node Affinity」「Pod Affinity / Anti-Affinity」についてまとめます。 「Taints & Tolerations」は次回まとめます。

Selector または Affinity 、 Taints & Tolerations など似たようなものがいくつかあり、分かりづらいのでまとめてみました。

関連記事

概要

NodeにはあらかじめLabelが指定されています。 Podに対して「NodeのどのLabelと一致させるか」を指定し、Labelが一致するNodeに対してPodを配置していくものです。

Podを意図したNodeに配置したい場合、以下のような定義を利用して指定します。

  • nodeSelector
  • nodeAffinity
  • podAffinity または podAntiAffinity

上記の定義はいずれも Node Label との一致状況を確認するので、まずは Node Label から確認していきましょう。

Node Label

Podの配置にはNodeのラベルが使われます。 なので、何はともあれNodeのラベルとしてどんなものが定義されているのか、どう定義するのかなどを確認しておきます。

現在 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

… (以下省略) …

新たなラベルを 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

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

nodeAffinitynodeSelector よりも柔軟な 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パターンの動作が考えられます。 どのような動作をさせたいかで選択します。

  • requiredDuringSchedulingIgnoredDuringExecution

    Pod配置時は必須条件とするが、すでに配置されているPodに対しては無視する。

  • preferredDuringSchedulingIgnoredDuringExecution

    Pod配置時にできるだけ配慮して配置する。すでに配置されているPodに対しては無視する。

  • requiredDuringSchedulingRequiredDuringExecution

    Pod配置時に必須条件とし、すでに配置されているPodがある場合は退去させる。 Kubernetes v1.14 時点では利用不可。 今後実装予定の機能。

  • preferredDuringSchedulingRequiredDuringExecution

    組み合わせ上は存在するが機能としては存在しない。

matchExpressionskeyoperatorvalues で構成されます。 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 を配置する」動作になります。

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

podAffinitypodAntiAffinityはその性質(Nodeに配置されたPodのラベルマッチを行う)ので処理が重くなります。 そのため、数百Nodeもあるようなサービスでは使わないほうが良いようです。

labelSelectorkeyoperatorvalues で構成されます。 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 の フォロー」 お願いします!!