2.7. ノードセレクターの使用による特定ノードへの Pod の配置

ノードセレクター は、キーと値のペアのマップを指定します。ルールは、ノード上のカスタムラベルと Pod で指定されたセレクターを使って定義されます。特定のノードセレクターを使用して特定の Pod を特定のノードに配置し、プロジェクトノードセレクターを使用して新規 Pod をプロジェクトで特定ノード内のプロジェクトに配置することができます。または、クラスタースコープのデフォルトノードセレクターを使用して、新規 Pod をクラスター内の任意の場所に配置することができます。

Pod がノードで実行する要件を満たすには、Pod にはノードのラベルとして同じキーと値のペアがなければなりません。

重要

同じ Pod 設定でノードセレクターとノードのアフィニティーを使用している場合は、以下のルールが Pod のノードへの配置を制御します。

  • nodeSelectornodeAffinity の両方を設定する場合、Pod が候補ノードでスケジュールされるにはどちらの条件も満たしている必要があります。
  • nodeAffinity タイプに関連付けられた複数の nodeSelectorTerms を指定する場合、nodeSelectorTerms のいずれかが満たされている場合に Pod をノードにスケジュールすることができます。
  • nodeSelectorTerms に関連付けられた複数の matchExpressions を指定する場合、すべての matchExpressions が満たされている場合にのみ Pod をノードにスケジュールすることができます。

2.7.1. ノードセレクターの使用による Pod 配置の制御

Pod にノードセレクターのラベルを使用することで、Pod がスケジュールされる場所を制御できます。

ノードセレクターにより、OpenShift Container Platform は一致するラベルが含まれるノード上に Pod をスケジュールします。

ノードセレクターを既存 Pod に追加するには、ノードセレクターをレプリカセット、デーモンセット、またはステートフルセットなどのノードの制御オブジェクトに追加します。制御オブジェクト下の既存 Pod は、一致するラベルを持つノードで再作成されます。新規 Pod を作成する場合、ノードセレクターを Pod 仕様に直接追加できます。

ラベルはノードまたはマシン設定に追加できますが、ノードまたはマシンが停止するとラベルは維持されません。マシンセットにラベルを追加すると、新しいノードまたはマシンにそのラベルが追加されます。

注記

ノードセレクターを既存のスケジュールされている Pod に直接追加することはできません。

前提条件

ノードセレクターを既存 Pod に追加するには、Pod の制御オブジェクトを判別します。たとえば、router-default-66d5cf9464-m2g75 Pod は router-default-66d5cf9464 レプリカセットによって制御されます。

$ oc describe pod router-default-66d5cf9464-7pwkc

Name:               router-default-66d5cf9464-7pwkc
Namespace:          openshift-ingress

....

Controlled By:      ReplicaSet/router-default-66d5cf9464

Web コンソールでは、Pod YAML の ownerReferences に制御オブジェクトを一覧表示します。

  ownerReferences:
    - apiVersion: apps/v1
      kind: ReplicaSet
      name: router-default-66d5cf9464
      uid: d81dd094-da26-11e9-a48a-128e7edf0312
      controller: true
      blockOwnerDeletion: true

