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: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault affinity: podAffinity: 1 requiredDuringSchedulingIgnoredDuringExecution: 2 - labelSelector: matchExpressions: - key: security 3 operator: In 4 values: - S1 5 topologyKey: topology.kubernetes.io/zone containers: - name: with-pod-affinity image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL]
Pod の非アフィニティーが設定された Pod
設定ファイルのサンプル
apiVersion: v1 kind: Pod metadata: name: with-pod-antiaffinity spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault 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 securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL]
ノードのラベルに、Pod のノードのアフィニティールールを満たさなくなるような結果になる変更がランタイム時に生じる場合も、Pod はノードで引き続き実行されます。
4.3.2. Pod アフィニティールールの設定
以下の手順は、ラベルの付いた Pod と Pod のスケジュールを可能にするアフィニティーを使用する Pod を作成する 2 つの Pod の単純な設定を示しています。
アフィニティーをスケジュールされた Pod に直接追加することはできません。
手順
Pod 仕様の特定のラベルの付いた Pod を作成します。
以下の内容を含む YAML ファイルを作成します。
apiVersion: v1 kind: Pod metadata: name: security-s1 labels: security: S1 spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: security-s1 image: docker.io/ocpqe/hello-pod securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault
Pod を作成します。
$ oc create -f <pod-spec>.yaml
他の Pod の作成時に、以下のパラメーターを設定してアフィニティーを追加します。
以下の内容を含む 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
を指定します。演算子はIn
、NotIn
、Exists
、またはDoesNotExist
にすることができます。たとえば、演算子In
を使用してラベルをノードで必要になるようにします。- 5
topologyKey
を指定します。これは、システムがトポロジードメインを表すために使用する事前にデータが設定された Kubernetes ラベル です。
Pod を作成します。
$ oc create -f <pod-spec>.yaml
4.3.3. Pod 非アフィニティールールの設定
以下の手順は、ラベルの付いた Pod と Pod のスケジュールの禁止を試行する非アフィニティーの preferred (優先) ルールを使用する Pod を作成する 2 つの Pod の単純な設定を示しています。
アフィニティーをスケジュールされた Pod に直接追加することはできません。
手順
Pod 仕様の特定のラベルの付いた Pod を作成します。
以下の内容を含む YAML ファイルを作成します。
apiVersion: v1 kind: Pod metadata: name: security-s1 labels: security: S1 spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: security-s1 image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL]
Pod を作成します。
$ oc create -f <pod-spec>.yaml
他の Pod の作成時に、以下のパラメーターを設定します。
以下の内容を含む 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
を指定します。演算子はIn
、NotIn
、Exists
、またはDoesNotExist
にすることができます。たとえば、演算子In
を使用してラベルをノードで必要になるようにします。- 6
topologyKey
を指定します。これは、システムがトポロジードメインを表すために使用する事前にデータが設定された Kubernetes ラベル です。
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: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: ocp image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] # ...
Pod team4a には、
podAffinity
の下にラベルセレクターteam:4
が付けられています。apiVersion: v1 kind: Pod metadata: name: team4a # ... spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault 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 securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] # ...
- 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: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: ocp image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] # ...
Pod pod-s2 には、
podAntiAffinity
の下にラベルセレクターsecurity:s1
が付けられています。apiVersion: v1 kind: Pod metadata: name: pod-s2 # ... spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault 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 securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] # ...
-
Pod pod-s2 は
pod-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: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault containers: - name: ocp image: docker.io/ocpqe/hello-pod securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] # ...
Pod pod-s2 にはラベルセレクター
security:s2
があります。apiVersion: v1 kind: Pod metadata: name: pod-s2 # ... spec: securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault 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 securityContext: allowPrivilegeEscalation: false capabilities: drop: [ALL] # ...
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 が
amd64
やarm64
などの特定のプラットフォームを必要とする場合 - オペレータが 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 の配置を制御するには、次の手順を実行します。
- 通常どおり Operator をインストールします。
- 必要に応じて、ノードがアフィニティーに適切に応答するようにラベル付けされていることを確認してください。
-
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>