4.4. ノードのアフィニティールールを使用したノード上での Pod 配置の制御

アフィニティーとは、スケジュールするノードを制御する Pod の特性です。

OpenShift Container Platformnode では、アフィニティーとはスケジューラーが Pod を配置する場所を決定するために使用する一連のルールのことです。このルールは、ノードのカスタムラベルと Pod で指定されたラベルセレクターを使用して定義されます。

4.4.1. ノードのアフィニティーについて

ノードのアフィニティーにより、Pod がその配置に使用できるノードのグループに対してアフィニティーを指定できます。ノード自体は配置に対して制御を行いません。

たとえば、Pod を特定の CPU を搭載したノードまたは特定のアベイラビリティーゾーンにあるノードでのみ実行されるよう設定することができます。

ノードのアフィニティールールには、required (必須) および preferred (優先) の 2 つのタイプがあります。

Pod をノードにスケジュールする前に、required (必須) ルールを 満たしている必要があります。preferred (優先) ルールは、ルールを満たす場合に、スケジューラーはルールの実施を試行しますが、その実施が必ずしも保証される訳ではありません。

注記

ランタイム時にノードのラベルに変更が生じ、その変更により Pod でのノードのアフィニティールールを満たさなくなる状態が生じるでも、Pod はノードで引き続き実行されます。

ノードのアフィニティーは Pod 仕様ファイルで設定します。required (必須) ルール、preferred (優先) ルールのいずれか、その両方を指定することができます。両方を指定する場合、ノードは最初に required (必須) ルールを満たす必要があり、その後に preferred (優先) ルールを満たそうとします。

以下の例は、Pod をキーが e2e-az-NorthSouth で、その値が e2e-az-North または e2e-az-South のいずれかであるラベルの付いたノードに Pod を配置することを求めるルールが設定された Pod 仕様です。

ノードのアフィニティーの required (必須) ルールが設定された Pod 設定ファイルのサンプル

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity: 1
      requiredDuringSchedulingIgnoredDuringExecution: 2
        nodeSelectorTerms:
        - matchExpressions:
          - key: e2e-az-NorthSouth 3
            operator: In 4
            values:
            - e2e-az-North 5
            - e2e-az-South 6
  containers:
  - name: with-node-affinity
    image: docker.io/ocpqe/hello-pod
#...

1
ノードのアフィニティーを設定するためのスタンザです。
2
required (必須) ルールを定義します。
3 5 6
ルールを適用するために一致している必要のあるキー/値のペア (ラベル) です。
4
演算子は、ノードのラベルと Pod 仕様の matchExpression パラメーターの値のセットの間の関係を表します。この値は、InNotInExists、または DoesNotExistLt、または Gt にすることができます。

以下の例は、キーが e2e-az-EastWest で、その値が e2e-az-East または e2e-az-West のラベルが付いたノードに Pod を配置すること優先する preferred (優先) ルールが設定されたノード仕様です。

ノードのアフィニティーの preferred (優先) ルールが設定された Pod 設定ファイルのサンプル

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity: 1
      preferredDuringSchedulingIgnoredDuringExecution: 2
      - weight: 1 3
        preference:
          matchExpressions:
          - key: e2e-az-EastWest 4
            operator: In 5
            values:
            - e2e-az-East 6
            - e2e-az-West 7
  containers:
  - name: with-node-affinity
    image: docker.io/ocpqe/hello-pod
#...

1
ノードのアフィニティーを設定するためのスタンザです。
2
preferred (優先) ルールを定義します。
3
preferred (優先) ルールの重みを指定します。最も高い重みを持つノードが優先されます。
4 6 7
ルールを適用するために一致している必要のあるキー/値のペア (ラベル) です。
5
演算子は、ノードのラベルと Pod 仕様の matchExpression パラメーターの値のセットの間の関係を表します。この値は、InNotInExists、または DoesNotExistLt、または Gt にすることができます。

ノードの非アフィニティー についての明示的な概念はありませんが、NotIn または DoesNotExist 演算子を使用すると、動作が複製されます。

注記

同じ Pod 設定でノードのアフィニティーとノードのセレクターを使用している場合は、以下に注意してください。

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

4.4.2. ノードアフィニティーの required (必須) ルールの設定

Pod をノードにスケジュールする前に、required (必須) ルールを 満たしている必要があります

手順