手順

  1. マシンセットを使用するか、またはノードを直接編集してラベルをノードに追加します。

    • MachineSet オブジェクトを使用して、ノードの作成時にマシンセットによって管理されるノードにラベルを追加します。

      1. 以下のコマンドを実行してノードセレクターを MachineSet オブジェクトに追加します。

        $ oc patch MachineSet <name> --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"<key>"="<value>","<key>"="<value>"}}]'  -n openshift-machine-api

        以下は例になります。

        $ oc patch MachineSet abc612-msrtw-worker-us-east-1c  --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"type":"user-node","region":"east"}}]'  -n openshift-machine-api
      2. oc edit コマンドを使用して、ラベルが MachineSet オブジェクトに追加されていることを確認します。

        以下は例になります。

        $ oc edit MachineSet abc612-msrtw-worker-us-east-1c -n openshift-machine-api

        MachineSet オブジェクトの例

        apiVersion: machine.openshift.io/v1beta1
        kind: MachineSet
        
        ....
        
        spec:
        ...
          template:
            metadata:
        ...
            spec:
              metadata:
                labels:
                  region: east
                  type: user-node
        ....
    • ラベルをノードに直接追加します。

      1. ノードの Node オブジェクトを編集します。

        $ oc label nodes <name> <key>=<value>

        たとえば、ノードにラベルを付けるには、以下を実行します。

        $ oc label nodes ip-10-0-142-25.ec2.internal type=user-node region=east
      2. ラベルがノードに追加されていることを確認します。

        $ oc get nodes -l type=user-node,region=east

        出力例

        NAME                          STATUS   ROLES    AGE   VERSION
        ip-10-0-142-25.ec2.internal   Ready    worker   17m   v1.18.3+002a51f

  2. 一致するノードセレクターを Pod に追加します。

    • ノードセレクターを既存 Pod および新規 Pod に追加するには、ノードセレクターを Pod の制御オブジェクトに追加します。

      ReplicaSet オブジェクトの例

      kind: ReplicaSet
      
      ....
      
      spec:
      
      ....
      
        template:
          metadata:
            creationTimestamp: null
            labels:
              ingresscontroller.operator.openshift.io/deployment-ingresscontroller: default
              pod-template-hash: 66d5cf9464
          spec:
            nodeSelector:
              beta.kubernetes.io/os: linux
              node-role.kubernetes.io/worker: ''
              type: user-node 1

      1
      ノードセレクターを追加します。
    • ノードセレクターを特定の Pod に追加するには、セレクターを Pod オブジェクトに直接追加します。

      Pod オブジェクトの例

      apiVersion: v1
      kind: Pod
      
      ...
      
      spec:
        nodeSelector:
          <key>: <value>
      
      ...

      以下は例になります。

      ノードセレクターを持つ Pod オブジェクトの例

      apiVersion: v1
      kind: Pod
      
      ....
      
      spec:
        nodeSelector:
          region: east
          type: user-node

2.7.2. クラスタースコープのデフォルトノードセレクターの作成

クラスター内の作成されたすべての Pod を特定のノードに制限するために、デフォルトのクラスタースコープのノードセレクターをノード上のラベルと共に Pod で使用することができます。

クラスター全体のノードセレクターを使用する場合、クラスターで Pod を作成すると、OpenShift Container Platform はデフォルトのノードセレクターを Pod に追加し、一致するラベルのあるノードで Pod をスケジュールします。

スケジューラー Operator カスタムリソース (CR) を作成して、クラスタースコープのノードセレクターを設定します。 Node オブジェクト、MachineSet オブジェクト、または MachineConfig オブジェクトを編集してラベルをノードに追加します。マシンセットにラベルを追加すると、ノードまたはマシンが停止した場合に、新規ノードにそのラベルが追加されます。ノードまたはマシン設定に追加されるラベルは、ノードまたはマシンが停止すると維持されません。

たとえば、スケジューラーはクラスタースコープの region=east ノードセレクターを設定します。

スケジューラー Operator カスタムリソースの例

apiVersion: config.openshift.io/v1
kind: Scheduler
metadata:
  name: cluster
...

spec:
  defaultNodeSelector: type=user-node,region=east 1
...

クラスター内のノードには type=user-node,region=east ラベルがあります。

ノードオブジェクトの例

apiVersion: v1
kind: Node
metadata:
  name: ci-ln-qg1il3k-f76d1-hlmhl-worker-b-df2s4
...
  labels:
    region: east
    type: user-node
...

Pod をクラスターに作成する場合、Pod はクラスタースコープのノードセレクターで作成され、ラベルが付けられたノードにスケジュールされます。

Pod オブジェクトの例

