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を表示できます.
ノードnode 02にcom=youdianzhishiのラベルを追加します.コマンドは次のとおりです.
上記の--show-labelsパラメータを使用して、上記のラベルが有効かどうかを確認できます.Nodeが関連ラベルを付けられた後、スケジューリング時にこれらのラベルを使用することができます.PodのspecフィールドにnodeSelectorフィールドを追加するだけで、スケジューリングするノードのlabelが必要です.たとえば、次のPodはnode 02というノードに強制的にスケジューリングされ、nodeSelectorを使用して表すことができます:(node-selector-demo.yaml)
次にdescribeコマンドでスケジュール結果を表示できます.
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)
上のpodはまずnode 03というノードで実行できないことを要求し,com=youdianzhishiを満たすノードがあればこのノードに優先的にスケジューリングする.
次に、テストしたノードのリスト情報を示します.
Node 02ノードにはcom=youdianzhishiのようなlabelがあり、要求に応じて優先的にこのノードにスケジューリングされていることがわかります.ここでpodを作成し、descirbeコマンドを使用して具体的なスケジューリング状況が私たちの要求を満たしているかどうかを確認します.
結果から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を同じホスト上に作成します.
同様に、上記のリソースオブジェクトに対してpodの親和性をテストします:(pod-affinity-demo.yaml)
上記の例のpodは、特定のホストにスケジューリングする必要があり、少なくとも1つのノードでこのようなpodが実行されています.このpodにはapp=busybox-podのlabelがあります.
ラベルapp=busybox-podのpodリストを表示します.
このpodはnode 02のノード上で実行されているので、上記の親和性に基づいて、上記の3つのpodコピーもnode 02ノード上で実行する必要があります.
上のtest-busyboxとaffinityというDeploymentを削除し、affinityというリソースを再作成して、正常にスケジューリングできるかどうかを見てみましょう.
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はどのノードにもスケジューリングされる可能性があります.
これがpod親和性の使い方ですが、pod反親和性は逆です.例えば、ノードでpodが実行されている場合、私たちのpodは他のノードにスケジューリングされることを望んでいます.同じように、上のpodAffinityをpodAntiAffinityに直接変更します.(pod-antiaffinity-demo.yaml)
ここで、ノードの上にapp=busybox-podというpodがある場合、私たちのpodはこのノードの上にスケジューリングしないでください.app=busybox-podというpodをnode 03というノードの上に固定しています.だから、通常、私たちのこのpodはnode 03ノードに現れません.
これがpodの反親和性の使い方です.
親和性にはノード親和性(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の反親和性の使い方です.