Kubernetes 学習メモ - 高度なスケジューリング 20230304

序文:

前の章では、kubernetes の拡張、水平拡張、自動スケーリングについて学びましたが、この章では、拡張および縮小されたポッドがどのノードにスケジュールされるかを学び始めます。

以前、kubernetes では、ポッド仕様でノード セレクターを指定することで、ポッドがどのノードにスケジュールされるかに影響を与えることができましたが、この章では他のメカニズムの追加を開始しました。

1. テイントとトレランスを使用して、ノードが特定のノードにスケジュールされないようにする

高度なスケジューリングの 2 つの機能: ノードのテイント、ポッドのテイント耐性

これら 2 つのプロパティは、特定のノードにスケジュールできるポッドを制限するために使用されます。ポッドがノードの汚染を許容する場合にのみ、ポッドをそのノードでスケジュールできます。

説明: これは、ノードセレクターやノードアフィニティーとは多少異なります。ノード セレクターとノード アフィニティ ルールは、ポッドに情報を明示的に追加することで、ポッドをスケジュールできるノードとスケジュールできないノードを決定します。テイントとは、既存の Pod 情報を変更せずにノード上の情報を汚染することで、一部のノードでの Pod のデプロイを拒否することです。
  1. 汚染と耐性

デフォルトでは、マスター ノードにコントロール プレーン ポッドのみをデプロイできるように、クラスターのマスター ノードを汚染する必要があります。

ノードの汚染情報を表示する

kubect description ノードを通じてノードのテイント情報を表示できます。

$kubectl ノード master.k8s を説明します

ポッドは、ノードの汚染を許容できる場合にのみ、ノード上でスケジュールできます。

ポッドの汚染耐性を表示する

kubeadm によって初期化されたクラスターでは、ポッドとして実行されているマスター ノード コンポーネントも kubernetes サービスにアクセスする必要があるため、kube-proxy クラスター コンポーネントはマスター ノードを含む各ノードでポッドとして実行されます。kube-proxy ポッドがマスター ノードでも実行できるようにするには、ポッドに対応する汚染耐性を追加する必要があります。

次のコード:

ポッドの汚染耐性

$kubectl description po kube-proxy-80wqm -n kube-system
...
Tolerations:node-role.kubernetes.io/master=:NoSchedule
node.alpha.kubernetes.io/notReady=:Exists:NoExecute
node.alpha.kubernetes .io/unreachable=:Exists:NoExecute

注: ポッドのテイントトレランスには等号が表示されますが、ノードのテイント情報には等号が表示されません。テイントまたはテイント トレランスの値ビットが null の場合、kubectl は意図的にテイントとテイント トレランスを異なる形式で表示します。

ステイン効果

各ステインは、次の 3 つのタイプを含むエフェクトに関連付けることができます。

  • NoSchedule は、ポッドがこれらの汚れを許容しない場合、これらの汚れを含むノードにポッドをスケジュールできないことを意味します

  • PreferNoSchedule は NoSchedule の緩やかなバージョンです。つまり、ポッドがこのノードにスケジュールされるのを防ぎますが、他にスケジュールするノードがない場合でも、ポッドはこのノードにスケジュールされます。

  • NoExecute は NoSchedule および PreferNoSchedule とは異なり、後者の 2 つはスケジュール中にのみ機能し、NoExecute はノード上で実行されているポッドにも影響します。NoExecute テイントがノードに追加されると、NoExecute テイントを許容しないノード上で実行されているポッドはノードから削除されます。

  1. ノードにカスタム taint を追加する

シナリオ: 実稼働環境と非実稼働環境のトラフィックの両方が存在する別の kubernetes クラスターがあることを前提とします。 要件: 非実稼働環境のポッドは、実稼働環境のノード上で実行できません。この要件は、本番環境のノードにテイントを追加することで満たされます。

kubectl taint を使用してテイントを追加する

$kubectl taintノードnode1.k8snode-type=production:NoSchedule
ノード「node1.k8s」が汚染されました

このコマンドはテイントを追加します。キーはノードタイプ、値は実稼働、効果は NoSchedule です。

この方法では、誰も自由にポッドを運用環境ノードにデプロイできなくなります。

  1. ポッドに汚染耐性を追加する