apiVersion: v1
kind: Pod
...

spec:
  nodeSelector:
    region: east
...

ラベルが付けられたノード上の Pod を含む Pod 一覧の例

NAME     READY   STATUS    RESTARTS   AGE   IP           NODE                                       NOMINATED NODE   READINESS GATES
pod-s1   1/1     Running   0          20s   10.131.2.6   ci-ln-qg1il3k-f76d1-hlmhl-worker-b-df2s4   <none>           <none>

注記

Pod を作成するプロジェクトにプロジェクトノードセレクターがある場合、そのセレクターはクラスタースコープのセレクターよりも優先されます。Pod 仕様のノードセレクターがプロジェクトノードセレクターを使用しない場合、Pod は作成されたり、スケジュールされたりしません。

Pod オブジェクトにクラスタースコープのノードセレクターではなく、プロジェクトノードセレクターではないノードセレクターが含まれる場合、Pod は作成またはスケジュールされません。たとえば、以下の Pod をサンプルプロジェクトにデプロイする場合、これは作成されません。

無効なノードセレクターを持つ Pod 出力の例

apiVersion: v1
kind: Pod
....

spec:
  nodeSelector:
    region: west

その仕様から Pod を作成すると、以下のメッセージと同様のエラーが表示されます。

エラーメッセージの例

Error from server (Forbidden): error when creating "pod.yaml": pods "pod-4" is forbidden: pod node label selector conflicts with its project node label selector

注記

Pod にキーと値のペアを追加できます。ただし、デフォルトのプロジェクトキーに異なる値を追加することはできません。

手順

デフォルトのクラスタースコープのセレクターを追加するには、以下を実行します。

  1. スケジューラー Operator カスタムリソースを編集し、クラスターノードクラスターを追加します。

    $ oc edit scheduler cluster

    出力例

    apiVersion: config.openshift.io/v1
    kind: Scheduler
    metadata:
      name: cluster
    ...
    
    spec:
      defaultNodeSelector: type=user-node,region=east 1
      mastersSchedulable: false
      policy:
        name: ""

    1 1
    適切な <key>:<value> ペアが設定されたノードセレクターを追加します。

    この変更を加えた後に、openshift-kube-apiserver プロジェクトの Pod の再デプロイを待機します。これには数分の時間がかかる場合があります。デフォルトのクラスターノードセレクターは、Pod の再起動まで有効になりません。

  2. マシンセットを使用するか、またはノードを直接編集してラベルをノードに追加します。

    • MachineSet オブジェクトを使用して、ノードの作成時にマシンセットによって管理されるノードにラベルを追加します。

      1. 以下のコマンドを実行してノードセレクターを MachineSet オブジェクトに追加します。

        $ oc patch MachineSet <name> --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"<key>"="<value>","<key>"="<value>"}}]'  -n openshift-machine-api 1
        1
        各ノードセレクターに <key> /<value> ペアを追加します。

        以下は例になります。

        $ oc patch MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"type":"user-node","region":"east"}}]'  -n openshift-machine-api
      2. oc edit コマンドを使用して、ラベルが MachineSet オブジェクトに追加されていることを確認します。

        以下は例になります。

        $ oc edit MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api

        出力例

        apiVersion: machine.openshift.io/v1beta1
        kind: MachineSet
        metadata:
        ...
        spec:
        ...
          template:
            metadata:
        ...
            spec:
              metadata:
                labels:
                  region: east
                  type: user-node

      3. 0 にスケールダウンし、ノードをスケールアップして、そのマシンセットに関連付けられたノードを再デプロイします。

        以下は例になります。

        $ oc scale --replicas=0 MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api
        $ oc scale --replicas=1 MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api
      4. ノードの準備ができ、利用可能な状態になったら、oc get コマンドを使用してラベルがノードに追加されていることを確認します。

        $ oc get nodes -l <key>=<value>

        以下は例になります。

        $ oc get nodes -l type=user-node

        出力例

        NAME                                       STATUS   ROLES    AGE   VERSION
        ci-ln-l8nry52-f76d1-hl7m7-worker-c-vmqzp   Ready    worker   61s   v1.18.3+002a51f

    • ラベルをノードに直接追加します。

      1. ノードの Node オブジェクトを編集します。

        $ oc label nodes <name> <key>=<value>

        たとえば、ノードにラベルを付けるには、以下を実行します。

        $ oc label nodes ci-ln-l8nry52-f76d1-hl7m7-worker-b-tgq49 type=user-node region=east
      2. oc get コマンドを使用して、ラベルがノードに追加されていることを確認します。

        $ oc get nodes -l <key>=<value>,<key>=<value>

        以下は例になります。

        $ oc get nodes -l type=user-node,region=east

        出力例

        NAME                                       STATUS   ROLES    AGE   VERSION
        ci-ln-l8nry52-f76d1-hl7m7-worker-b-tgq49   Ready    worker   17m   v1.18.3+002a51f

