継続的統合デプロイメント - k8s - 高度なスケジューリング - アフィニティ
1. アフィニティの基本概念
Kubernetes
では、アフィニティ (Affinity
) は、ポッドとノードとのアフィニティの一致方法を指定する高度なスケジューリング メカニズムです。アフィニティ ルールを使用すると、 Pod
を特定のノードにスケジュールする方法を制御して、アプリケーションのニーズと制約をより適切に満たすことができます。
亲和力规则
分为两种类型:node亲和性
和pod亲和性
。
-
ノード アフィニティ:
- ノード アフィニティ ルールを使用すると、
Pod
特定のラベルを持つノードにスケジュールするよう指定
- ノード アフィニティ ルールを使用すると、
-
ポッドのアフィニティ:
- ポッド アフィニティ ルールを使用すると、ポッドを他のポッドと同じノードにデプロイする必要があることを指定できます。この種のルールにより、特定の関連する Pod が同じノードにスケジュールされるようになり、ネットワーク遅延が削減されたり、ローカルのパフォーマンスが向上したりすることができます。
汚れと寛容に比べて、汚れと寛容は排除効果がありやすいです。私の汚れを許容できるならあなたは来てください、私の汚れを許容できないならあなたは去ります。
アフィニティと呼ばれる次の新しいスケジュール効果を見てみましょう。アフィニティは汚染耐性の正反対であり、Pod が可能な限り特定の場所に移動するように構成することを意味します。一方、アンチアフィニティはアフィニティの正反対で、Pod が可能な限り特定の場所に移動しないことを意味します。これは汚染と同じ効果があります。
テイントはテイントとトレランスを使用してラベル付けされますが、アフィニティ マッチングではラベルが使用されます。親和性が高いほど、スケジュールによって選択される可能性が高くなります。
テイントとアフィニティを組み合わせると、より詳細で複雑かつインテリジェントなスケジューリング機能を実現できます。
2. 親和性と非親和性
nodeSelector
は、 Pod
を特定のラベルを持つノードに制限する最も簡単な方法を提供します。アフィニティと反アフィニティにより、定義できる制約の種類が拡張されます。アフィニティと反アフィニティを使用する利点は次のとおりです。
- アフィニティ言語と反アフィニティ言語は、より強力な表現力を持っています。
nodeSelector
指定されたすべてのラベルを持つノードのみを選択できます。アフィニティと非アフィニティを使用すると、選択ロジックをより詳細に制御できます。 - ルールを「ソフト要件」または「設定」としてマークすると、一致するノードが見つからない場合でもスケジューラーがポッドをスケジュールできるようになります。
- ノード自体のラベルを使用するだけでなく、ノード上 (または他のトポロジ ドメイン内) で実行されている他の Pod からのラベルを使用してスケジュール制約を適用できます。この機能を使用すると、ポッドを一緒に配置できるルールを定義できます。
アフィニティ機能は、次の 2 種類のアフィニティで構成されます。
节点亲和性
はnodeSelector
フィールドと同様に機能しますが、より表現力が高く、ソフト ルールを指定できます。- ポッド間のアフィニティ/アンチアフィニティを使用すると、他のポッドのラベルに基づいてポッドを制約できます。
ノード アフィニティは概念的には nodeSelector
に似ており、ノードのラベルに基づいてポッドをスケジュールできるノードを制限できます。ノード アフィニティには 2 つのタイプがあります。
requiredDuringSchedulingIgnoredDuringExecution
: スケジューラは、ルールが満たされている場合にのみスケジューリングを実行できます。この機能はnodeSelector
に似ていますが、より表現力豊かな構文を持ちます。preferredDuringSchedulingIgnoredDuringExecution
: スケジューラは、対応するルールを満たすノードの検索を試みます。一致するノードが見つからない場合でも、スケジューラーはポッドをスケジュールします。
注:
上記のタイプでは、IgnoredDuringExecution は、Kubernetes がポッドをスケジュールした後にノード ラベルが変更された場合でも、ポッドは実行を継続することを意味します。
3. ノードアフィニティの使用
公式ドキュメントのデモをご覧ください。pods/pod-with-node-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity: # 定义亲和性规则
nodeAffinity: # 定义节点亲和性规则
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms: # 定义选择节点的条件
- matchExpressions: # 定义匹配表达式
- key: topology.kubernetes.io/zone # 指定匹配的标签键
operator: In # 指定匹配操作符为In,表示节点的标签键值在指定的values中
values: # 指定匹配的标签值列表,包括"antarctica-east1"和"antarctica-west1"
- antarctica-east1
- antarctica-west1
preferredDuringSchedulingIgnoredDuringExecution: # 定义优选的节点亲和性规则,即首选但不是必需的
- weight: 1 # 定义优选规则的权重为1
preference:
matchExpressions: # 定义首选规则的匹配表达式
- key: another-node-label-key # 指定匹配的标签键
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: registry.k8s.io/pause:2.0
適用されるルールは次のとおりです。
- ノードには、キー名
topology.kubernetes.io/zone
のラベルが含まれている必要があり、ラベルの値はantarctica-east1
またはantarctica-west1
- ノードは、キー名
another-node-label-key
と値another-node-label-value
を持つラベルを持つことが好ましい。
operator
フィールドを使用して、ルールを解釈するときに使用する Kubernetes
の論理演算子を設定できます。 In
、NotIn
、Exists
、DoesNotExist
、 がオペレーターとして使用されます。 Gt
Lt
In
: 1 つだけ満たしてください。NotIn
: どれも満たせない、反親和性。Exists
:それが存在する限り、それは満たされます。DoesNotExist
: 存在しないだけで十分です。Gt
: 満たされるには、ノードの値より大きくなければなりません。Lt
: 満たされるには、ノード上の値より小さい必要があります。
では、Pod
が特定のラベルを持つノードにスケジュールされる必要があります (トポロジ ドメインは「antarctica-east1
」または「」です) > antarctica-west1
")。同時に、 首选规则
も定義されており、 Pod
が 特定标签
を持つノードにスケジュールされることが期待されます。 (ラベルキーは「another-node-label-key
」、タグ値は「another-node-label-value
」です)。
この構成ではKubernetes
、スケジューラは必要なノード アフィニティ ルールを満たすノードに優先順位を与えます。それを満たすノードがない場合は、優先されるノード アフィニティ ルールが考慮されます。 . .
NotIn
と DoesNotExist
を使用して、ノードの反アフィニティ動作を実装できます。ノード テイントを使用して、 Pod
を特定のノードから削除することもできます。
注:
nodeSelector
とnodeAffinity
を同時に指定する場合は、ポッドの前に両方の条件を満たす必要があります。候補ノードにスケジュールされます。
nodeAffinity
タイプに関連付けられたnodeSelectorTerms
で複数の条件を指定した場合、そのうちの 1 つだけが指定されます。nodeSelectorTerms
それが満たされる場合 (各条件は論理 OR 演算によって結合されます)、Pod をノードにスケジュールできます。
nodeSelectorTerms
の条件に関連付けられた 1 つのmatchExpressions
フィールドに複数の式を指定すると、すべての式が指定された場合のみ条件が満たされると (各式は論理 AND 演算で結合されます)、Pod をノードにスケジュールできます。
4. ノード アフィニティの重み
フィールドは、preferredDuringSchedulingIgnoredDuringExecution
アフィニティ タイプのインスタンスごとに、 から。スケジューラが の他のスケジューリング リクエストを満たすことができるノードを見つけると、スケジューラはそのノードによって満たされるすべての優先ルールを調べ、対応する式の を追加します。値は合計されます。 weight
1
100
Pod
weight
最終的な合計値は、ノードの他の優先関数のスコアに追加されます。スケジューラが Pod
のスケジューリングを決定すると、 总分最高
のノードも 优先级
が最も高くなります。
設定ファイル: pods/pod-with-affinity-anti-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: with-affinity-anti-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: label-1
operator: In
values:
- key-1
- weight: 50
preference:
matchExpressions:
- key: label-2
operator: In
values:
- key-2
containers:
- name: with-node-affinity
image: registry.k8s.io/pause:2.0
候補ノードが 2 つあり、両方とも preferredDuringSchedulingIgnoredDuringExecution
ルールを満たす場合、一方のノードにはラベル label-1:key-1
が付けられ、もう一方のノードにはラベル < a i=3>、スケジューラは各ノードの 値を調べ、重み値をノードの他のスコア値に追加します。label-2:key-2
weight
注:
この例でKubernetes
がPod
を正常にスケジュールするには、次のノードが必要です。kubernetes.io/os=linux
ラベル。
5. ノードのアフィニティを確認する
現在の k8s 環境ノードのラベルを見てください。
[root@docker-54 ~]# kubectl get no --show-labels
NAME STATUS ROLES AGE VERSION LABELS
docker-54 Ready control-plane,master 201d v1.22.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-54,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
docker-55 Ready <none> 201d v1.22.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-55,kubernetes.io/os=linux,type=microservice
docker-56 Ready <none> 201d v1.22.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-56,kubernetes.io/os=linux,type=microservice
[root@docker-54 ~]#
上記のノードにはすでにラベルが付いていることがわかりますkubernetes.io/os=linux
。
上記のノード アフィニティ構成を確認するために、2 つのスレーブ ノードにそれぞれラベルを追加します。
[root@docker-54 ~]# kubectl label no docker-55 label-1=key-1
node/docker-55 labeled
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl label no docker-56 label-2=key-2
node/docker-56 labeled
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl get no --show-labels
NAME STATUS ROLES AGE VERSION LABELS
docker-54 Ready control-plane,master 202d v1.22.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-54,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=
docker-55 Ready <none> 201d v1.22.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-55,kubernetes.io/os=linux,label-1=key-1,type=microservice
docker-56 Ready <none> 201d v1.22.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-56,kubernetes.io/os=linux,label-2=key-2,type=microservice
[root@docker-54 ~]#
上では、docker-55
ノードlabel-1=key-1
にラベルを追加し、docker-56
ノード にラベルを追加しました。 label-2=key-2
。
ここでは、上記の構成ファイルのアフィニティ コンテンツを直接使用して、現在の環境のデプロイを変更し、デプロイを直接編集します。kubectl edit deploy nginx-deploy
template:
metadata:
labels:
app: nginx-deploy
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: label-1
operator: In
values:
- key-1
- weight: 50
preference:
matchExpressions:
- key: label-2
operator: In
values:
- key-2
ここでのアフィニティ設定も containers
と同じレベルであることに注意してください。
保存後、ポッドのスケジュールを確認してください。
[root@docker-54 ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-b8976d7b5-b86q4 1/1 Terminating 0 55m 10.244.1.78 docker-55 <none> <none>
nginx-deploy-b8976d7b5-fvqn8 1/1 Terminating 1 (55m ago) 115m 10.244.2.119 docker-56 <none> <none>
nginx-deploy-c7f9688fd-mqfmf 1/1 Running 0 27s 10.244.2.123 docker-56 <none> <none>
nginx-deploy-c7f9688fd-w6vhk 1/1 Running 0 29s 10.244.2.122 docker-56 <none> <none>
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-c7f9688fd-mqfmf 1/1 Running 0 54s 10.244.2.123 docker-56 <none> <none>
nginx-deploy-c7f9688fd-w6vhk 1/1 Running 0 56s 10.244.2.122 docker-56 <none> <none>
[root@docker-54 ~]#
2 つの Pod は元々 2 つのスレーブ ノードに分散されており、上記のアフィニティ構成を追加した後、Pod は docker-56 ノードにスケジュールされたことがわかります。
上記のノード アフィニティ設定を見てください。両方のスレーブ ノードが最初の要件を満たしており、ラベルkubernetes.io/os=linux
が付いていますが、ラベルlabel-2=key-2
が付いています。ノードの重みは次のとおりです。高いため、ポッドはこの特定のラベルを持つノードに最初にスケジュールされます。
その後、再度アフィニティ設定を変更し、タグlabel-2=key-2
の判定条件をIn
からNotIn
に変更します。推測してみましょう。現時点では、どちらの Pod も label-2=key-2
というラベルが付いたノードにスケジュールすることはできません。
それをチェックしてください:
[root@docker-54 ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-75578bc7f7-47cqt 0/1 ContainerCreating 0 2s <none> docker-55 <none> <none>
nginx-deploy-75578bc7f7-78j75 1/1 Running 0 4s 10.244.1.79 docker-55 <none> <none>
nginx-deploy-c7f9688fd-mqfmf 1/1 Running 0 7m52s 10.244.2.123 docker-56 <none> <none>
nginx-deploy-c7f9688fd-w6vhk 1/1 Terminating 0 7m54s 10.244.2.122 docker-56 <none> <none>
[root@docker-54 ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-75578bc7f7-47cqt 1/1 Running 0 4s 10.244.1.80 docker-55 <none> <none>
nginx-deploy-75578bc7f7-78j75 1/1 Running 0 6s 10.244.1.79 docker-55 <none> <none>
nginx-deploy-c7f9688fd-mqfmf 1/1 Terminating 0 7m54s 10.244.2.123 docker-56 <none> <none>
nginx-deploy-c7f9688fd-w6vhk 1/1 Terminating 0 7m56s 10.244.2.122 docker-56 <none> <none>
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl get po -o wide
nginx-deploy-75578bc7f7-47cqt 1/1 Running 0 52s 10.244.1.80 docker-55 <none> <none>
nginx-deploy-75578bc7f7-78j75 1/1 Running 0 56s 10.244.1.79 docker-55 <none> <none>
上記のアフィニティ設定が実際に一貫していることがわかります。
ここのマスター ノード docker-54 は、ラベルkubernetes.io/os=linux
と一致しますが、マスター ノードが汚染されているため、スケジュールされません。
[root@docker-54 ~]# kubectl describe no docker-54 |grep Taints
Taints: node-role.kubernetes.io/master:NoSchedule
[root@docker-54 ~]#
このステインが削除されても、上記の Pod は依然としてマスター ノードにスケジュールされている可能性があります。次に試してみましょう。
[root@docker-54 ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-75578bc7f7-47cqt 1/1 Running 0 52s 10.244.1.80 docker-55 <none> <none>
nginx-deploy-75578bc7f7-78j75 1/1 Running 0 54s 10.244.1.79 docker-55 <none> <none>
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl taint no docker-54 node-role.kubernetes.io/master:NoSchedule-
node/docker-54 untainted
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl describe no docker-54 |grep Taints
Taints: <none>
[root@docker-54 ~]#
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl delete po nginx-deploy-75578bc7f7-47cqt nginx-deploy-75578bc7f7-78j75
pod "nginx-deploy-75578bc7f7-47cqt" deleted
pod "nginx-deploy-75578bc7f7-78j75" deleted
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-75578bc7f7-8zz8h 1/1 Running 0 33s 10.244.0.11 docker-54 <none> <none>
nginx-deploy-75578bc7f7-xvnfm 1/1 Running 0 33s 10.244.1.81 docker-55 <none> <none>
[root@docker-54 ~]#
Master ノードからテイントが削除された後、Pod が削除されて再スケジュールされ、Master ノードにスケジュールできることがわかります。
Master ノード上のテイントが削除されていない場合、Pod にトレランスが設定されていないため、アフィニティ ラベルがあっても Master ノードにスケジュールされませんが、Master ノード上のテイントが削除された後は、必要なアフィニティ label を満たしているため、スケジュールによって選択される可能性があります。
6. ポッド間のアフィニティとアンチアフィニティ
ポッド間のアフィニティと反アフィニティを使用すると、ノード上のラベルではなく、ノード上ですでに実行されているポッドのラベルに基づいて、ポッドをスケジュールできるノードを制限できます。
Pod 間のアフィニティおよび反アフィニティ ルールの形式は、「ルール Y を満たす 1 つ以上の Pod がすでに X 上で実行されている場合、この Pod は X 上で実行される必要があります (または、反アフィニティの場合は実行すべきではありません)」です。 。ここで、X はノード、ラック、クラウド プロバイダーの可用性ゾーン、地理的エリア、または同様のトポロジー ドメインにすることができ、Y は Kubernetes が満たそうとしているルールです。
ルール (Y) をラベル セレクターの形式で表現し、オプションで関連する名前空間のリストを指定します。 の Pod
は名前空間スコープのオブジェクトであるため、 の も暗黙的です。公式にはがあります。 Pod タグのすべてのタグ セレクターはネームスペースを指定する必要があり、 は指定されたネームスペース内のタグを検索します。 Kubernetes
Pod
标签
名字空间属性
Kubernetes
topologyKey
を通じてトポロジ ドメイン (X) の概念を表現します。その値は、システムがドメインを識別するために使用するノード ラベル キーです。関連する例は、「共通のタグ、注釈、およびテイント」にあります。
注:
ポッド間のアフィニティと反アフィニティにはかなりの量の計算が必要であり、大規模クラスタではスケジューリング速度が大幅に低下します。数百のノードを持つクラスターでこのタイプのセットアップを使用することはお勧めしません。
注:
ポッドのアンチアフィニティには、ノード上で一貫したラベルが必要です。つまり、クラスタ内のすべてのノードにはtopologyKey
に一致するラベルが必要です。指定されたtopologyKey
タグが一部またはすべてのノードに存在しない場合、スケジュール動作が予期したものと異なる可能性があります。
7. ポッド間のアフィニティとアンチアフィニティの種類
ノード アフィニティと同様に、Pod アフィニティとアンチアフィニティには 2 種類があります。
- 必須スケジュール中無視実行中
- 優先中スケジュール中無視実行中
requiredDuringSchedulingIgnoredDuringExecution
アフィニティを使用すると、2 つのサービスのポッドは相互に頻繁に通信するため、それらのポッドを同じクラウド プロバイダー アベイラビリティ ゾーンに配置するようにスケジューラに指示できます。
同様に、preferredDuringSchedulingIgnoredDuringExecution
アンチアフィニティを使用して、同じサービスの複数のポッドを複数のクラウド プロバイダー アベイラビリティ ゾーンに分散できます。
ポッド間のアフィニティを使用するには、ポッド仕様の.affinity.podAffinity
フィールドを使用します。ポッド間のアンチアフィニティの場合、ポッド仕様の .affinity.podAntiAffinity
フィールドを使用できます。
8. ポッド間のアフィニティを使用して一連のポッドをスケジュールする
現在スケジュールされているポッドが自己アフィニティを持つ一連のポッドの最初である場合、他のすべてのアフィニティ ルールを満たしている限り、正常にスケジュールできます。これは、クラスター内の他の Pod がこの Pod の名前空間およびラベル セレクターと一致しないこと、Pod が独自に定義された条件を満たしていること、および選択されたノードが指定されたすべてのトポロジー要件を満たしていることを確認することによって決定されます。これにより、すべての Pod が Pod 間アフィニティで構成されている場合でも、スケジュールのデッドロックが発生しないことが保証されます。
ポッド アフィニティの例
次のポッド仕様を考えてみましょう: pods/pod-with-pod-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity: # 定义亲和性规则
podAffinity: # 定义Pod亲和性规则
requiredDuringSchedulingIgnoredDuringExecution: # 定义在调度时必须满足的Pod亲和性规则
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: topology.kubernetes.io/zone # 指定拓扑域的标签键 也就是 依赖的 Pod 所在的节点必须要有这个标签才行
podAntiAffinity: # 定义Pod反亲和性规则
preferredDuringSchedulingIgnoredDuringExecution: # 定义优选的Pod反亲和性规则,即首选但不是必需的
- weight: 100 # 定义优选规则的权重为100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: topology.kubernetes.io/zone
containers:
- name: with-pod-affinity
image: registry.k8s.io/pause:2.0
上の例では、ポッド 亲和性
ルールとポッド 反亲和性
ルールを定義しています。ポッド アフィニティ ルールは requiredDuringSchedulingIgnoredDuringExecution
として設定され、ポッドのアンチアフィニティは preferredDuringSchedulingIgnoredDuringExecution
として設定されます。
アフィニティ ルールは、ノードが特定のリージョンに属し、リージョン内の他の Pod が security=S1
でタグ付けされている場合にのみ、スケジューラがサンプル Pod をこのノードにスケジュールできることを規定します。たとえば、ラベル topology.kubernetes.io/zone=V
を持つノードで構成される指定されたゾーン (「ゾーン V」と呼びます) を持つクラスターがある場合、ゾーン V がすでに のタグが付けられており、スケジューラはこのポッドをゾーン V の にスケジュールできます。逆に、ゾーン V にラベル を持つポッドがない場合、スケジューラはサンプル ポッドをそのゾーンの にスケジュールしません。 至少有一个
security=S1
任何节点
security=S1
任何节点
アンチアフィニティ ルールでは、ノードが特定のゾーンに属し、そのゾーン内の他の Pod が security=S2
でタグ付けされている場合、スケジューラは、このゾーンに Pod をスケジュールすることを回避する必要があると規定しています。ノード上位。たとえば、指定されたゾーン (「ゾーン R」と呼びます) を持つクラスターがある場合、ゾーン R がすでに topology.kubernetes.io/zone=R
というラベルが付いたノードで構成されます。 > タグを持つポッドがない場合、反アフィニティ ルールはポッドをゾーン R にスケジュールすることに影響しません。 。スケジューラはゾーン R 内のノードにポッドを割り当てないようにする必要があります。逆に、ゾーン R に 至少有一个
ポッドにはタグが付けられていますsecurity=S2
security=S2
この構成ではKubernetes
、スケジューラは必要なポッド アフィニティ ルールを満たすことを優先します。それを満たすノードがない場合は、優先されるポッドの非アフィニティ ルールが考慮されます。
は、Pod 間アフィニティおよびアンチアフィニティの operator
フィールドに In
、 NotIn
を使用できます。< /span> など。 Exists
、DoesNotExist
原則として、topologyKey
には任意の正当なタグ キーを使用できます。パフォーマンスとセキュリティ上の理由から、topologyKey
にはいくつかの制限があります。
ポッド 亲和性
の場合、requiredDuringSchedulingIgnoredDuringExecution
および preferredDuringSchedulingIgnoredDuringExecution
では、topologyKey
空ではありません許可された。
requiredDuringSchedulingIgnoredDuringExecution
で必要なポッドのアンチアフィニティの場合、アドミッション コントローラ LimitPodHardAntiAffinityTopology
には topologyKey
のみが必要ですkubernetes.io/hostname
。他のカスタム トポロジ ロジックを使用する場合は、アドミッション コントローラーを変更するか、無効にすることができます。
labelSelector
と topologyKey
に加えて、 labelSelector
名前空間のリストを指定することもできます。 match、 を labelSelector
と topologyKey
と同じレベルに設定する方法です。 が省略されるか空の場合、ポッド アフィニティ/アンチアフィニティが定義されている名前空間がデフォルトで使用されます。 namespaces
namespaces
9. ポッドのアフィニティを確認する
上記の設定ファイルに従って、ここではまずマスター ノードに topology.kubernetes.io/zone=R
のラベルを付け、スレーブ ノードに topology.kubernetes.io/zone=V
のラベルを付けます。
[root@docker-54 ~]# kubectl label no docker-54 topology.kubernetes.io/zone=R
node/docker-54 labeled
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl label no docker-55 docker-56 topology.kubernetes.io/zone=V
node/docker-55 labeled
node/docker-56 labeled
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl get no --show-labels
NAME STATUS ROLES AGE VERSION LABELS
docker-54 Ready control-plane,master 202d v1.22.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-54,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=,node.kubernetes.io/exclude-from-external-load-balancers=,topology.kubernetes.io/zone=R
docker-55 Ready <none> 202d v1.22.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,ingress=true,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-55,kubernetes.io/os=linux,label-1=key-1,topology.kubernetes.io/zone=V,type=microservice
docker-56 Ready <none> 202d v1.22.6 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=docker-56,kubernetes.io/os=linux,label-2=key-2,topology.kubernetes.io/zone=V,type=microservice
[root@docker-54 ~]#
次に、s2 タグの新しい構成ファイルを作成します。s2-nginx-deploy-affinity.yaml
apiVersion: apps/v1 # deployment api 版本
kind: Deployment # 资源类型为 deployment
metadata: # 元信息
labels: # 标签
app: nginx-deploy # 具体的 key: value 配置形式
name: nginx-deploy-s2 # deployment 的名字
namespace: default # 所在的命名空间
spec:
replicas: 1 # 期望副本数
revisionHistoryLimit: 10 # 进行滚动更新后,保留的历史版本数
selector: # 选择器,用于找到匹配的 RS
matchLabels: # 按照标签匹配
app: nginx-deploy # 匹配的标签key/value
strategy: # 更新策略
rollingUpdate: # 滚动更新配置
maxSurge: 25% # 进行滚动更新时,更新的个数最多可以超过期望副本数的个数/比例
maxUnavailable: 25% # 进行滚动更新时,最大不可用比例更新比例,表示在所有副本数中,最多可以有多少个不更新成功
type: RollingUpdate # 更新类型,采用滚动更新
template: # pod 模板
metadata: # pod 的元信息
labels: # pod 的标签
app: nginx-deploy
topology.kubernetes.io/zone: V
security: S2
spec: # pod 期望信息
nodeSelector:
kubernetes.io/hostname: docker-54
containers: # pod 的容器
- image: nginx:1.7.9 # 镜像
imagePullPolicy: IfNotPresent # 拉取策略
name: nginx # 容器名称
resources:
limits:
cpu: 200m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
restartPolicy: Always # 重启策略
terminationGracePeriodSeconds: 30 # 删除操作最多宽限多长时间
上記の構成は、ラベル セレクターを使用して Nginx ポッドを docker-54 ノードにデプロイすることを意味します。このポッドには、後でポッド アフィニティをテストするために使用される 2 つのラベルがあります。 。 topology.kubernetes.io/zone: V
と security: S2
これを直接作成しますdeployment
見てください。ノード セレクターを使用して Master
ノードに直接ディスパッチします。成功しないはずです。ここではまだ処理されていません。マスター ノードの汚れ、効果を見てください:
[root@docker-54 deployments]# kubectl create -f s2-nginx-deploy-affinity.yaml
deployment.apps/nginx-deploy-s2 created
[root@docker-54 deployments]#
[root@docker-54 ~]# kubectl get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-75578bc7f7-8zz8h 1/1 Running 11 (46m ago) 11h 10.244.0.11 docker-54 <none> <none>
nginx-deploy-75578bc7f7-xvnfm 1/1 Running 11 (46m ago) 11h 10.244.1.81 docker-55 <none> <none>
nginx-deploy-s2-5fd5bf9d5c-52d2k 0/1 Pending 0 19s <none> <none> <none> <none>
[root@docker-54 ~]#
[root@docker-54 deployments]# kubectl get po -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
nginx-deploy-75578bc7f7-8zz8h 1/1 Running 11 (50m ago) 11h 10.244.0.11 docker-54 <none> <none> app=nginx-deploy,pod-template-hash=75578bc7f7
nginx-deploy-75578bc7f7-xvnfm 1/1 Running 11 (50m ago) 11h 10.244.1.81 docker-55 <none> <none> app=nginx-deploy,pod-template-hash=75578bc7f7
nginx-deploy-s2-5fd5bf9d5c-52d2k 0/1 Pending 0 5m2s <none> <none> <none> <none> app=nginx-deploy,pod-template-hash=5fd5bf9d5c,security=S2,topology.kubernetes.io/zone=V
[root@docker-54 deployments]#
ポッドのステータスが保留中であることがわかり、次のイベントを確認します。
[root@docker-54 ~]# kubectl describe po nginx-deploy-s2-5fd5bf9d5c-52d2k
Name: nginx-deploy-s2-5fd5bf9d5c-52d2k
Namespace: default
// 省略中间内容
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 31s default-scheduler 0/3 nodes are available: 1 node(s) had taint {
node-role.kubernetes.io/master: }, that the pod didn't tolerate, 2 node(s) didn't match Pod's node affinity/selector.
[root@docker-54 ~]#
ご覧のとおり、上記は 3 つのノードのデフォルトのスケジュールを示していますが、どれも利用できず、ノードの 1 つが汚染されています{node-role.kubernetes.io/master: }
。また、このポッドには許容値が設定されていません上記では、他の 2 つのノードにはポッドのノード アフィニティ ラベルが含まれていません。
次に、マスター ノードの汚染を一時的に削除し、Pod がマスター ノードに正常にスケジュールできるかどうかを確認してみましょう。
[root@docker-54 ~]# kubectl describe no docker-54 | grep Taint
Taints: node-role.kubernetes.io/master:NoSchedule
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl taint no docker-54 node-role.kubernetes.io/master:NoSchedule-
node/docker-54 untainted
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl describe no docker-54 | grep Taint
Taints: <none>
[root@docker-54 ~]#
次に、ポッドのステータスを再度確認します。
[root@docker-54 deployments]# kubectl get po -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
nginx-deploy-75578bc7f7-8zz8h 1/1 Running 11 (55m ago) 11h 10.244.0.11 docker-54 <none> <none> app=nginx-deploy,pod-template-hash=75578bc7f7
nginx-deploy-75578bc7f7-xvnfm 1/1 Running 11 (55m ago) 11h 10.244.1.81 docker-55 <none> <none> app=nginx-deploy,pod-template-hash=75578bc7f7
nginx-deploy-s2-5fd5bf9d5c-52d2k 1/1 Running 0 9m46s 10.244.0.12 docker-54 <none> <none> app=nginx-deploy,pod-template-hash=5fd5bf9d5c,security=S2,topology.kubernetes.io/zone=V
[root@docker-54 deployments]#
nginx-deploy-s2
のポッドが Maser ノードにスケジュールされていることがわかります。これが K8s のバグかどうかはわかりません。ノード docker-54
には topology.kubernetes.io/zone=R
というラベルが付いていますが、このポッドはこのノードにスケジュールできます。
次に、設定ファイル内の Pod テンプレートのラベル セレクタを topology.kubernetes.io/zone=R
に設定してみましたが、docker-54
ノードにスケジュールできることがわかりました。通常は。つまり、k8sがスケジュールされているときに、ラベルセレクターのみが構成されている場合、バグが発生します。つまり、ラベルのキーのみが比較され、ラベルの値は比較されません。これは使用されます。染色Exists
機能での判定用。これら 3 つのノードにはすべて topology.kubernetes.io/zone
タグが含まれていますが、値は異なります。
次に、新しいデプロイを作成し、S1 ラベルを使用してポッドを構成します。s1-nginx-deploy-affinity.yaml
apiVersion: apps/v1 # deployment api 版本
kind: Deployment # 资源类型为 deployment
metadata: # 元信息
labels: # 标签
app: nginx-deploy # 具体的 key: value 配置形式
name: nginx-deploy-s1 # deployment 的名字
namespace: default # 所在的命名空间
spec:
replicas: 2 # 期望副本数
revisionHistoryLimit: 10 # 进行滚动更新后,保留的历史版本数
selector: # 选择器,用于找到匹配的 RS
matchLabels: # 按照标签匹配
app: nginx-deploy # 匹配的标签key/value
strategy: # 更新策略
rollingUpdate: # 滚动更新配置
maxSurge: 25% # 进行滚动更新时,更新的个数最多可以超过期望副本数的个数/比例
maxUnavailable: 25% # 进行滚动更新时,最大不可用比例更新比例,表示在所有副本数中,最多可以有多少个不更新成功
type: RollingUpdate # 更新类型,采用滚动更新
template: # pod 模板
metadata: # pod 的元信息
labels: # pod 的标签
app: nginx-deploy
topology.kubernetes.io/zone: V
security: S1
spec: # pod 期望信息
containers: # pod 的容器
- image: nginx:1.7.9 # 镜像
imagePullPolicy: IfNotPresent # 拉取策略
name: nginx # 容器名称
resources:
limits:
cpu: 200m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
restartPolicy: Always # 重启策略
terminationGracePeriodSeconds: 30 # 删除操作最多宽限多长时间
この構成のポッドのラベルは topology.kubernetes.io/zone: V
と security: S1
であり、2 つのスレーブ ノードのラベルに対応していることがわかります。 2 つのスレーブ ノードにスケジュールされるかどうかを確認します。
[root@docker-54 deployments]# kubectl create -f s1-nginx-deploy-affinity.yaml
deployment.apps/nginx-deploy-s1 created
[root@docker-54 deployments]#
[root@docker-54 deployments]# kubectl get po -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
nginx-deploy-s1-7bbd9fbdb7-25627 1/1 Running 0 2s 10.244.0.19 docker-54 <none> <none> app=nginx-deploy,pod-template-hash=7bbd9fbdb7,security=S1,topology.kubernetes.io/zone=V
nginx-deploy-s1-7bbd9fbdb7-bqwm4 1/1 Running 0 2s 10.244.2.127 docker-56 <none> <none> app=nginx-deploy,pod-template-hash=7bbd9fbdb7,security=S1,topology.kubernetes.io/zone=V
nginx-deploy-s2-df8df55b9-f8cb6 1/1 Running 0 79s 10.244.0.18 docker-54 <none> <none> app=nginx-deploy,pod-template-hash=df8df55b9,security=S2,topology.kubernetes.io/zone=R
[root@docker-54 deployments]#
理想的には、s1 のデプロイの 2 つのポッドは topology.kubernetes.io/zone=V
というラベルが付いた 2 つのスレーブ ノードにスケジュールされる必要があります。 ! !これは当てはまりません:
[root@docker-54 deployments]# kubectl get po -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
nginx-deploy-s1-7bbd9fbdb7-25627 1/1 Running 0 2s 10.244.0.19 docker-54 <none> <none> app=nginx-deploy,pod-template-hash=7bbd9fbdb7,security=S1,topology.kubernetes.io/zone=V
nginx-deploy-s1-7bbd9fbdb7-bqwm4 1/1 Running 0 2s 10.244.2.127 docker-56 <none> <none> app=nginx-deploy,pod-template-hash=7bbd9fbdb7,security=S1,topology.kubernetes.io/zone=V
nginx-deploy-s2-df8df55b9-f8cb6 1/1 Running 0 79s 10.244.0.18 docker-54 <none> <none> app=nginx-deploy,pod-template-hash=df8df55b9,security=S2,topology.kubernetes.io/zone=R
[root@docker-54 deployments]#
ノードの 1 つは、docker-55 ノードではなく docker-54 ノードに依存する必要があります。
また、docker-55 ノードにテイントが設定されているかどうかも具体的に確認しました。
[root@docker-54 ~]# kubectl describe no docker-55 | grep Taints
Taints: <none>
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl describe no docker-54 | grep Taints
Taints: <none>
[root@docker-54 ~]#
[root@docker-54 ~]# kubectl describe no docker-56 | grep Taints
Taints: <none>
[root@docker-54 ~]#
何度もデプロイを削除しましたが、同じ状態のままでプレイできなくなりました。 。 。 。 。 。 。
以上、スパイシーなタグセレクターでした。スケジューリングの制御のみに使用するのは非常に信頼性がありません。ステイン関数やアフィニティ関数があるのも不思議ではありません。期待に応えられないものです。 。 。 。 。