アフィニティおよび非アフィニティのスケジューリング

DaemonSetでは、nodeSelectorを使用して、ポッドによってデプロイされるノードを選択する方法について説明しました。実際、Kubernetesは、より洗練された柔軟なスケジューリングメカニズム、つまり、アフィニティおよび非アフィニティスケジューリングもサポートしています。

Kubernetesは、ノードとポッドの2つのレベルの親和性と反親和性をサポートします。アフィニティルールと非アフィニティルールを設定することで、フロントエンドポッドとバックエンドポッドを一緒にデプロイする、特定のタイプのアプリケーションを特定の特定のノードにデプロイする、異なるアプリケーションを異なるノードにデプロイするなど、厳しい制限や設定を指定できます。 。

ノードアフィニティ(ノードアフィニティ)

アフィニティルールの基本はラベルである必要があることを推測している必要があります。CCEクラスター内のノードのラベルを見てみましょう。

$ kubectl describe node 192.168.0.212
Name:               192.168.0.212
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    failure-domain.beta.kubernetes.io/is-baremetal=false
                    failure-domain.beta.kubernetes.io/region=cn-east-3
                    failure-domain.beta.kubernetes.io/zone=cn-east-3a
                    kubernetes.io/arch=amd64
                    kubernetes.io/availablezone=cn-east-3a
                    kubernetes.io/eniquota=12
                    kubernetes.io/hostname=192.168.0.212
                    kubernetes.io/os=linux
                    node.kubernetes.io/subnetid=fd43acad-33e7-48b2-a85a-24833f362e0e
                    os.architecture=amd64
                    os.name=EulerOS_2.0_SP5
                    os.version=3.10.0-862.14.1.5.h328.eulerosv2r7.x86_64

これらのラベルは、ノードの作成時にCCEによって自動的に追加されます。次に、スケジューリングでさらに使用されるいくつかのラベルを紹介します。

  • failure-domain.beta.kubernetes.io/region:ノードが配置されているリージョンを示します。上記のノードのラベル値がcn-east-3の場合、ノードが上海のリージョンにあることを意味します。
  • failure-domain.beta.kubernetes.io/zone:ノードが配置されているアベイラビリティーゾーン(アベイラビリティーゾーン)を示します。
  • kubernetes.io/hostname:ノードのホスト名。
    さらに、「ラベル:ポッドを整理する武器」では、カスタムラベルも導入されています。一般に、大規模なKubernetesクラスターの場合、多くのラベルはビジネスニーズに応じて確実に定義されます。

NodeSelectorはDaemonSetで導入され、Podは特定のラベルを持つノードにのみデプロイできます。以下に示すように、ポッドはラベルgpu = trueのノードにのみデプロイされます。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  nodeSelector:                 # 节点选择,当节点拥有gpu=true时才在节点上创建Pod
    gpu: true
...

以下に示すように、ノードアフィニティルールの構成でも同じことができます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name:  gpu
  labels:
    app:  gpu
spec:
  selector:
    matchLabels:
      app: gpu
  replicas: 3
  template:
    metadata:
      labels:
        app:  gpu
    spec:
      containers:
      - image:  nginx:alpine
        name:  gpu
        resources:
          requests:
            cpu: 100m
            memory: 200Mi
          limits:
            cpu: 100m
            memory: 200Mi
      imagePullSecrets:
      - name: default-secret
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: gpu
                operator: In
                values:
                - "true"

これはもっと複雑なようですが、この方法で表現力を高めることができます。これについては後で詳しく説明します。

ここで、アフィニティはアフィニティを意味し、nodeAffinityはノードアフィニティを意味し、requiredDuringSchedulingIgnoredDuringExecutionは非常に長いですが、これは2つの段落に分けることができます。

  • requiredDuringSchedulingの前半は、以下に定義されているルールを強制的に満たす必要があることを示しています(必須)。
  • IgnoredDuringExecutionの後半では、ノードですでに実行されているポッドには影響しないと述べています。現在のノードアフィニティルールはスケジュールされているポッドにのみ影響するため、Kubernetesによって提供される現在のルールはすべてIgnoredDuringExecutionで終わります。最終的にはkubernetesもサポートします。 RequiredDuringExecution、つまり、ノードのラベルを削除すると、ノードにラベルを含める必要があるポッドが削除されます。
  • さらに、演算子演算子の値はInであり、タグ値が値のリストに含まれている必要があることを示しています。他の演算子の値は次のとおりです。
  • NotIn:タグの値がリストにありません
  • 存在する:ラベルが存在する
  • DoesNotExist:ラベルが存在しません
  • Gt:タグの値が特定の値より大きい(文字列比較)
  • Lt:ラベルの値が特定の値(文字列の比較)未満です
    。NotInとDoesNotExistが同じ機能を提供できるため、nodeAntiAffinity(ノードの反親和性)がないことに注意しください。