2.7.3. プロジェクトスコープのノードセレクターの作成

プロジェクトで作成されたすべての Pod をラベルが付けられたノードに制限するために、プロジェクトのノードセレクターをノード上のラベルと共に使用できます。

このプロジェクトで Pod を作成する場合、OpenShift Container Platform はノードセレクターをプロジェクトの Pod に追加し、プロジェクトの一致するラベルを持つノードで Pod をスケジュールします。クラスタースコープのデフォルトノードセレクターがない場合、プロジェクトノードセレクターが優先されます。

ラベル定義が含まれる openshift.io/node-selector パラメーターを追加するには、Namespace オブジェクトを編集してラベルをプロジェクトに追加します。Node オブジェクト、 MachineSet オブジェクト、または MachineConfig オブジェクトを編集してラベルをノードに追加します。マシンセットにラベルを追加すると、ノードまたはマシンが停止した場合に、新規ノードにそのラベルが追加されます。ノードまたはマシン設定に追加されるラベルは、ノードまたはマシンが停止すると維持されません。

注記

Pod にキーと値のペアを追加できます。ただし、デフォルトのプロジェクトキーに異なる値を追加することはできません。

たとえば、以下のプロジェクトには region=east ノードセレクターがあります。

Namespace オブジェクトの例

apiVersion: v1
kind: Namespace
metadata:
  annotations:
    openshift.io/node-selector: "region=east"
...

以下のノードには type=user-node,region=east ラベルがあります。

Node オブジェクトの例

apiVersion: v1
kind: Node
metadata:
  name: ci-ln-qg1il3k-f76d1-hlmhl-worker-b-df2s4
...
  labels:
    region: east
    type: user-node
...

Pod をこのサンプルプロジェクトで作成する場合、Pod はプロジェクトノードセレクターで作成され、ラベルが付けられたノードにスケジュールされます。

Pod オブジェクトの例

apiVersion: v1
kind: Pod
metadata:
...
spec:
  nodeSelector:
    region: east
    type: user-node
...

ラベルが付けられたノード上の Pod を含む Pod 一覧の例

NAME     READY   STATUS    RESTARTS   AGE   IP           NODE                                       NOMINATED NODE   READINESS GATES
pod-s1   1/1     Running   0          20s   10.131.2.6   ci-ln-qg1il3k-f76d1-hlmhl-worker-b-df2s4   <none>           <none>

Pod に異なるノードセレクターが含まれる場合、プロジェクトの Pod は作成またはスケジュールされません。たとえば、以下の Pod をサンプルプロジェクトにデプロイする場合、これは作成されません。

無効なノードセレクターを持つ Pod オブジェクトの例

apiVersion: v1
kind: Pod
...

spec:
  nodeSelector:
    region: west

....

Pod を作成すると、以下のメッセージと同様のエラーが表示されます。

エラーメッセージの例

