Azure Kubernetes Service (AKS) での高度なスケジューラ機能に関するベスト プラクティス
Azure Kubernetes Service (AKS) でクラスターを管理する際は、多くの場合、チームとワークロードを分離する必要があります。 Kubernetes スケジューラで提供される高度な機能を使用すると、次のことが制御できます。
- 特定のノードでスケジュールできるポッド。
- マルチポッド アプリケーションをクラスター全体へ適切に分散させる方法。
このベスト プラクティス記事では、クラスター オペレーター向けに Kubernetes の高度なスケジュール機能について説明します。 この記事では、次のことについて説明します。
- テイントと容認を使用して、ノードでスケジュールできるポッドを制限します。
- ノード セレクターまたはノード アフィニティを使用して、特定のノードで実行するポッドに優先順位を指定します。
- ポッド間アフィニティまたは非アフィニティを使用して、ポッドを分割したりグループ化したりします。
- スケジュール可能な GPU を持つノードでのみ GPU を必要とするワークロードのスケジュール設定を制限します。
テイントと容認を使用して専用のノードを提供する
ベスト プラクティスのガイダンス:
イングレス コントローラーなどのリソースを多量に消費するアプリケーションへのアクセスを特定のノードに制限します。 ノードのリソースをそれが必要なワークロードで使用できるように保ち、そのノードでは他のワークロードをスケジュールできないようにします。
AKS クラスターを作成するときは、GPU のサポートや多数の強力な CPU を備えたノードをデプロイできます。 詳細については、AKS での GPU の使用に関するページを参照してください。 このようなノードは、機械学習 (ML) や人工知能 (AI) などの大規模なデータ処理ワークロードに使用できます。
このノード リソース ハードウェアは通常、デプロイにコストがかかるため、これらのノードでスケジュールできるワークロードを制限します。 代わりに、クラスター内にある一部のノードをイングレス サービスの実行専用にして、他のワークロードを防ぐこともできます。
さまざまなノードに対するこのサポートは、複数のノード プールを使用して提供されます。 AKS クラスターでは、1 つ以上のノード プールがサポートされます。
Kubernetes スケジューラでは、テイントと容認を使用して、ノードで実行できるワークロードを制限できます。
- テイントをノードに適用して、特定のポッドのみをノードにスケジュールできることを示します。
- 次に、ポッドに容認を適用して、ノードのテイントを容認できるようにします。
ポッドを AKS クラスターにデプロイすると、Kubernetes によってテイントが容認と一致するノードでのみポッドがスケジュールされます。 テイントと容認は、連携動作して、ポッドが不適切なノードにスケジュールされないようにします。 1 つ以上のテイントがノードに適用され、ノードがそのテイントを許容しないポッドを受け入れないようにノードをマークします。
たとえば、GPU をサポートしているノードのプールを AKS クラスターに追加した場合を考えてください。 gpu などの名前と、スケジュールのための値を定義します。 この値を NoSchedule に設定すると、Kubernetes スケジューラによってノード上で未定義の容認を使用したポッドがスケジュールされることが制限されます。
az aks nodepool add \
--resource-group myResourceGroup \
--cluster-name myAKSCluster \
--name taintnp \
--node-taints sku=gpu:NoSchedule \
--no-wait
ノード プールのノードにテイントを適用した上で、それらのノードへのスケジュールを許可するポッドの仕様内で容認を定義します。 次の例では、sku: gpu
と effect: NoSchedule
を指定することで、前のステップでノード プールに適用したテイントを容認するように設定してます。
kind: Pod
apiVersion: v1
metadata:
name: app
spec:
containers:
- name: app
image: <your-workload>:gpu
resources:
requests:
cpu: 0.5
memory: 2Gi
limits:
cpu: 4.0
memory: 16Gi
tolerations:
- key: "sku"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
kubectl apply -f gpu-toleration.yaml
を使用してこのポッドをデプロイすると、Kubernetes によってテイントが適用されたノードでポッドが正常にスケジュールできます。 この論理的な分離を使用することで、クラスター内のリソースへのアクセスを制御できます。
テイントを適用するときは、アプリケーションの開発者や所有者と協力して、デプロイで必要な容認を定義できるようにします。
AKS で複数のノード プールを使用する方法の詳細については、「AKS のクラスターに対する複数のノード プールの作成」を参照してください。
AKS でのテイントと容認の動作
AKS でノード プールをアップグレードすると、テイントと容認は新しいノードに適用されるときに、次のように設定されたパターンに従います。
Azure Virtual Machine Scale Sets を使用する既定のクラスター
AKS API からノード プールのテイントを設定して、新たにスケールアウトされたノードが API で指定されたノードのテイントを受け取るようにすることができます。
次のような場合を考えてみましょう。
- 2 ノード クラスター、node1 と node2 から始めます。
- ノード プールをアップグレードします。
- node3 と node4 という 2 つの追加ノードが作成されます。
- テイントはそれぞれ渡されます。
- 元の node1 と node2 は削除されます。
Virtual Machine Scale Sets のサポートがないクラスター
ここでも、次のことを想定してみましょう。
- 2 つのノード クラスター、node1 と node2 があるとします。
- ノード プールをアップグレードします。
- node3 という追加のノードが作成されます。
- node1 のテイントが node3 に適用されます。
- node1 が削除されます。
- 新しい node1 が作成され、元の node1 と置き換えられます。
- node2 のテイントが新しい node1 に適用されます。
- node2 が削除されます。
つまり、node1 が node3 になり、node2 が新しい node1 になります。
AKS でノード プールをスケーリングするとき、テイントと容認は設計上持ち越されません。
ノード セレクターとアフィニティを使用してポッドのスケジュールを制御する
ベスト プラクティスのガイダンス
ノード セレクター、ノードのアフィニティ、またはポッド間のアフィニティを使用して、ノード上のポッドのスケジュールを制御します。 これらの設定を使用すると、Kubernetes のスケジューラは、ノードのハードウェアなどによって、ワークロードを論理的に分離できます。
テイントと容認は、ハードカット オフでリソースを論理的に分離します。 ポッドがノードのテイントを許容していない場合、そのノードはノード上でスケーリングされていません。
または、ノード セレクターを使用することもできます。 たとえば、ローカルにアタッチされた SSD ストレージや大容量のメモリを示すラベルをノードに付けてから、ポッドの仕様でノード セレクターを定義します。 Kubernetes は一致するノード上にこれらのポッドをスケジュールします。
容認とは異なり、一致するノード セレクターのないポッドは、ラベルが付いているノードでもスケジュールできます。 この動作により、ノード上にある未使用のリソースを消費できますが、一致するノード セレクターが定義されているポッドが優先されます。
大容量メモリを装備したノードの例を見てみましょう。 これらのノードでは、大量のメモリを要求するポッドが優先されます。 リソースがアイドル状態にならないようにするために、他のポッドの実行も許可されます。 次のサンプル コマンドでは、hardware=highmem というラベルを持つノード プールを、myResourceGroup の myAKSCluster に追加します。 そのノード プールのすべてのノードがこのラベルを持ちます。
az aks nodepool add \
--resource-group myResourceGroup \
--cluster-name myAKSCluster \
--name labelnp \
--node-count 1 \
--labels hardware=highmem \
--no-wait
ポッドの仕様に、ノードで設定されているラベルと一致するノード セレクターを定義する nodeSelector
プロパティを追加します。
kind: Pod
apiVersion: v1
metadata:
name: app
spec:
containers:
- name: app
image: <your-workload>:gpu
resources:
requests:
cpu: 0.5
memory: 2Gi
limits:
cpu: 4.0
memory: 16Gi
nodeSelector:
hardware: highmem
これらのスケジューラ オプションを使用するときは、アプリケーションの開発者および所有者と協力して、ポッドの仕様を正しく定義できるようにします。
ノード セレクターの使用について詳しくは、「Assigning Pods to Nodes」 (ノードへのポッドの割り当て) をご覧ください。
ノード アフィニティ
ノード セレクターは、特定のノードにポッドを割り当てる際の基本的なソリューションです。 ノードのアフィニティにより柔軟性が向上し、ポッドがノードと一致できない場合に起こる事象を定義できるようになります。 次の操作を行います。
- Kubernetes スケジューラがポッドをラベルの付いたホストと一致させる必要があります。 または、
- 一致させることを優先しますが、一致するものがない場合は、ポッドが別のホストでスケジュールできるようにします。
次の例では、ノード アフィニティを requiredDuringSchedulingIgnoredDuringExecution に設定しています。 このアフィニティでは、一致するラベルを持つノードを使用することが要求されます。 使用できるノードがない場合、ポッドはスケジュールの継続を待機する必要があります。 ポッドを別のノードでスケジュールできるようにするには、値をpreferredDuringSchedulingIgnoreDuringExecution に設定します。
kind: Pod
apiVersion: v1
metadata:
name: app
spec:
containers:
- name: app
image: <your-workload>:gpu
resources:
requests:
cpu: 0.5
memory: 2Gi
limits:
cpu: 4.0
memory: 16Gi
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: hardware
operator: In
values:
- highmem
設定の IgnoredDuringExecution の部分は、ノードのラベルが変更された場合に、ポッドをノードから削除してはならないことを示しています。 Kubernetes スケジューラでは、新しくスケジュールされるポッドに対してのみ更新されたノード ラベルが使用され、ノードで既にスケジュールされているポッドには使用されません。
詳しくは、「Affinity and anti-affinity」 (アフィニティと非アフィニティ) をご覧ください。
ポッド間アフィニティと非アフィニティ
Kubernetes スケジューラでワークロードを論理的に分離する最後の方法では、ポッド間アフィニティまたは非アフィニティを使用します。 これらの設定は、一致するポッドが既にあるノードでポッドをスケジュールする必要がないか、あるいは必要があるかのいずれかを定義できます。 既定では、Kubernetes スケジューラは、ノードをまたぐレプリカ セットに複数のポッドのスケジュールを試みます。 この動作に関しては、さらに具体的なルールを定義できます。
たとえば、Azure Cache for Redis も使用する Web アプリケーションがあります。
- ポッドの非アフィニティ ルールを使用して、Kubernetes スケジューラによってノード間でレプリカを分散するように要求します。
- アフィニティ ルールを使用して、各 Web アプリ コンポーネントが対応するキャッシュと同じホストにスケジュールされるようにします。
複数ノードへのポッドの分散は、次の例のようになります。
ノード 1 | ノード 2 | ノード 3 |
---|---|---|
webapp-1 | webapp-2 | webapp-3 |
cache-1 | cache-2 | cache-3 |
ポッド間のアフィニティと非アフィニティは、ノード セレクターまたはノード アフィニティよりも複雑なデプロイを提供します。 デプロイすることで、リソースを論理的に分離し、Kubernetes がノードでポッドをスケジュールする方法を制御できます。
Azure Cache for Redis を使用するこの Web アプリケーションの完全な例については、同じノードへのポッドの併置に関する記事をご覧ください。
次のステップ
この記事では、Kubernetes の高度なスケジューラ機能に注目しました。 AKS でのクラスター操作の詳細については、次のベスト プラクティスを参照してください。
Azure Kubernetes Service