Azure Kubernetes Service (AKS) での高度なスケジューラ機能に関するベスト プラクティスBest practices for advanced scheduler features in Azure Kubernetes Service (AKS)

Azure Kubernetes Service (AKS) でクラスターを管理する際は、多くの場合、チームとワークロードを分離する必要があります。As you manage clusters in Azure Kubernetes Service (AKS), you often need to isolate teams and workloads. Kubernetes スケジューラで提供されている高度な機能を使用すると、特定のノードでスケジュールできるポッドや、マルチポッド アプリケーションをクラスター全体に適切に分散させる方法を、制御することができます。The Kubernetes scheduler provides advanced features that let you control which pods can be scheduled on certain nodes, or how multi-pod applications can appropriately distributed across the cluster.

このベスト プラクティス記事では、クラスター オペレーター向けに Kubernetes の高度なスケジュール機能について説明します。This best practices article focuses on advanced Kubernetes scheduling features for cluster operators. この記事では、次のことについて説明します。In this article, you learn how to:

  • テイントと容認を使用して、ノードでスケジュールできるポッドを制限するUse taints and tolerations to limit what pods can be scheduled on nodes
  • ノード セレクターまたはノード アフィニティを使用して、特定のノードで実行するポッドに優先順位を指定するGive preference to pods to run on certain nodes with node selectors or node affinity
  • ポッド間アフィニティまたは非アフィニティを使用して、ポッドを分けたりまとめたりするSplit apart or group together pods with inter-pod affinity or anti-affinity

テイントと容認を使用して専用のノードを提供するProvide dedicated nodes using taints and tolerations

ベスト プラクティス ガイダンス - イングレス コントローラーのようなリソースを消費するアプリケーションのアクセスを特定のノードに制限します。Best practice guidance - Limit access for resource-intensive applications, such as ingress controllers, to specific nodes. ノードのリソースをそれが必要なワークロードで使用できるように保ち、そのノードでは他のワークロードをスケジュールできないようにします。Keep node resources available for workloads that require them, and don't allow scheduling of other workloads on the nodes.

AKS クラスターを作成するときは、GPU のサポートや多数の強力な CPU を備えたノードをデプロイできます。When you create your AKS cluster, you can deploy nodes with GPU support or a large number of powerful CPUs. このようなノードは、機械学習 (ML) や人工知能 (AI) などの大規模なデータ処理ワークロードによく使用されます。These nodes are often used for large data processing workloads such as machine learning (ML) or artificial intelligence (AI). 通常、この種のハードウェアはデプロイするのが高価なノード リソースなので、これらのノードでスケジュールできるワークロードを制限します。As this type of hardware is typically an expensive node resource to deploy, limit the workloads that can be scheduled on these nodes. 代わりに、クラスターの一部のノードをイングレス サービスの実行専用にして、他のワークロードを防ぐこともできます。You may instead wish to dedicate some nodes in the cluster to run ingress services, and prevent other workloads.

さまざまなノードに対するこのサポートは、複数のノード プールを使用して提供されます。This support for different nodes is provided by using multiple node pools. AKS クラスターでは、1 つ以上のノード プールが提供されます。An AKS cluster provides one or more node pools.

Kubernetes スケジューラでは、テイントと容認を使用して、ノードで実行できるワークロードを制限できます。The Kubernetes scheduler can use taints and tolerations to restrict what workloads can run on nodes.

  • テイントは、ノードに適用されて、特定のポッドのみをそのノードでスケジュールできることを示します。A taint is applied to a node that indicates only specific pods can be scheduled on them.
  • 容認は、ポッドに適用されて、ポッドがノードのテイントを "許容する" ことを許可します。A toleration is then applied to a pod that allows them to tolerate a node's taint.