実稼働ポッドを実稼働ノードにデプロイするには、ポッドがノードに追加する汚染に耐性がある必要があります。yaml コード スニペットを実稼働環境のポッドのマニフェストに追加する必要があります

実動デプロイメント.yaml

apiVersion:extensions/v1beta1
kind:デプロイメント
メタデータ:
name:prod
spec:
replicas:5
template:
spec:
...
tolerations:
-key:node-type
演算子:等しい
値:prodction
効果:NoSchedule

このデプロイメントが実行される場合、ポッドは実稼働ノードにスケジュールされます。

  1. 汚染と汚染耐性の使用例

ノードは複数のテイントを持つことができ、ポッドは複数のテイント耐性を持つことができます。汚染許容度は、値と一致するように Equal 演算子 (デフォルトでは演算子) で指定するか、汚染されたキーと一致するように Exists 演算子を設定することで指定できます。

スケジュール設定時のテイントと許容範囲の使用

ステインを使用して、新しいポッドのスケジュールを整理したり (NoSchedule 効果を使用)、非優先スケジューリング ノードを定義したり (PreferNoSchedule 効果を使用)、現在のノードから既存のポッドを削除したりすることもできます。

汚染と許容値は、適切と思われる方法で設定できます。たとえば、クラスターを複数の部分に分割して、開発チームのみが特定のノードにポッドをスケジュールできるようにすることができます。一部のノードが特別なハードウェアを提供し、一部のポッドのみがこのハードウェアを使用する必要がある場合、テイントとトレランスを設定することもできます。

ノード障害後のポッドの再スケジュールの最大待機時間を構成する

ポッドが実行されているノードが準備完了または到達不能状態になったときの許容値を構成できます。kubernetes は、ポッドが他のノードにスケジュールされるまでの最長待機時間を待機できます。

$kubectl get po prod-350605-1ph5h -o yaml
....
tolerations:
-effect:NoExecute
key:node.alpha.kubernetes.io/notReady
Operator:Exists
tlerationSeconds:300
-effect:NoExecute
key:node.alpha.kubernetes .io/unreachable
演算子:存在します
tolerationSeconds:300

上記の 2 つの許容値は、ノードが 300 秒間 notReady または到達不能状態にあることをポッドが許容することを示しています。kubernetes コントローラーは、ノードが notReady または到達不能状態にあることを検出すると、300 秒待機し、この状態が続く場合は、ポッドを他のノードに再スケジュールします。

2. ノード アフィニティを使用して、特定のノード上でポッドをスケジュールします。

前のセクションのテイントは、ポッドを特定のノードから遠ざけるために使用でき、ノード アフィニティは、ノードの特定のサブセット上でのみポッドをスケジュールするように Kubernetes に通知できます。

ノード アフィニティとノード セレクターの比較

kubernetes の初期バージョンでは、最初のノード アフィニティ メカニズムはポッドの説明の nodeSelector フィールドです。ノードがポッド モバイル化のターゲット ノードになるには、すべてのポッドの対応するフィールドに指定された abel が含まれている必要があります。

ノード セレクターは実装が簡単ですが、すべてのニーズを満たせるわけではありません。より堅牢なメカニズムが導入され、ノード セレクターは最終的に非推奨になります。

ノード セレクターと同様に、各ポッドは独自のノード アフィニティ ルールを定義でき、これによりハード リミットや設定を適用できます。プリファレンスを指定すると、特定のポッドについて、特定のノード上でスケジュールすることを好むことが Kubernetes に伝えられ、kubernetes はこれらのノード上でこのポッドをスケジュールしようとします。これが不可能な場合、ポッドは他のノードにスケジュールされます。

デフォルトのノードラベル

ノード アフィニティは、ノード セレクターと一致するノードのラベルに従って選択されます。

Google Kubernetes Engine クラスタ (GKE) 内のノードのラベルを確認します。デフォルトのラベルは何ですか?

GKE ノードのデフォルトのラベル

$kuectl ノードの説明 gke-kubia-default-pool-db274c5a-mjnf
名前:gke-kubia-default-pool-db274c5a-mjnf
役割:
ラベル:beta.kubernetes.io/arch=amd4
beta.kubernetes.io/fluentd-ds -ready=true
beta.kubernetes.io/instance-type=f1-micro
beta.kubernetes.io/os=linux
cloud.google.com/gke-nodepool=default-pool
Failure-domain.beta.kubernetes.io/region =europe-west1
Failure-domain.beta.kubernetes.io/zone=europe-west1-d
kubernetes.io/hostname=gke-kubia-default-pool-db2754c5a-mjnf

