Kubernetes(k 8 s)親和性スケジューリング

13319 ワード

一般的に私たちが配置するPodはクラスタの自動スケジューリングポリシーによってノードを選択します.デフォルトではスケジューラはリソースが十分で、負荷ができるだけ平均化されていますが、私たちの内部のサービスgitlabのようなPodのスケジューリングをより細かく制御する必要があります.例えば、私たちの内部のサービスgitlabもKubernetesクラスタを走っています.私たちは対外的ないくつかのサービスと内部のサービスが同じノードに走ることを望んでいません.内部のサービスが外部のサービスに影響を与えることを心配しています.しかし、私たちのサービス間のコミュニケーションが頻繁な場合もあり、この2つのサービスのPodを同じノードにスケジューリングすることを望んでいます.これはKubernetesの概念:親和性と反親和性を使用する必要があります.
親和性にはノード親和性(nodeAffinity)とPod親和性(podAffinity)がある.
nodeSelector
親和性を理解する前に、nodeSelectorという非常に一般的なスケジューリング方法を理解します.labelはkubernetesの非常に重要な概念であることを知っています.ユーザーはlabelを非常に柔軟に利用してクラスタ内のリソースを管理することができます.例えば、最も一般的なのはserviceがlabelをマッチングすることによってPodリソースをマッチングし、Podのスケジューリングもノードのlabelに基づいてスケジューリングすることができます.
次のコマンドでnodeのlabelを表示できます.
$ kubectl get nodes --show-labels
NAME      STATUS    ROLES     AGE       VERSION   LABELS
master    Ready     master    147d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=
node02    Ready         67d       v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,course=k8s,kubernetes.io/hostname=node02
node03    Ready         127d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,jnlp=haimaxy,kubernetes.io/hostname=node03

ノードnode 02にcom=youdianzhishiのラベルを追加します.コマンドは次のとおりです.
$ kubectl label nodes node02 com=youdianzhishi
node "node02" labeled

上記の--show-labelsパラメータを使用して、上記のラベルが有効かどうかを確認できます.Nodeが関連ラベルを付けられた後、スケジューリング時にこれらのラベルを使用することができます.PodのspecフィールドにnodeSelectorフィールドを追加するだけで、スケジューリングするノードのlabelが必要です.たとえば、次のPodはnode 02というノードに強制的にスケジューリングされ、nodeSelectorを使用して表すことができます:(node-selector-demo.yaml)
apiVersion: v1
kind: Pod
metadata:
  labels:
    app: busybox-pod
  name: test-busybox
spec:
  containers:
  - command:
    - sleep
    - "3600"
    image: busybox
    imagePullPolicy: Always
    name: test-busybox
  nodeSelector:
    com: youdianzhishi

次にdescribeコマンドでスケジュール結果を表示できます.
$ kubectl create -f node-selector-demo.yaml
pod "test-busybox" created
$ kubectl describe pod test-busybox
Name:         test-busybox
Namespace:    default
Node:         node02/10.151.30.63
......
QoS Class:       BestEffort
Node-Selectors:  com=youdianzhishi
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  SuccessfulMountVolume  55s   kubelet, node02    MountVolume.SetUp succeeded for volume "default-token-n9w2d"
  Normal  Scheduled              54s   default-scheduler  Successfully assigned test-busybox to node02
  Normal  Pulling                54s   kubelet, node02    pulling image "busybox"
  Normal  Pulled                 40s   kubelet, node02    Successfully pulled image "busybox"
  Normal  Created                40s   kubelet, node02    Created container
  Normal  Started                40s   kubelet, node02    Started container

Eventsの次の情報が表示され、私たちのPodはデフォルトのdefault-schedulerスケジューラを通じてnode 02ノードにバインドされています.ただし、nodeSelectorは強制的であり、ターゲットノードに使用可能なリソースがなければ、Podは常にPending状態にあります.これがnodeSelectorの使い方です.
上記の例では、nodeSelectorの方式が直感的であることを感じることができますが、まだ柔軟で、制御粒度が大きいので、次に、ノード親和性(nodeAffinity)というより柔軟な方法を理解します.
親和性と反親和性スケジューリング
以前はkubernetesスケジューラのスケジューリングの流れを理解していましたが、デフォルトのスケジューラが使用されている間にpredicatesとprioritiesの2つの段階を経ていることを知っていましたが、実際の生産環境では、podのスケジューリングを自分の実際のニーズに基づいて制御する必要があることがよくあります.これはnodeAffinity(ノード親和性)、podAffinity(pod親和性)、podAntiAffinity(pod反親和性)を使用する必要があります.
親和性スケジューリングは、ソフト・ポリシーとハード・ポリシーの2つの方法に分けることができます.
ソフトポリシーとは、スケジューリング要求を満たすノードがなければpodはこのルールを無視してスケジューリングプロセスを継続し、はっきり言って条件を満たすのが一番で、なければどうでもいいポリシーハードポリシーは比較的強硬で、条件を満たすノードがなければ、条件を満たすまで繰り返し、簡単に言えば私の要求を満たさなければならない、さもないと私はやらないポリシーです.親和性と反親和性には、p r e f e r e d D u r g S h e d D u r g I g n o r e d DuringExecutionとr e q u i r e d DuringSchedulingIgnoredDuringExecutionの2つのルールがあります.前はソフトポリシーで、後ろはハードポリシーです.
nodeAffinity
ノード親和性は、podがどのホストに配備されるか、どのホストに配備できないかを制御するために主に使用されます.単純な等しいマッチングだけでなく、いくつかの簡単な論理組合せを行うことができます.
たとえば、3つのpodコピーを1つのDeploymentで管理し、次の例でこれらのpodのスケジューリングを制御します.(node-affinity-demo.yaml)
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: affinity
  labels:
    app: affinity