ポッドを AKS クラスターにデプロイするときは、容認とテイントが一致している場合にのみ、ノードでポッドがスケジュールされます。When you deploy a pod to an AKS cluster, Kubernetes only schedules pods on nodes where a toleration is aligned with the taint. たとえば、GPU のサポートを備えたノード用のノード プールが AKS クラスターにあると仮定します。As an example, assume you have a node pool in your AKS cluster for nodes with GPU support. gpu などの名前と、スケジュールのための値を定義します。You define name, such as gpu, then a value for scheduling. この値を NoSchedule に設定した場合、ポッドで適切な容認が定義されていない場合、そのノードをポッドにスケジュールすることはできません。If you set this value to NoSchedule, the Kubernetes scheduler can't schedule pods on the node if the pod doesn't define the appropriate toleration.

kubectl taint node aks-nodepool1 sku=gpu:NoSchedule

ノードにテイントを適用したら、そのノードでのスケジュールを許可する容認をポッドの仕様で定義します。With a taint applied to nodes, you then define a toleration in the pod specification that allows scheduling on the nodes. 次の例では、前のステップでノードに適用したテイントを許容するための sku: gpueffect: NoSchedule を定義しています。The following example defines the sku: gpu and effect: NoSchedule to tolerate the taint applied to the node in the previous step:

kind: Pod
apiVersion: v1
metadata:
  name: tf-mnist
spec:
  containers:
  - name: tf-mnist
    image: microsoft/samples-tf-mnist-demo: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 を使用するなどして、このポッドをデプロイすると、テイントが適用されているノードでそのポッドを正常にスケジュールできます。When this pod is deployed, such as using kubectl apply -f gpu-toleration.yaml, Kubernetes can successfully schedule the pod on the nodes with the taint applied. この論理的な分離を使用することで、クラスター内のリソースへのアクセスを制御できます。This logical isolation lets you control access to resources within a cluster.

テイントを適用するときは、アプリケーションの開発者や所有者と協力して、デプロイで必要な容認を定義できるようにします。When you apply taints, work with your application developers and owners to allow them to define the required tolerations in their deployments.

テイントと容認について詳しくは、テイントと容認の適用に関する記事をご覧ください。For more information about taints and tolerations, see applying taints and tolerations.

AKS での複数のノード プールの使用方法の詳細については、AKS でのクラスターの複数のノード プールの作成と管理に関する記事をご覧ください。For more information about how to use multiple node pools in AKS, see Create and manage multiple node pools for a cluster in AKS.

AKS でのテイントと容認の動作Behavior of taints and tolerations in AKS

AKS でノード プールをアップグレードすると、テイントと容認は新しいノードに適用されるときに、次のように設定されたパターンに従います。When you upgrade a node pool in AKS, taints and tolerations follow a set pattern as they're applied to new nodes:

  • 仮想マシン スケール セットを使用する既定のクラスターDefault clusters that use virtual machine scale sets

    • 2 つのノード クラスター node1node2 があると仮定します。Let's assume you have a two-node cluster - node1 and node2. ノード プールをアップグレードします。You upgrade the node pool.
    • 2 つの追加ノード node3node4 が作成されて、それぞれにテイントが渡されます。Two additional nodes are created, node3 and node4, and the taints are passed on respectively.
    • 元の node1node2 は削除されます。The original node1 and node2 are deleted.
  • 仮想マシン スケール セットのサポートがないクラスターClusters without virtual machine scale set support

    • ここでも、2 つのノード クラスター node1node2 があると仮定します。Again, let's assume you have a two-node cluster - node1 and node2. アップグレードすると、追加ノード (node3) が作成されます。When you upgrade, an additional node (node3) is created.
    • node1 のテイントが node3 に適用されて、次に node1 が削除されます。The taints from node1 are applied to node3, then node1 is then deleted.
    • 別の新規ノードが作成されます (前の node1 が削除されたため、名前は node1 になります)、そして node2 のテイントが新しい node1 に適用されます。Another new node is created (named node1, since the previous node1 was deleted), and the node2 taints are applied to the new node1. 次に、node2 が削除されます。Then, node2 is deleted.
    • 要するに、node1node3 になり、node2node1 になります。In essence node1 becomes node3, and node2 becomes node1.

AKS でノード プールをスケーリングするとき、テイントと容認は設計により持ち越されません。When you scale a node pool in AKS, taints and tolerations do not carry over by design.

ノード セレクターとアフィニティを使用してポッドのスケジュールを制御するControl pod scheduling using node selectors and affinity