このノードには多くのラベルがありますが、ノード アフィニティとポッド アフィニティに関しては、赤でマークされた最後の 3 つのラベルが最も重要です。これら 3 つのラベルの意味は次のとおりです。

Failure-domain.beta.kubernetes.io/region=europe-west1 は、ノードが配置されている地理的領域を示します

Failure-domain.beta.kubernetes.io/zone=europe-west1-d は、ノードが配置されている可用性ゾーン (可用性ゾーン) を示します。

kubernetes.io/hostname は明らかにノードのホスト名です

これら 3 つはタグとともにポッド アフィニティ ルールで使用されます。

  1. 必須ノードを指定するアフィニティ ルール

例: ノード セレクターは、GPU を最も必要とするポッドが GPU を備えたノードにのみスケジュールされるように使用され、nodeSelector フィールドを含むポッドは次のように記述されます: kubia-gpu-nodeselector.yaml

apiVersion:v1
種類:pod
メタデータ:
名前:kubia-gpu
仕様:
nodeSelector:
gpu:"true"
..

nodeSelector フィールドは、ポッドが gpu=true ラベルを含むノードにのみデプロイできることを示します。ノード セレクターがノード アフィニティ ルールに置き換えられた場合、ポッドは次のように定義されます: kubia-gpu-nodeaffinity.yaml

apiVersion:v1
kind:pod
メタデータ:
name:kubia-gpu
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
-matchExpressions:
-key:gpu
演算子:In
値:
-"true"

アフィニティ ルールは単純なノード セレクターよりもはるかに複雑であるため、より表現力が豊かになります。

長いノード アフィニティ属性名の意味

ポッドの説明には、nodeAffinity フィールドを含むアフィニティ フィールドが含まれています。このフィールドには、requiredSchedulingIgnoredDuringExecution という非常に長い名前が付いています。この名前を 2 つの部分に分割し、それぞれの意味を調べます。

  • requiredDuringSchedulingI... フィールドの下に定義されたルールを示します。ポッドをノードにスケジュールするには、ノードに含める必要があるラベルを明確に示します

  • ...IgnoredDuringExecution は、このフィールドで定義されたルールがノード上ですでに実行されているポッドに影響を与えないことを示します

アフィニティ ルールは、スケジュールされているポッドにのみ影響し、すでに実行されているポッドがカリングされることはありません。状況はより単純になる可能性があるため、現在のルールはすべて IgnoredDuringExecution で終わります。最終的に、kubernetes は RequiredDuringExecution もサポートする予定です。これは、ノード上のノードが削除された場合、ノードにラベルが含まれることを必要とするポッドが提案されることを意味します。しかし、まだサポートされていません

ノードセレクターの条件を理解する

nodeSelectorTerms フィールドと matchExpressions フィールドは、ポッドのスケジュール条件を満たすためにノード ラベルが満たさなければならない式を定義します。

  1. ポッドをスケジュールするときに特定のノードを優先する

ポッドをスケジュールするとき、指定されたスケジューラーはそれらのノードに優先順位を与えることができます。これは、preferredDuringSchedulingIgnoredDuringExecution フィールドを通じて実装されます。

ノードにラベルを付ける

まず、ノードに適切にラベルを付ける必要があります。各ノードには 2 つのラベルが含まれる必要があります。1 つはノードが配置されているアベイラビリティ ゾーンを示すために使用され、もう 1 つは排他ノードか共有ノードかを示すために使用されます。

優先ノード アフィニティ ルールの指定

デプロイメントの yaml ファイルの重みフィールドを使用して優先度を決定できます。

以下は、優先ノード アフィニティ ルールを含むデプロイメントの yaml ファイルです:preferred-deployment.yaml

apiVersion:extensions/v1beta1
kind:Deploymentmetadata
:
name:pref
spec:
template:
...
spec:
affinity:
nodeAffinity:
preferred WhileSchedulingIgnoredDuringExecution:
-weight :80
priority:
matchExpressions:
-key:availability-zone
演算子:In
値:
-zone1
-weight:20
設定:
matchExpressions:
-key:share-type
演算子:In
値:
-dended