spec:
  replicas: 3
  revisionHistoryLimit: 15
  template:
    metadata:
      labels:
        app: affinity
        role: test
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
          name: nginxweb
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  #    
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/hostname
                operator: NotIn
                values:
                - node03
          preferredDuringSchedulingIgnoredDuringExecution:  #    
          - weight: 1
            preference:
              matchExpressions:
              - key: com
                operator: In
                values:
                - youdianzhishi

上のpodはまずnode 03というノードで実行できないことを要求し,com=youdianzhishiを満たすノードがあればこのノードに優先的にスケジューリングする.
次に、テストしたノードのリスト情報を示します.
$ kubectl get nodes --show-labels
NAME      STATUS    ROLES     AGE       VERSION   LABELS
master    Ready     master    154d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=
node02    Ready         74d       v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,com=youdianzhishi,course=k8s,kubernetes.io/hostname=node02
node03    Ready         134d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,jnlp=haimaxy,kubernetes.io/hostname=node03

Node 02ノードにはcom=youdianzhishiのようなlabelがあり、要求に応じて優先的にこのノードにスケジューリングされていることがわかります.ここでpodを作成し、descirbeコマンドを使用して具体的なスケジューリング状況が私たちの要求を満たしているかどうかを確認します.
$ kubectl create -f node-affinity-demo.yaml
deployment.apps "affinity" created
$ kubectl get pods -l app=affinity -o wide
NAME                        READY     STATUS    RESTARTS   AGE       IP             NODE
affinity-7b4c946854-5gfln   1/1       Running   0          47s       10.244.4.214   node02
affinity-7b4c946854-l8b47   1/1       Running   0          47s       10.244.4.215   node02
affinity-7b4c946854-r86p5   1/1       Running   0          47s       10.244.4.213   node02

結果からpodはnode 02に配備されており、他のノードにはpodが配備されていないことがわかります.ここでのマッチングロジックはlabelの値がリストにあり、Kubernetesが提供するオペレータは以下のいくつかあります.
In:labelの値あるリストにあるNotIn:labelの値があるリストにないGt:labelの値がある値Lt:labelより大きい値がある値Existsより小さい:あるlabelがDoesNotExistに存在する:あるlabelが存在しないnodeSelectorTermsの下に複数の選択肢があれば、いずれかの条件を満たすことができる;matchExpressionsに複数のオプションがある場合は、PODを正常にスケジュールするには、これらの条件を同時に満たす必要があります.
podAffinity
pod親和性は主にpodが同じトポロジードメインに配置できる問題(トポロジードメインはホストラベルで実現され、単一ホストであってもよいし、複数のホストからなるcluster、zoneなどであってもよい)を解決し、pod反親和性は主にpodが同じトポロジードメインに配置できない問題を解決し、それらはすべて処理されたpodとpodの関係である.例えばpodがノードにあるとしたら、私もこのノードにいなければなりません.あるいは、このpodがノードにいるとしたら、私はあなたと同じノードにいたくありません.
ここにはクラスタが1つしかないので、エリアや機械室の概念はありません.ここではホスト名を直接トポロジードメインとして使用し、podを同じホスト上に作成します.
$ kubectl get nodes --show-labels
NAME      STATUS    ROLES     AGE       VERSION   LABELS
master    Ready     master    154d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=
node02    Ready         74d       v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,com=youdianzhishi,course=k8s,kubernetes.io/hostname=node02
node03    Ready         134d      v1.10.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,jnlp=haimaxy,kubernetes.io/hostname=node03

同様に、上記のリソースオブジェクトに対してpodの親和性をテストします:(pod-affinity-demo.yaml)
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: affinity
  labels:
    app: affinity
spec:
  replicas: 3
  revisionHistoryLimit: 15
  template:
    metadata:
      labels:
        app: affinity
        role: test
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
          name: nginxweb
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  #    
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - busybox-pod
            topologyKey: kubernetes.io/hostname