ベスト プラクティス ガイダンス - ノード セレクター、ノードのアフィニティ、ポッド間のアフィニティを使用して、ノードでのポッドのスケジュールを制御します。Best practice guidance - Control the scheduling of pods on nodes using node selectors, node affinity, or inter-pod affinity. これらの設定を使用すると、Kubernetes のスケジューラは、ノードのハードウェアなどによって、ワークロードを論理的に分離できます。These settings allow the Kubernetes scheduler to logically isolate workloads, such as by hardware in the node.

テイントと容認は、ハード カットオフでリソースを論理的に分離するために使用されます。つまり、ポッドがノードのテイントを許容しない場合、そのポッドはそのノードでスケジュールされません。Taints and tolerations are used to logically isolate resources with a hard cut-off - if the pod doesn't tolerate a node's taint, it isn't scheduled on the node. ノード セレクターを使用するのは別の方法です。An alternate approach is to use node selectors. ローカルにアタッチされた SSD ストレージや大容量のメモリといったことを示すラベルをノードに付けた後、ポッドの仕様でノード セレクターを定義します。You label nodes, such as to indicate locally attached SSD storage or a large amount of memory, and then define in the pod specification a node selector. その後、そのようなノードは一致するノードにスケジュールされます。Kubernetes then schedules those pods on a matching node. 容認とは異なり、一致するノード セレクターのないポッドは、ラベルの付いているノードにスケジュールできます。Unlike tolerations, pods without a matching node selector can be scheduled on labeled nodes. この動作により、ノード上の未使用のリソースを使用できますが、一致するノード セレクターが定義されているポッドが優先されます。This behavior allows unused resources on the nodes to consume, but gives priority to pods that define the matching node selector.

大容量メモリを装備したノードの例を見てみましょう。Let's look at an example of nodes with a high amount of memory. これらのノードでは、大量のメモリを要求するポッドを優先させることができます。These nodes can give preference to pods that request a high amount of memory. リソースがアイドル状態で放置されないように、他のポッドの実行も許可します。To make sure that the resources don't sit idle, they also allow other pods to run.

kubectl label node aks-nodepool1 hardware:highmem

ポッドの仕様に、ノードで設定されているラベルと一致するノード セレクターを定義する nodeSelector プロパティを追加します。A pod specification then adds the nodeSelector property to define a node selector that matches the label set on a node:

kind: Pod
apiVersion: v1
metadata:
  name: tf-mnist
spec:
  containers:
  - name: tf-mnist
    image: microsoft/samples-tf-mnist-demo:gpu
    resources:
      requests:
        cpu: 0.5
        memory: 2Gi
      limits:
        cpu: 4.0
        memory: 16Gi
    nodeSelector:
      hardware: highmem

これらのスケジューラ オプションを使用するときは、アプリケーションの開発者および所有者と協力して、ポッドの仕様を正しく定義できるようにします。When you use these scheduler options, work with your application developers and owners to allow them to correctly define their pod specifications.

ノード セレクターの使用について詳しくは、「Assigning Pods to Nodes」 (ノードへのポッドの割り当て) をご覧ください。For more information about using node selectors, see Assigning Pods to Nodes.

ノード アフィニティNode affinity

ノード セレクターは、特定のノードにポッドを割り当てる基本的な方法です。A node selector is a basic way to assign pods to a given node. "ノード アフィニティ" を使用すると柔軟性が増します。More flexibility is available using node affinity. ノード アフィニティでは、ポッドがノードと一致しない場合の動作を定義します。With node affinity, you define what happens if the pod can't be matched with a node. ポッドがラベル付けされたホストと一致することを、"必須" として指定できます。You can require that Kubernetes scheduler matches a pod with a labeled host. または、一致することが "望ましい" けれども、一致するものがない場合は別のホストでのポッドのスケジュールを許可することもできます。Or, you can prefer a match but allow the pod to be scheduled on a different host if not match is available.