以下の手順は、ノードとスケジューラーがノードに配置する必要のある Pod を作成する単純な設定を示しています。

  1. oc label node コマンドを使用してラベルをノードに追加します。

    $ oc label node node1 e2e-az-name=e2e-az1
    ヒント

    あるいは、以下の YAML を適用してラベルを追加できます。

    kind: Node
    apiVersion: v1
    metadata:
      name: <node_name>
      labels:
        e2e-az-name: e2e-az1
    #...
  2. Pod 仕様の特定のラベルの付いた Pod を作成します。

    1. 以下の内容を含む YAML ファイルを作成します。

      注記

      アフィニティーをスケジュールされた Pod に直接追加することはできません。

      出力例

      apiVersion: v1
      kind: Pod
      metadata:
        name: s1
      spec:
        affinity: 1
          nodeAffinity:
            requiredDuringSchedulingIgnoredDuringExecution: 2
              nodeSelectorTerms:
              - matchExpressions:
                - key: e2e-az-name 3
                  values:
                  - e2e-az1
                  - e2e-az2
                  operator: In 4
      #...

      1
      Pod のアフィニティーを追加します。
      2
      requiredDuringSchedulingIgnoredDuringExecution パラメーターを設定します。
      3
      満たす必要のある key および values を指定します。新規 Pod を編集したノードにスケジュールする必要がある場合、ノードのラベルと同じ key および values パラメーターを使用します。
      4
      Operator を指定します。演算子は InNotInExists、または DoesNotExist にすることができます。たとえば、演算子 In を使用してラベルをノードで必要になるようにします。
    2. Pod を作成します。

      $ oc create -f <file-name>.yaml

4.4.3. ノードアフィニティーの preferred (優先) ルールの設定

preferred (優先) ルールは、ルールを満たす場合に、スケジューラーはルールの実施を試行しますが、その実施が必ずしも保証される訳ではありません。

手順

以下の手順は、ノードとスケジューラーがノードに配置しようとする Pod を作成する単純な設定を示しています。

  1. oc label node コマンドを使用してラベルをノードに追加します。

    $ oc label node node1 e2e-az-name=e2e-az3
  2. 特定のラベルの付いた Pod を作成します。

    1. 以下の内容を含む YAML ファイルを作成します。

      注記

      アフィニティーをスケジュールされた Pod に直接追加することはできません。

      apiVersion: v1
      kind: Pod
      metadata:
        name: s1
      spec:
        affinity: 1
          nodeAffinity:
            preferredDuringSchedulingIgnoredDuringExecution: 2
            - weight: 3
              preference:
                matchExpressions:
                - key: e2e-az-name 4
                  values:
                  - e2e-az3
                  operator: In 5
      #...
      1
      Pod のアフィニティーを追加します。
      2
      preferredDuringSchedulingIgnoredDuringExecution パラメーターを設定します。
      3
      ノードの重みを数字の 1-100 で指定します。最も高い重みを持つノードが優先されます。
      4
      満たす必要のある key および values を指定します。新規 Pod を編集したノードにスケジュールする必要がある場合、ノードのラベルと同じ key および values パラメーターを使用します。
      5
      Operator を指定します。演算子は InNotInExists、または DoesNotExist にすることができます。たとえば、演算子 In を使用してラベルをノードで必要になるようにします。
    2. Pod を作成します。

      $ oc create -f <file-name>.yaml

4.4.4. ノードのアフィニティールールの例

以下の例は、ノードのアフィニティーを示しています。

4.4.4.1. 一致するラベルを持つノードのアフィニティー

以下の例は、一致するラベルを持つノードと Pod のノードのアフィニティーを示しています。

  • Node1 ノードにはラベル zone:us があります。

    $ oc label node node1 zone=us
    ヒント

    あるいは、以下の YAML を適用してラベルを追加できます。

    kind: Node
    apiVersion: v1
    metadata:
      name: <node_name>
      labels:
        zone: us
    #...
  • pod-s1 pod にはノードアフィニティーの required (必須) ルールの下に zoneus のキー/値のペアがあります。

    $ cat pod-s1.yaml

    出力例

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s1
    spec:
      containers:
        - image: "docker.io/ocpqe/hello-pod"
          name: hello-pod
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                - key: "zone"
                  operator: In
                  values:
                  - us
    #...

  • pod-s1 pod は Node1 でスケジュールできます。

    $ oc get pod -o wide

    出力例

    NAME     READY     STATUS       RESTARTS   AGE      IP      NODE
    pod-s1   1/1       Running      0          4m       IP1     node1

4.4.4.2. 一致するラベルのないノードのアフィニティー

以下の例は、一致するラベルを持たないノードと Pod のノードのアフィニティーを示しています。

  • Node1 ノードにはラベル zone:emea があります。

    $ oc label node node1 zone=emea
    ヒント

    あるいは、以下の YAML を適用してラベルを追加できます。

    kind: Node
    apiVersion: v1
    metadata:
      name: <node_name>
      labels:
        zone: emea
    #...
  • pod-s1 pod にはノードアフィニティーの required (必須) ルールの下に zoneus のキー/値のペアがあります。

    $ cat pod-s1.yaml

    出力例

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s1
    spec:
      containers:
        - image: "docker.io/ocpqe/hello-pod"
          name: hello-pod
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                - key: "zone"
                  operator: In
                  values:
                  - us
    #...

  • pod-s1 pod は Node1 でスケジュールすることができません。

    $ oc describe pod pod-s1

    出力例

    ...
    
    Events:
     FirstSeen LastSeen Count From              SubObjectPath  Type                Reason
     --------- -------- ----- ----              -------------  --------            ------
     1m        33s      8     default-scheduler Warning        FailedScheduling    No nodes are available that match all of the following predicates:: MatchNodeSelector (1).

4.4.5. ノードアフィニティーを使用して Operator がインストールされる場所を制御する

デフォルトでは、Operator をインストールすると、OpenShift Container Platform は Operator Pod をワーカーノードの 1 つにランダムにインストールします。ただし、特定のノードまたはノードのセットでその Pod をスケジュールする必要がある場合があります。

以下の例では、Operator Pod を特定のノードまたはノードのセットにスケジュールする状況について説明します。

  • Operator が amd64arm64 などの特定のプラットフォームを必要とする場合
  • オペレータが Linux や Windows などの特定のオペレーティングシステムを必要とする場合
  • 同じホストまたは同じラックに配置されたホストでスケジュールされた一緒に動作する Operator が必要な場合
  • ネットワークまたはハードウェアの問題によるダウンタイムを回避するために、Operator をインフラストラクチャー全体に分散させたい場合

Operator の Subscription オブジェクトにノードアフィニティーの制約を追加することで、Operator Pod がインストールされる場所を制御できます。

次の例は、ノードアフィニティーを使用して、Custom Metrics Autoscaler Operator のインスタンスをクラスター内の特定のノードにインストールする方法を示しています。

Operator Pod を特定のノードに配置するノードアフィニティーの例

apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: openshift-custom-metrics-autoscaler-operator
  namespace: openshift-keda
spec:
  name: my-package
  source: my-operators
  sourceNamespace: operator-registries
  config:
    affinity:
      nodeAffinity: 1
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: kubernetes.io/hostname
              operator: In
              values:
              - ip-10-0-163-94.us-west-2.compute.internal
#...

1
Operator の Pod を ip-10-0-163-94.us-west-2.compute.internal という名前のノードでスケジュールする必要があるノードアフィニティー。

Operator Pod を特定のプラットフォームのノードに配置するノードアフィニティーの例

apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
  name: openshift-custom-metrics-autoscaler-operator
  namespace: openshift-keda
spec:
  name: my-package
  source: my-operators
  sourceNamespace: operator-registries
  config:
    affinity:
      nodeAffinity: 1
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
          - matchExpressions:
            - key: kubernetes.io/arch
              operator: In
              values:
              - arm64
            - key: kubernetes.io/os
              operator: In
              values:
              - linux
#...

1
Operator の Pod を kubernetes.io/arch=arm64 および kubernetes.io/os=linux ラベルを持つノードでスケジュールする必要があるノードアフィニティー。

手順

Operator Pod の配置を制御するには、次の手順を実行します。

  1. 通常どおり Operator をインストールします。
  2. 必要に応じて、ノードがアフィニティーに適切に応答するようにラベル付けされていることを確認してください。
  3. Operator Subscription オブジェクトを編集してアフィニティーを追加します。

    apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: openshift-custom-metrics-autoscaler-operator
      namespace: openshift-keda
    spec:
      name: my-package
      source: my-operators
      sourceNamespace: operator-registries
      config:
        affinity: 1
          nodeAffinity:
            requiredDuringSchedulingIgnoredDuringExecution:
              nodeSelectorTerms:
              - matchExpressions:
                - key: kubernetes.io/hostname
                  operator: In
                  values:
                  - ip-10-0-185-229.ec2.internal
    #...
    1
    nodeAffinity を追加します。

検証

  • Pod が特定のノードにデプロイされていることを確認するには、次のコマンドを実行します。

    $ oc get pods -o wide

    出力例

    NAME                                                  READY   STATUS    RESTARTS   AGE   IP            NODE                           NOMINATED NODE   READINESS GATES
    custom-metrics-autoscaler-operator-5dcc45d656-bhshg   1/1     Running   0          50s   10.131.0.20   ip-10-0-185-229.ec2.internal   <none>           <none>

4.4.6. 関連情報