このルールが有効かどうかを確認しましょう。まず、ノード192.168.0.212にgpu = trueのラベルを付けます。

$ kubectl label node 192.168.0.212 gpu=true
node/192.168.0.212 labeled

$ kubectl get node -L gpu
NAME            STATUS   ROLES    AGE   VERSION                            GPU
192.168.0.212   Ready    <none>   13m   v1.15.6-r1-20.3.0.2.B001-15.30.2   true
192.168.0.94    Ready    <none>   13m   v1.15.6-r1-20.3.0.2.B001-15.30.2   
192.168.0.97    Ready    <none>   13m   v1.15.6-r1-20.3.0.2.B001-15.30.2   

このデプロイメントを作成すると、すべてのポッドが192.168.0.212ノードにデプロイされていることがわかります。

$ kubectl create -f affinity.yaml 
deployment.apps/gpu created

$ kubectl get pod -owide
NAME                     READY   STATUS    RESTARTS   AGE   IP            NODE         
gpu-6df65c44cf-42xw4     1/1     Running   0          15s   172.16.0.37   192.168.0.212
gpu-6df65c44cf-jzjvs     1/1     Running   0          15s   172.16.0.36   192.168.0.212
gpu-6df65c44cf-zv5cl     1/1     Running   0          15s   172.16.0.38   192.168.0.212

ノード優先順位選択ルール

上記のrequiredDuringSchedulingIgnoredDuringExecutionは必須の選択ルールです。ノードアフィニティの優先選択ルール、つまり、preferredDuringSchedulingIgnoredDuringExecutionもあります。これは、ルールに従ってどのノードが優先的に選択されるかを示します。

この効果を示すには、最初に上記のクラスターにノードを追加しますが、このノードは他の3つのノードと同じアベイラビリティーゾーンにありません。作成後、以下に示すように、ノードのアベイラビリティーゾーンラベルをクエリします。新しく追加されたノードはcn-eastにあります。 -3cこの利用可能なゾーン。

$ kubectl get node -L failure-domain.beta.kubernetes.io/zone,gpu
NAME            STATUS   ROLES    AGE     VERSION                            ZONE         GPU
192.168.0.100   Ready    <none>   7h23m   v1.15.6-r1-20.3.0.2.B001-15.30.2   cn-east-3c   
192.168.0.212   Ready    <none>   8h      v1.15.6-r1-20.3.0.2.B001-15.30.2   cn-east-3a   true
192.168.0.94    Ready    <none>   8h      v1.15.6-r1-20.3.0.2.B001-15.30.2   cn-east-3a   
192.168.0.97    Ready    <none>   8h      v1.15.6-r1-20.3.0.2.B001-15.30.2   cn-east-3a  

以下は、最初にアベイラビリティーゾーンcn-east-3aのノードにポッドをデプロイする必要があるデプロイメントを定義します。preferredDuringSchedulingIgnoredDuringExecutionルールを使用して、cn-east-3aの重みを80に設定し、gpu = trueweightを設定して次のように定義できます。 20なので、ポッドは最初にcn-east-3aノードにデプロイされます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name:  gpu
  labels:
    app:  gpu
spec:
  selector:
    matchLabels:
      app: gpu
  replicas: 10
  template:
    metadata:
      labels:
        app:  gpu
    spec:
      containers:
      - image:  nginx:alpine
        name:  gpu
        resources:
          requests:
            cpu:  100m
            memory:  200Mi
          limits:
            cpu:  100m
            memory:  200Mi
      imagePullSecrets:
      - name: default-secret
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 80 
            preference: 
              matchExpressions: 
              - key: failure-domain.beta.kubernetes.io/zone
                operator: In 
                values: 
                - cn-east-3a
          - weight: 20 
            preference: 
              matchExpressions: 
              - key: gpu
                operator: In 
                values: 
                - "true"

実際の展開状況を見ると、192.168.0.212ノードには5つのポッドが展開されていますが、192.168.0.100には2つしかないことがわかります。

$ kubectl create -f affinity2.yaml 
deployment.apps/gpu created