次の例では、ノード アフィニティを requiredDuringSchedulingIgnoredDuringExecution に設定しています。The following example sets the node affinity to requiredDuringSchedulingIgnoredDuringExecution. このアフィニティでは、一致するラベルを持つノードを使用することが要求されます。This affinity requires the Kubernetes schedule to use a node with a matching label. 使用できるノードがない場合、ポッドはスケジュールの継続を待機する必要があります。If no node is available, the pod has to wait for scheduling to continue. 別のノードでポッドをスケジュールできるようにするには、代わりに値を preferredDuringScheduledIgnoreDuringExecution に設定します。To allow the pod to be scheduled on a different node, you can instead set the value to preferredDuringScheduledIgnoreDuringExecution:

kind: Pod
apiVersion: v1
metadata:
  name: tf-mnist
spec:
  containers:
  - name: tf-mnist
    image: microsoft/samples-tf-mnist-demo: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 の部分は、ノードのラベルが変更された場合でも、ポッドをノードから削除してはならないことを示します。The IgnoredDuringExecution part of the setting indicates that if the node labels change, the pod shouldn't be evicted from the node. Kubernetes スケジューラでは、新しくスケジュールされるポッドに対してのみ更新されたノード ラベルが使用され、ノードで既にスケジュールされているポッドには使用されません。The Kubernetes scheduler only uses the updated node labels for new pods being scheduled, not pods already scheduled on the nodes.

詳しくは、「Affinity and anti-affinity」 (アフィニティと非アフィニティ) をご覧ください。For more information, see Affinity and anti-affinity.

ポッド間アフィニティと非アフィニティInter-pod affinity and anti-affinity

Kubernetes スケジューラでワークロードを論理的に分離する最後の方法では、ポッド間アフィニティまたは非アフィニティを使用します。One final approach for the Kubernetes scheduler to logically isolate workloads is using inter-pod affinity or anti-affinity. 設定では、一致するポッドが既にあるノードではポッドをスケジュール "してはならない" こと、またはスケジュール "しなければならない" ことを定義します。The settings define that pods shouldn't be scheduled on a node that has an existing matching pod, or that they should be scheduled. 既定では、Kubernetes スケジューラは、ノードをまたぐレプリカ セットに複数のポッドのスケジュールを試みます。By default, the Kubernetes scheduler tries to schedule multiple pods in a replica set across nodes. この動作に関しては、さらに具体的なルールを定義できます。You can define more specific rules around this behavior.

よい例は、Azure Cache for Redis キャッシュも使用している Web アプリケーションです。A good example is a web application that also uses an Azure Cache for Redis. ポッドの非アフィニティ ルールを使用すると、複数のノードにレプリカを分散させるよう Kubernetes スケジューラに要求できます。You can use pod anti-affinity rules to request that the Kubernetes scheduler distributes replicas across nodes. その後、アフィニティ ルールを使用して、各 Web アプリ コンポーネントが対応するキャッシュと同じホストにスケジュールされるようにすることができます。You can then use affinity rules to make sure that each web app component is scheduled on the same host as a corresponding cache. 複数ノードへのポッドの分散は、次の例のようになります。The distribution of pods across nodes looks like the following example:

ノード 1Node 1 ノード 2Node 2 ノード 3Node 3
webapp-1webapp-1 webapp-2webapp-2 webapp-3webapp-3
cache-1cache-1 cache-2cache-2 cache-3cache-3

この例のデプロイは、ノード セレクターまたはノード アフィニティを使用する場合より複雑です。This example is a more complex deployment than the use of node selectors or node affinity. デプロイでは、Kubernetes スケジューラによるノードでのポッドのスケジュール方法を制御でき、リソースを論理的に分離できます。The deployment gives you control over how Kubernetes schedules pods on nodes and can logically isolate resources. Azure Cache for Redis を使用するこの Web アプリケーションの完全な例については、同じノードへのポッドの併置に関する記事をご覧ください。For a complete example of this web application with Azure Cache for Redis example, see Co-locate pods on the same node.

次の手順Next steps

この記事では、Kubernetes の高度なスケジューラ機能に注目しました。This article focused on advanced Kubernetes scheduler features. AKS でのクラスター操作の詳細については、次のベスト プラクティスを参照してください。For more information about cluster operations in AKS, see the following best practices: