4.3. アフィニティールールと非アフィニティールールの使用による他の Pod との相対での Pod の配置

アフィニティーとは、スケジュールするノードを制御する Pod の特性です。非アフィニティーとは、Pod がスケジュールされることを拒否する Pod の特性です。

OpenShift Container Platform では、Pod のアフィニティーPod の非アフィニティー によって、他の Pod のキー/値ラベルに基づいて、Pod のスケジュールに適したノードを制限できます。

4.3.1. Pod のアフィニティーについて

Pod のアフィニティーPod の非アフィニティー によって、他の Pod のキー/値ラベルに基づいて、Pod をスケジュールすることに適したノードを制限することができます。

  • Pod のアフィニティーはスケジューラーに対し、新規 Pod のラベルセレクターが現在の Pod のラベルに一致する場合に他の Pod と同じノードで新規 Pod を見つけるように指示します。
  • Pod の非アフィニティーは、新規 Pod のラベルセレクターが現在の Pod のラベルに一致する場合に、同じラベルを持つ Pod と同じノードで新規 Pod を見つけることを禁止します。

たとえば、アフィニティールールを使用することで、サービス内で、または他のサービスの Pod との関連で Pod を分散したり、パックしたりすることができます。非アフィニティールールにより、特定のサービスの Pod がそののサービスの Pod のパフォーマンスに干渉すると見なされる別のサービスの Pod と同じノードでスケジュールされることを防ぐことができます。または、関連する障害を減らすために複数のノード、アベイラビリティーゾーン、またはアベイラビリティーセットの間でサービスの Pod を分散することもできます。

注記

ラベルセレクターは、複数の Pod デプロイメントを持つ Pod に一致する可能性があります。非アフィニティールールを設定して Pod が一致しないようにする場合は、一意のラベル組み合わせを使用します。

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

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

注記

Pod の優先順位およびプリエンプションの設定により、スケジューラーはアフィニティーの要件に違反しなければ Pod の適切なノードを見つけられない可能性があります。その場合、Pod はスケジュールされない可能性があります。

この状態を防ぐには、優先順位が等しい Pod との Pod のアフィニティーの設定を慎重に行ってください。

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

以下の例は、Pod のアフィニティーおよび非アフィニティーに設定される Pod 仕様を示しています。

この例では、Pod のアフィニティールールは ノードにキー security と値 S1 を持つラベルの付いた 1 つ以上の Pod がすでに実行されている場合にのみ Pod をノードにスケジュールできることを示しています。Pod の非アフィニティールールは、ノードがキー security と値 S2 を持つラベルが付いた Pod がすでに実行されている場合は Pod をノードにスケジュールしないように設定することを示しています。

Pod のアフィニティーが設定された Pod 設定ファイルのサンプル

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity: 1
      requiredDuringSchedulingIgnoredDuringExecution: 2
      - labelSelector:
          matchExpressions:
          - key: security 3
            operator: In 4
            values:
            - S1 5
        topologyKey: failure-domain.beta.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: docker.io/ocpqe/hello-pod

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

Pod の非アフィニティーが設定された Pod 設定ファイルのサンプル

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-antiaffinity
spec:
  affinity:
    podAntiAffinity: 1
      preferredDuringSchedulingIgnoredDuringExecution: 2
      - weight: 100  3
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security 4
              operator: In 5
              values:
              - S2
          topologyKey: kubernetes.io/hostname
  containers:
  - name: with-pod-affinity
    image: docker.io/ocpqe/hello-pod

1
Pod の非アフィニティーを設定するためのスタンザです。
2
preferred (優先) ルールを定義します。
3
preferred (優先) ルールの重みを指定します。最も高い重みを持つノードが優先されます。
4
非アフィニティールールが適用される時を決定する Pod ラベルの説明です。ラベルのキーおよび値を指定します。
5
演算子は、既存 Pod のラベルと新規 Pod の仕様の matchExpression パラメーターの値のセットの間の関係を表します。これには InNotInExists、または DoesNotExist のいずれかを使用できます。
注記

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

4.3.2. Pod アフィニティールールの設定

以下の手順は、ラベルの付いた Pod と Pod のスケジュールを可能にするアフィニティーを使用する Pod を作成する 2 つの Pod の単純な設定を示しています。

注記

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

手順

  1. Pod 仕様の特定のラベルの付いた Pod を作成します。

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

      apiVersion: v1
      kind: Pod
      metadata:
        name: security-s1
        labels:
          security: S1
      spec:
        containers:
        - name: security-s1
          image: docker.io/ocpqe/hello-pod
    2. Pod を作成します。

      $ oc create -f <pod-spec>.yaml
  2. 他の Pod の作成時に、以下のパラメーターを設定してアフィニティーを追加します。

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

      apiVersion: v1
      kind: Pod
      metadata:
        name: security-s1-east
      #...
      spec
        affinity 1
          podAffinity:
            requiredDuringSchedulingIgnoredDuringExecution: 2
            - labelSelector:
                matchExpressions:
                - key: security 3
                  values:
                  - S1
                  operator: In 4
              topologyKey: topology.kubernetes.io/zone 5
      #...
      1
      Pod のアフィニティーを追加します。
      2
      requiredDuringSchedulingIgnoredDuringExecution パラメーターまたは preferredDuringSchedulingIgnoredDuringExecution パラメーターを設定します。
      3
      満たす必要のある key および values を指定します。新規 Pod を他の Pod と共にスケジュールする必要がある場合、最初の Pod のラベルと同じ key および values パラメーターを使用します。
      4
      Operator を指定します。演算子は InNotInExists、または DoesNotExist にすることができます。たとえば、演算子 In を使用してラベルをノードで必要になるようにします。
      5
      topologyKey を指定します。これは、システムがトポロジードメインを表すために使用する事前にデータが設定された Kubernetes ラベル です。
    2. Pod を作成します。

      $ oc create -f <pod-spec>.yaml

4.3.3. Pod 非アフィニティールールの設定

以下の手順は、ラベルの付いた Pod と Pod のスケジュールの禁止を試行する非アフィニティーの preferred (優先) ルールを使用する Pod を作成する 2 つの Pod の単純な設定を示しています。

注記

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

手順

  1. Pod 仕様の特定のラベルの付いた Pod を作成します。

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

      apiVersion: v1
      kind: Pod
      metadata:
        name: security-s1
        labels:
          security: S1
      spec:
        containers:
        - name: security-s1
          image: docker.io/ocpqe/hello-pod
    2. Pod を作成します。

      $ oc create -f <pod-spec>.yaml
  2. 他の Pod の作成時に、以下のパラメーターを設定します。

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

      apiVersion: v1
      kind: Pod
      metadata:
        name: security-s2-east
      #...
      spec
        affinity 1
          podAntiAffinity:
            preferredDuringSchedulingIgnoredDuringExecution: 2
            - weight: 100 3
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                  - key: security 4
                    values:
                    - S1
                    operator: In 5
                topologyKey: kubernetes.io/hostname 6
      #...
      1
      Pod の非アフィニティーを追加します。
      2
      requiredDuringSchedulingIgnoredDuringExecution パラメーターまたは preferredDuringSchedulingIgnoredDuringExecution パラメーターを設定します。
      3
      優先ルールの場合、ノードの重みを 1 ~ 100 で指定します。最も高い重みを持つノードが優先されます。
      4
      満たす必要のある key および values を指定します。新規 Pod を他の Pod と共にスケジュールされないようにする必要がある場合、最初の Pod のラベルと同じ key および values パラメーターを使用します。
      5
      Operator を指定します。演算子は InNotInExists、または DoesNotExist にすることができます。たとえば、演算子 In を使用してラベルをノードで必要になるようにします。
      6
      topologyKey を指定します。これは、システムがトポロジードメインを表すために使用する事前にデータが設定された Kubernetes ラベル です。
    2. Pod を作成します。

      $ oc create -f <pod-spec>.yaml

4.3.4. Pod のアフィニティールールと非アフィニティールールの例

以下の例は、Pod のアフィニティーおよび非アフィニティーについて示しています。