$ kubectl get po -o wide
NAME                   READY   STATUS    RESTARTS   AGE     IP            NODE         
gpu-585455d466-5bmcz   1/1     Running   0          2m29s   172.16.0.44   192.168.0.212
gpu-585455d466-cg2l6   1/1     Running   0          2m29s   172.16.0.63   192.168.0.97 
gpu-585455d466-f2bt2   1/1     Running   0          2m29s   172.16.0.79   192.168.0.100
gpu-585455d466-hdb5n   1/1     Running   0          2m29s   172.16.0.42   192.168.0.212
gpu-585455d466-hkgvz   1/1     Running   0          2m29s   172.16.0.43   192.168.0.212
gpu-585455d466-mngvn   1/1     Running   0          2m29s   172.16.0.48   192.168.0.97 
gpu-585455d466-s26qs   1/1     Running   0          2m29s   172.16.0.62   192.168.0.97 
gpu-585455d466-sxtzm   1/1     Running   0          2m29s   172.16.0.45   192.168.0.212
gpu-585455d466-t56cm   1/1     Running   0          2m29s   172.16.0.64   192.168.0.100
gpu-585455d466-t5w5x   1/1     Running   0          2m29s   172.16.0.41   192.168.0.212

上記の例では、ノードの並べ替えの優先度は次のとおりです。2つのラベルを持つノードが最も高くランク付けされ、cn-east-3aラベルを持つノードのみが2番目にランク付けされ(重み80)、gpu = trueを持つノードのみが最初にランク付けされます。第三に、最低ランクを持たないノード。

図1優先順位

アフィニティおよび非アフィニティのスケジューリング

ここでは、ポッドが192.168.0.94ノードにスケジュールされていないことがわかります。これは、このノードに他の多くのポッドがデプロイされており、より多くのリソースを使用しているため、このノードではスケジュールされていないことを示しています。これは、preferredDuringSchedulingIgnoredDuringExecutionが優先ルールであることも示しています。 、必須のルールではありません。

ポッドアフィニティ(ポッドアフィニティ)

ノードアフィニティのルールは、ポッドとノード間のアフィニティにのみ影響します。Kubernetesは、アプリケーションのフロントエンドとバックエンドを一緒にデプロイしてアクセスの待ち時間を短縮するなど、ポッドとポッド間のアフィニティもサポートします。ポッドアフィニティには、requiredDuringSchedulingIgnoredDuringExecutionとpreferredDuringSchedulingIgnoredDuringExecutionの2つのルールもあります。

次の例を見てみましょう。アプリケーションバックエンドが作成され、app = backendというタグが付いていると仮定します。

$ kubectl get po -o wide
NAME                       READY   STATUS    RESTARTS   AGE     IP            NODE         
backend-658f6cb858-dlrz8   1/1     Running   0          2m36s   172.16.0.67   192.168.0.100

フロントエンドポッドをバックエンドと一緒にデプロイする場合、次のポッドアフィニティルール設定を行うことができます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name:   frontend
  labels:
    app:  frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 3
  template:
    metadata:
      labels:
        app:  frontend
    spec:
      containers:
      - image:  nginx:alpine
        name:  frontend
        resources:
          requests:
            cpu:  100m
            memory:  200Mi
          limits:
            cpu:  100m
            memory:  200Mi
      imagePullSecrets:
      - name: default-secret
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - topologyKey: kubernetes.io/hostname
            labelSelector:
              matchLabels:
                app: backend

フロントエンドを作成して表示すると、フロントエンドがバックエンドと同じノードに作成されていることがわかります。

$ kubectl create -f affinity3.yaml 
deployment.apps/frontend created

$ kubectl get po -o wide
NAME                        READY   STATUS    RESTARTS   AGE     IP            NODE         
backend-658f6cb858-dlrz8    1/1     Running   0          5m38s   172.16.0.67   192.168.0.100
frontend-67ff9b7b97-dsqzn   1/1     Running   0          6s      172.16.0.70   192.168.0.100
frontend-67ff9b7b97-hxm5t   1/1     Running   0          6s      172.16.0.71   192.168.0.100
frontend-67ff9b7b97-z8pdb   1/1     Running   0          6s      172.16.0.72   192.168.0.100

topologyKeyフィールドがあります。これは、最初にtopologyKeyで指定された範囲を区切り、次に次のルールで定義されたコンテンツを選択することを意味します。ここの各ノードにはkubernetes.io/hostnameがあるため、topologyKeyの役割は表示されません。

バックエンドに2つのポッドがある場合、それらは異なるノード上にあります。

$ kubectl get po -o wide
NAME                       READY   STATUS    RESTARTS   AGE     IP            NODE         
backend-658f6cb858-5bpd6   1/1     Running   0          23m     172.16.0.40   192.168.0.97
backend-658f6cb858-dlrz8   1/1     Running   0          2m36s   172.16.0.67   192.168.0.100

192.168.0.97と192.168.0.94にperfer = trueのタグを付けます。

$ kubectl label node 192.168.0.97 perfer=true
node/192.168.0.97 labeled
$ kubectl label node 192.168.0.94 perfer=true
node/192.168.0.94 labeled

$ kubectl get node -L perfer
NAME            STATUS   ROLES    AGE   VERSION                            PERFER
192.168.0.100   Ready    <none>   44m   v1.15.6-r1-20.3.0.2.B001-15.30.2   
192.168.0.212   Ready    <none>   91m   v1.15.6-r1-20.3.0.2.B001-15.30.2   
192.168.0.94    Ready    <none>   91m   v1.15.6-r1-20.3.0.2.B001-15.30.2   true
192.168.0.97    Ready    <none>   91m   v1.15.6-r1-20.3.0.2.B001-15.30.2   true

podAffinityのtopologyKeyをperferとして定義します。

        affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - topologyKey: perfer
            labelSelector:
              matchLabels:
                app: backend

スケジュールを設定するときは、最初にperferラベル(ここでは192.168.0.97と192.168.0.94)でノードを丸で囲み、次にポッドをapp = backendラベルと一致させて、すべてのフロントエンドが192.168.0.97にデプロイされるようにします。

$ kubectl create -f affinity3.yaml 
deployment.apps/frontend created

$ kubectl get po -o wide
NAME                        READY   STATUS    RESTARTS   AGE     IP            NODE         
backend-658f6cb858-5bpd6    1/1     Running   0          26m     172.16.0.40   192.168.0.97
backend-658f6cb858-dlrz8    1/1     Running   0          5m38s   172.16.0.67   192.168.0.100
frontend-67ff9b7b97-dsqzn   1/1     Running   0          6s      172.16.0.70   192.168.0.97
frontend-67ff9b7b97-hxm5t   1/1     Running   0          6s      172.16.0.71   192.168.0.97
frontend-67ff9b7b97-z8pdb   1/1     Running   0          6s      172.16.0.72   192.168.0.97

ポッドアンチアフィニティ(ポッドアンチアフィニティ)

ポッドのアフィニティについて説明しました。ポッドはアフィニティを介して一緒にデプロイされます。要件が正反対の場合もあります。ポッドは個別にデプロイする必要があります。たとえば、ポッドを一緒にデプロイするとパフォーマンスに影響します。

次の例では、非アフィニティルールを定義します。このルールは、app = frontendラベルPodのノードにポッドをスケジュールできないこと、つまり、フロントエンドが異なるノードにスケジュールされることを示します(各ノードにはポッドが1つだけあります)。

apiVersion: apps/v1
kind: Deployment
metadata:
  name:   frontend
  labels:
    app:  frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 5
  template:
    metadata:
      labels:
        app:  frontend
    spec:
      containers:
      - image:  nginx:alpine
        name:  frontend
        resources:
          requests:
            cpu:  100m
            memory:  200Mi
          limits:
            cpu:  100m
            memory:  200Mi
      imagePullSecrets:
      - name: default-secret
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - topologyKey: kubernetes.io/hostname
            labelSelector:
              matchLabels:
                app: frontend

作成して表示すると、各ノードにフロントエンドポッドが1つだけあり、もう1つが保留中であることがわかります。これは、5番目がデプロイされると、4つのノードにapp = frontendポッドがあるため、5番目は常に保留中です。 。

$ kubectl create -f affinity4.yaml 
deployment.apps/frontend created

$ kubectl get po -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP            NODE         
frontend-6f686d8d87-8dlsc   1/1     Running   0          18s   172.16.0.76   192.168.0.100
frontend-6f686d8d87-d6l8p   0/1     Pending   0          18s   <none>        <none>       
frontend-6f686d8d87-hgcq2   1/1     Running   0          18s   172.16.0.54   192.168.0.97 
frontend-6f686d8d87-q7cfq   1/1     Running   0          18s   172.16.0.47   192.168.0.212
frontend-6f686d8d87-xl8hx   1/1     Running   0          18s   172.16.0.23   192.168.0.94 

おすすめ

転載: blog.51cto.com/14051317/2553703