Error from server (Forbidden): error when creating "pod.yaml": pods "pod-4" is forbidden: pod node label selector conflicts with its project node label selector

手順

デフォルトのプロジェクトノードセレクターを追加するには、以下を実行します。

  1. プロジェクトを作成するか、または既存プロジェクトを編集して openshift.io/node-selector パラメーターを追加します。

    $ oc edit project <name>
    apiVersion: v1
    kind: Project
    metadata:
      annotations:
        openshift.io/node-selector: "type=user-node,region=east" 1
        openshift.io/sa.scc.mcs: s0:c17,c14
        openshift.io/sa.scc.supplemental-groups: 1000300000/10000
        openshift.io/sa.scc.uid-range: 1000300000/10000
      creationTimestamp: 2019-06-10T14:39:45Z
      labels:
        openshift.io/run-level: "0"
      name: demo
      resourceVersion: "401885"
      selfLink: /api/v1/namespaces/openshift-kube-apiserver
      uid: 96ecc54b-8b8d-11e9-9f54-0a9ae641edd0
    spec:
      finalizers:
      - kubernetes
    status:
      phase: Active
    1
    適切な <key>:<value> ペアを持つ openshift.io/node-selector を追加します。
  2. マシンセットを使用するか、またはノードを直接編集してラベルをノードに追加します。

    • MachineSet オブジェクトを使用して、ノードの作成時にマシンセットによって管理されるノードにラベルを追加します。

      1. 以下のコマンドを実行してノードセレクターを MachineSet オブジェクトに追加します。

        $ oc patch MachineSet <name> --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"<key>"="<value>","<key>"="<value>"}}]'  -n openshift-machine-api

        以下は例になります。

        $ oc patch MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c --type='json' -p='[{"op":"add","path":"/spec/template/spec/metadata/labels", "value":{"type":"user-node","region":"east"}}]'  -n openshift-machine-api
      2. oc edit コマンドを使用して、ラベルが MachineSet オブジェクトに追加されていることを確認します。

        以下は例になります。

        $ oc edit MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api

        出力例

        apiVersion: machine.openshift.io/v1beta1
        kind: MachineSet
        metadata:
        ...
        spec:
        ...
          template:
            metadata:
        ...
            spec:
              metadata:
                labels:
                  region: east
                  type: user-node

      3. そのマシンセットに関連付けられたノードを再デプロイします。

        以下は例になります。

        $ oc scale --replicas=0 MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api
        $ oc scale --replicas=1 MachineSet ci-ln-l8nry52-f76d1-hl7m7-worker-c -n openshift-machine-api
      4. oc get コマンドを使用して、ノードの準備ができ、利用可能な場合にラベルが Node オブジェクトに追加されていることを確認します。

        $ oc label MachineSet abc612-msrtw-worker-us-east-1c type=user-node region=east

        以下は例になります。

        $ oc get nodes -l type=user-node

        出力例

        NAME                                       STATUS   ROLES    AGE   VERSION
        ci-ln-l8nry52-f76d1-hl7m7-worker-c-vmqzp   Ready    worker   61s   v1.18.3+002a51f

    • ラベルをノードに直接追加します。

      1. Node オブジェクトを編集してラベルを追加します。

        $ oc label <resource> <name> <key>=<value>

        たとえば、ノードにラベルを付けるには、以下を実行します。

        $ oc label nodes ci-ln-l8nry52-f76d1-hl7m7-worker-c-tgq49 type=user-node region=east
      2. oc get コマンドを使用して、ラベルが Node オブジェクトに追加されていることを確認します。

        $ oc get nodes -l <key>=<value>

        以下は例になります。

        $ oc get nodes -l type=user-node,region=east

        出力例

        NAME                                       STATUS   ROLES    AGE   VERSION
        ci-ln-l8nry52-f76d1-hl7m7-worker-b-tgq49   Ready    worker   17m   v1.18.3+002a51f