4.3.4.1. Pod のアフィニティー

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

  • Pod team4 にはラベル team:4 が付けられています。

    apiVersion: v1
    kind: Pod
    metadata:
      name: team4
      labels:
         team: "4"
    #...
    spec:
      containers:
      - name: ocp
        image: docker.io/ocpqe/hello-pod
    #...
  • Pod team4a には、podAffinity の下にラベルセレクター team:4 が付けられています。

    apiVersion: v1
    kind: Pod
    metadata:
      name: team4a
    #...
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: team
                operator: In
                values:
                - "4"
            topologyKey: kubernetes.io/hostname
      containers:
      - name: pod-affinity
        image: docker.io/ocpqe/hello-pod
    #...
  • team4a Pod は team4 Pod と同じノードにスケジュールされます。

4.3.4.2. Pod の非アフィニティー

以下の例は、一致するラベルとラベルセレクターを持つ Pod についての Pod の非アフィニティーを示しています。

  • Pod pod-s1 にはラベル security:s1 が付けられています。

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s1
      labels:
        security: s1
    #...
    spec:
      containers:
      - name: ocp
        image: docker.io/ocpqe/hello-pod
    #...
  • Pod pod-s2 には、podAntiAffinity の下にラベルセレクター security:s1 が付けられています。

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s2
    #...
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: security
                operator: In
                values:
                - s1
            topologyKey: kubernetes.io/hostname
      containers:
      - name: pod-antiaffinity
        image: docker.io/ocpqe/hello-pod
    #...
  • Pod pod-s2pod-s1 と同じノードにスケジュールできません。

4.3.4.3. 一致するラベルのない Pod のアフィニティー

以下の例は、一致するラベルとラベルセレクターのない Pod についての Pod のアフィニティーを示しています。

  • Pod pod-s1 にはラベル security:s1 が付けられています。

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s1
      labels:
        security: s1
    #...
    spec:
      containers:
      - name: ocp
        image: docker.io/ocpqe/hello-pod
    #...
  • Pod pod-s2 にはラベルセレクター security:s2 があります。

    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-s2
    #...
    spec:
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: security
                operator: In
                values:
                - s2
            topologyKey: kubernetes.io/hostname
      containers:
      - name: pod-affinity
        image: docker.io/ocpqe/hello-pod
    #...
  • Pod pod-s2 は、security:s2 ラベルの付いた Pod を持つノードがない場合はスケジュールされません。そのラベルの付いた他の Pod がない場合、新規 Pod は保留状態のままになります。

    出力例

    NAME      READY     STATUS    RESTARTS   AGE       IP        NODE
    pod-s2    0/1       Pending   0          32s       <none>

4.3.5. Pod のアフィニティーと非アフィニティーを使用して、Operator がインストールされている場所を制御する

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

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

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

Operator の サブスクリプション オブジェクトに Pod アフィニティーまたは非アフィニティーを追加することで、Operator Pod がインストールされる場所を制御できます。

次の例は、Pod の非アフィニティーを使用して、特定のラベルを持つ Pod を持つノードから Custom Metrics Autoscaler Operator がインストールされないようにする方法を示しています。

Operator Pod を 1 つ以上の特定のノードに配置する 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:
      podAffinity: 1
        requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - test
          topologyKey: kubernetes.io/hostname
#...

1
app=test ラベルを持つ Pod を持つノードに Operator の Pod を配置する Pod アフィニティー。

Operator Pod が 1 つ以上の特定のノードからアクセスできないようにする 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:
      podAntiAffinity: 1
        requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            matchExpressions:
            - key: cpu
              operator: In
              values:
              - high
          topologyKey: kubernetes.io/hostname
#...

1
Operator の Pod が cpu=high ラベルの Pod を持つノードでスケジュールされないようにする Pod 非アフィニティー。

手順

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:
          podAntiAffinity: 1
            requiredDuringSchedulingIgnoredDuringExecution:
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                  - key: kubernetes.io/hostname
                    operator: In
                    values:
                    - ip-10-0-185-229.ec2.internal
                topologyKey: topology.kubernetes.io/zone
    #...
    1
    podAffinity または podAntiAffinity を追加します。

検証

  • 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>