上記のコードと同様、ノード アフィニティの優先度は必須ではなく定義されています。

3. ポッド アフィニティと非アフィニティを使用したポッドの共同デプロイメント

前のセクションでは、ノード アフィニティ ルールと、それがポッドがスケジュールされるノードにどのような影響を与えるかについて学びました。ただし、これらのルールはポッドとノード間のアフィニティにのみ影響します。ポッド自体間のアフィニティを指定できる機能が望ましい場合があります。

フロントエンド ポッドとバックエンド ポッドがある場合、待ち時間を短縮し、アプリケーションのパフォーマンスを向上させるために、ノードはより近くにデプロイされます。ノード アフィニティ ルールを使用すると、これら 2 つのポッドが同じノード、同じラック、同じデータ センターにスケジュールされるようにすることができます。ただし、どのノード、どのラック、どのサービス センターにスケジュールを設定するかを指定する必要があります。現時点では、これは最良の解決策ではありません。より良いアプローチは、kubernetes が適切と判断する場所にポッドをデプロイできるようにすることです。同時に、2 つのポッドが互いに接近していることを確認します。この機能はポッド アフィニティによって実現できます。

  1. ポッド間アフィニティを使用して同じノードに複数のポッドをデプロイする

ポッド アフィニティ構成を使用して 1 つのバックエンド ポッド インスタンスと 5 つのフロントエンド ポッド インスタンスをデプロイする必要がある場合、これらのフロントエンド インスタンスはバックエンド ポッドと同じノードにデプロイされます。

まずバックエンド ポッドをデプロイします

$kubectl run backend -l app=backend --imagebusybox -- sleep 999999

デプロイメント「バックエンド」が作成されました

ポッド内で指定されたポッド アフィニティを定義します

フロントエンド ポッド説明ファイルfrontend-podaffinity-host.yaml

apiVersion:extensions/v1beta1
種類:デプロイメント
メタデータ:
名前:フロント
エンド 仕様:
レプリカ:5
テンプレート:
...
仕様:
アフィニティ:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologykey:kubernetes.io/hostname
matchLabels:
app:backend
....

注: 単純な matchLabels フィールドの使用に加えて、より表現力豊かな matchExpressions フィールドも使用できます。

ポッド アフィニティを使用してポッドをデプロイする

$kubectl get po -o Wide

フロントエンド展開ポッド

$kubectl create -f フロントエンド-podaffinity-host.yaml

すべてのフロントエンド ポッドはバックエンド ポッドと同じノードにスケジュールされます。フロントエンド ポッドをスケジュールするとき、スケジューラはまずフロントエンド ポッドの podAffinity 構成内の labelSelector に一致するすべてのポッドを見つけてから、フロントエンド ポッドを同じノードに接続します。

スケジューリングでポッド アフィニティ ルールがどのように使用されるかを学習する

バックエンド ポッドがここで削除された場合、バックエンド ポッドがポッド アフィニティ ルールを定義していない場合でも、スケジューラはフロントエンド ポッドが配置されているノードにポッドをスケジュールします (フロントエンド ポッドのみ)。ルールが設定されています)。

  1. ポッドを同じラック、可用性ゾーン、または地理的リージョンにデプロイする

前の例では、podAffinity を使用してフロントエンド ポッドとバックエンド ポッドを同じノードにデプロイします。すべてのフロントエンド ポッドを同じノードにデプロイしたくないが、それでもデプロイしたい場合は、たとえば、同じアベイラビリティ ゾーン内など、バックエンド ポッドに十分近い場所にあります。

同じアベイラビリティーゾーンに od を共同デプロイする

topologyKey プロパティを Failure-domain.beta.kubernetes.io/zone に設定することで、フロントエンド ポッドとバックエンド ポッドが同じアベイラビリティ ゾーンで実行されるようにすることができます。

同じリージョンにポッドを共同デプロイする

これを行うには、topologyKey プロパティを Failure-domain.beta.kubernetes.io/region に設定します。

  1. 必須ではなく Express ポッド アフィニティの優先順位を設定する

ノード アフィニティ、nodeAffinity は、ノード アフィニティ ルールを満たすノードにのみポッドをスケジュールできることを示す必須要件を表すことも、特定のノードにポッドをスケジュールするようにスケジューラーに通知するために使用されるノードの優先順位を表すこともできます。これらのノードがさまざまな理由でポッドの要件を満たせない場合、ポッドを他のノードにスケジュールできます。