上記の例のpodは、特定のホストにスケジューリングする必要があり、少なくとも1つのノードでこのようなpodが実行されています.このpodにはapp=busybox-podのlabelがあります.
ラベルapp=busybox-podのpodリストを表示します.
$ kubectl get pods -o wide -l app=busybox-pod
NAME           READY     STATUS    RESTARTS   AGE       IP             NODE
test-busybox   1/1       Running   164        7d        10.244.4.205   node02

このpodはnode 02のノード上で実行されているので、上記の親和性に基づいて、上記の3つのpodコピーもnode 02ノード上で実行する必要があります.
$ kubectl get pods -o wide -l app=affinity
NAME                        READY     STATUS    RESTARTS   AGE       IP             NODE
affinity-564f9d7db9-lzzvq   1/1       Running   0          3m        10.244.4.216   node02
affinity-564f9d7db9-p79cq   1/1       Running   0          3m        10.244.4.217   node02
affinity-564f9d7db9-spfzs   1/1       Running   0          3m        10.244.4.218   node02

上のtest-busyboxとaffinityというDeploymentを削除し、affinityというリソースを再作成して、正常にスケジューリングできるかどうかを見てみましょう.
$ kubectl delete -f node-selector-demo.yaml
pod "test-busybox" deleted
$ kubectl delete -f pod-affinity-demo.yaml
deployment.apps "affinity" deleted
$ kubectl create -f pod-affinity-demo.yaml
deployment.apps "affinity" created
$ kubectl get pods -o wide -l app=affinity
NAME                        READY     STATUS    RESTARTS   AGE       IP        NODE
affinity-564f9d7db9-fbc8w   0/1       Pending   0          2m            
affinity-564f9d7db9-n8gcf   0/1       Pending   0          2m            
affinity-564f9d7db9-qc7x6   0/1       Pending   0          2m            

Pending状態にあることがわかります.これは、busybox-podというlabelのpodを持つノードが1つもないためです.上のスケジューリングはハードポリシーを使用しているので、スケジューリングできません.test-busyboxというpodをnode 03というノードに再スケジューリングしてみてください.上のaffinityの3つのコピーもnode 03というノードにスケジューリングされているのではないでしょうか.
ここで使われているのはクベルネッツですio/hostnameというトポロジードメインは、現在スケジューリングされているpodがターゲットのpodと同じホスト上にあることを意味します.同じトポロジードメインの下にあるため、この問題を説明するために、トポロジードメインをbetaに変更します.kubernetes.io/os、同じ私たちが現在スケジューリングしているpodはターゲットのpodと同じトポロジードメインにあり、ターゲットのpodはbetaを持っているかどうか.kubernetes.io/os=linuxのラベルですが、3つのノードにはこのようなラベルがあります.これは、3つのノードが同じトポロジードメインにあることを意味します.したがって、podはどのノードにもスケジューリングされる可能性があります.
$ kubectl get pods -o wide
NAME                                      READY     STATUS      RESTARTS   AGE       IP             NODE
affinity-7d86749984-glkhz                 1/1       Running     0          3m        10.244.2.16    node03
affinity-7d86749984-h4fb9                 1/1       Running     0          3m        10.244.4.219   node02
affinity-7d86749984-tj7k2                 1/1       Running     0          3m        10.244.2.14    node03
podAntiAffinity

これがpod親和性の使い方ですが、pod反親和性は逆です.例えば、ノードでpodが実行されている場合、私たちのpodは他のノードにスケジューリングされることを望んでいます.同じように、上のpodAffinityをpodAntiAffinityに直接変更します.(pod-antiaffinity-demo.yaml)
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: affinity
  labels:
    app: affinity
spec:
  replicas: 3
  revisionHistoryLimit: 15
  template:
    metadata:
      labels:
        app: affinity
        role: test
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
          name: nginxweb
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  #    
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - busybox-pod
            topologyKey: kubernetes.io/hostname

ここで、ノードの上にapp=busybox-podというpodがある場合、私たちのpodはこのノードの上にスケジューリングしないでください.app=busybox-podというpodをnode 03というノードの上に固定しています.だから、通常、私たちのこのpodはnode 03ノードに現れません.
$ kubectl create -f pod-antiaffinity-demo.yaml
deployment.apps "affinity" created
$ kubectl get pods -o wide
NAME                                      READY     STATUS      RESTARTS   AGE       IP             NODE
affinity-bcbd8854f-br8z8                  1/1       Running     0          5s        10.244.4.222   node02
affinity-bcbd8854f-cdffh                  1/1       Running     0          5s        10.244.4.223   node02
affinity-bcbd8854f-htb52                  1/1       Running     0          5s        10.244.4.224   node02
test-busybox                              1/1       Running     0          23m       10.244.2.10    node03

これがpodの反親和性の使い方です.