継続的統合デプロイメント - 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 の論理演算子を設定できます。 InNotInExistsDoesNotExist がオペレーターとして使用されます。 GtLt

  • In: 1 つだけ満たしてください。
  • NotIn: どれも満たせない、反親和性。
  • Exists:それが存在する限り、それは満たされます。
  • DoesNotExist: 存在しないだけで十分です。
  • Gt: 満たされるには、ノードの値より大きくなければなりません。
  • Lt: 満たされるには、ノード上の値より小さい必要があります。

では、Pod が特定のラベルを持つノードにスケジュールされる必要があります (トポロジ ドメインは「antarctica-east1」または「」です) > antarctica-west1")。同時に、 首选规则 も定義されており、 Pod特定标签 を持つノードにスケジュールされることが期待されます。 (ラベルキーは「another-node-label-key」、タグ値は「another-node-label-value」です)。

この構成ではKubernetes、スケジューラは必要なノード アフィニティ ルールを満たすノードに優先順位を与えます。それを満たすノードがない場合は、優先されるノード アフィニティ ルールが考慮されます。 . .

NotInDoesNotExist を使用して、ノードの反アフィニティ動作を実装できます。ノード テイントを使用して、 Pod を特定のノードから削除することもできます。

注:
nodeSelectornodeAffinity を同時に指定する場合は、ポッドの前に両方の条件を満たす必要があります。候補ノードにスケジュールされます。
nodeAffinity タイプに関連付けられた nodeSelectorTerms で複数の条件を指定した場合、そのうちの 1 つだけが指定されます。 nodeSelectorTerms それが満たされる場合 (各条件は論理 OR 演算によって結合されます)、Pod をノードにスケジュールできます。
nodeSelectorTerms の条件に関連付けられた 1 つの matchExpressions フィールドに複数の式を指定すると、すべての式が指定された場合のみ条件が満たされると (各式は論理 AND 演算で結合されます)、Pod をノードにスケジュールできます。

4. ノード アフィニティの重み

フィールドは、preferredDuringSchedulingIgnoredDuringExecution アフィニティ タイプのインスタンスごとに、 から。スケジューラが の他のスケジューリング リクエストを満たすことができるノードを見つけると、スケジューラはそのノードによって満たされるすべての優先ルールを調べ、対応する式の を追加します。値は合計されます。 weight1100Podweight

最終的な合計値は、ノードの他の優先関数のスコアに追加されます。スケジューラが 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-2weight

注:
この例で KubernetesPod を正常にスケジュールするには、次のノードが必要です。 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 タグのすべてのタグ セレクターはネームスペースを指定する必要があり、 は指定されたネームスペース内のタグを検索します。 KubernetesPod标签名字空间属性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=S2security=S2

この構成ではKubernetes、スケジューラは必要なポッド アフィニティ ルールを満たすことを優先します。それを満たすノードがない場合は、優先されるポッドの非アフィニティ ルールが考慮されます。

は、Pod 間アフィニティおよびアンチアフィニティの operator フィールドに InNotIn を使用できます。< /span> など。 ExistsDoesNotExist

原則として、topologyKey には任意の正当なタグ キーを使用できます。パフォーマンスとセキュリティ上の理由から、topologyKey にはいくつかの制限があります。

ポッド 亲和性 の場合、requiredDuringSchedulingIgnoredDuringExecution および preferredDuringSchedulingIgnoredDuringExecution では、topologyKey 空ではありません許可された。
requiredDuringSchedulingIgnoredDuringExecution で必要なポッドのアンチアフィニティの場合、アドミッション コントローラ LimitPodHardAntiAffinityTopology には topologyKey のみが必要ですkubernetes.io/hostname。他のカスタム トポロジ ロジックを使用する場合は、アドミッション コントローラーを変更するか、無効にすることができます。
labelSelectortopologyKey に加えて、 labelSelector 名前空間のリストを指定することもできます。 match、labelSelectortopologyKey と同じレベルに設定する方法です。 が省略されるか空の場合、ポッド アフィニティ/アンチアフィニティが定義されている名前空間がデフォルトで使用されます。 namespacesnamespaces

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: Vsecurity: 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: Vsecurity: 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 ~]# 

何度もデプロイを削除しましたが、同じ状態のままでプレイできなくなりました。 。 。 。 。 。 。

以上、スパイシーなタグセレクターでした。スケジューリングの制御のみに使用するのは非常に信頼性がありません。ステイン関数やアフィニティ関数があるのも不思議ではありません。期待に応えられないものです。 。 。 。 。

おすすめ

転載: blog.csdn.net/linmengmeng_1314/article/details/134758294