この機能は podAffinity にも適用され、フロントエンド ポッドをバックエンド ポッドと同じノードに優先的にスケジュールするようにスケジューラーに指示できますが、そうでない場合は他のノードにスケジュールすることもできます。prerendDuringSchedulingIgnoredDuringExecution ポッド アフィニティ ルールを使用するデプロイメント。

yamlファイルは次のとおりです

apiVersion:extensions/v1beta1
種類:デプロイメント
メタデータ:
名前:フロント
エンド仕様:
レプリカ:5
テンプレート:
...
仕様:
アフィニティ:
podAffinity:
preferredSchedulingIgnoredDuringExection:
-weight:80
podAffinityTerm:
topologyKey:kubernetes.io/hostname
labelSelector:
matchLabels:
app:バックエンド
コンテナ...

NodeAffinity 優先順位ルールと同様に、ルールの重みを設定する必要があります。また、topologyKey と labelSelector を設定する必要があります。

4. ポッドの非アフィニティを使用してポッドを個別にスケジュールする

ポッドを互いに遠くに置く必要がある場合は、ポッドの非アフィニティを使用できます。これは、podAffinity フィールドが podAntiAffinity に置き換えられる点を除き、ポッド アフィニティと同じ方法で表現されます。これにより、スケジューラは、ポッドと一致するポッドを選択しなくなります。 podAntiAffinity 一致タグを含む ポッドが配置されているノード。

説明: ポッドの非アフィニティーを使用する必要がある理由の例としては、2 セットのポッドが同じノード上で実行されている場合に、互いのパフォーマンスに影響を与える場合が挙げられます。この場合、これらのポッドを同じノードにスケジュールしないようにスケジューラに指示する必要があります。

もう 1 つの例は、スケジューラに同じグループのポッドを異なる可用性ゾーンに分割するように強制して、ゾーン全体に障害が発生してもサービス全体が完全に使用不能にならないようにすることです。

非アフィニティを使用してデプロイメント内にポッドを分散する

フロントエンド-podantiaffinity-host.yaml

apiVersion:extensions/v1beta1
kind:Deployment
メタデータ:
name:frontend
spec:
replicas:5
template:
metadata:
labels:
app:frontend
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExection
- topologyKey:kubernetes.io/hostname
labelSelector:
machLabels:
app:frontend
コンテナ:...

上で定義したように、podAntiAffinity は podAffinity ではなく、labelSelector と Deployment によって作成されたポッドが一致します。

まとめ:

この章では主に、ノードまたはノード上で実行されているポッドのラベルを通じてポッドが特定のノードにスケジュールされていないこと、またはポッドのみが特定のノードにスケジュールされていることを確認する方法を学習します。

  • ノードに 1 つのテイント情報を追加すると、ポッドがこれらのテイントを許容しない限り、ポッドはノードにスケジュールされません。

  • テイント タイプは 3 つあります。NoSchedule はスケジュールを完全に阻止し、PreferNoSchedule はスケジュールを強制的に阻止しません。NoExecute は既に実行中のポッドをノードから削除します。

  • NoExecute ステインも同時に設定できます。ポッドが実行されているノードが到達不能または準備不能になり、ポッドを再スケジュールする必要がある場合、コントロール パネル上の最長待機時間が表示されます。

  • ノード アフィニティを使用すると、ポッドをスケジュールする必要があるノードを指定できます。これは、必須要件またはノードの優先順位として使用できます。

  • ポッド アフィニティは、(ポッドのラベルに基づいて) 別のポッドと同じノード上でポッドをスケジュールするようにスケジューラに指示するために使用されます。

  • ポッド アフィニティの topologyKey は、スケジュールされたポッドと別のポッド (同じノード、同じキャビネット、同じ可用性ローカル エリアまたは可用性エリア内) の間の距離を示します。

  • ポッドの非アフィニティを使用して、特定のポッドから遠く離れたノードにポッドをスケジュールできます。

  • ノード アフィニティと同様に、ポッド アフィニティと非アフィニティは、必須の要件または優先順位の選択として設定できます。

おすすめ

転載: blog.csdn.net/wwxsoft/article/details/129333141