すべてのプロダクト
Search
ドキュメントセンター

Container Service for Kubernetes:ギャングスケジューリングの作業

最終更新日:Dec 14, 2024

Container Service for Kubernetes (ACK) が提供するギャングスケジューリング機能は、新しいkube-schedulerフレームワークの上に開発されています。 ギャングスケジューリングは、相関ポッドのグループが同時にスケジュールされることを保証する。 スケジューリング要件が満たされない場合、どのポッドもスケジューリングされません。 Gangスケジューリングは、All-or-Nothingシナリオでのジョブスケジューリングのソリューションを提供します。 SparkやHadoopジョブなど、すべてのビッグデータコンピューティングジョブのリソースを同時にスケジュールまたは共有する必要がある分散アプリケーションに適しています。 このトピックでは、ギャングスケジューリングを有効にする方法について説明します。

使用上の注意

使用するエラスティックノードプールのリソース容量とノードラベルが、ポッドスケジューリングの要件を満たしていることを確認します。 そうしないと、ポッドがノードプール内のノードにスケジュールされない可能性があります。

前提条件

  • Kubernetes 1.16以降を実行するACK Proクラスターが作成されます。 詳細については、「ACK Proクラスターの作成」をご参照ください。

    重要

    ギャングスケジューリングは、ACK Proクラスターでのみ使用できます。 ACK専用クラスターでギャングスケジューリングを有効にするには、

    チケットを起票してサポートセンターにお問い合わせくださいしてサポートセンターにお問い合わせください。

使用上の注意

Kubernetesは、オンラインサービスオーケストレーションで広く使用されています。 ACKは、オンラインサービスとオフラインジョブの中央管理のプラットフォームとしてKubernetesを使用したいと考えています。 これにより、クラスターのリソース使用率とパフォーマンスが向上します。 ただし、kube-schedulerは特定のオフラインワークロードをKubernetesクラスターに移行できません。 たとえば、ジョブがオールオアナッシングのスケジューリングを必要とする場合、ジョブのすべてのタスクを同時にスケジューリングする必要があります。 一部のタスクのみが開始された場合、開始されたジョブは、残りのすべてのタスクがスケジュールされるまで待機する必要があります。 送信された各ジョブにスケジュールされていないタスクが含まれている場合、送信されたすべてのジョブは保留状態のままで、クラスターはデッドロックになります。 この状況を回避するには、kube-schedulerのギャングスケジューリングを有効にする必要があります。

Gangスケジューリングは、複数の相関するプロセスを並列システム内の異なるプロセッサにスケジューリングし、これらのプロセスを同時に開始するスケジューリングアルゴリズムです。 Gangスケジューリングは、すべての相関プロセスを同時に開始することを目的としています。 これにより、システムが一部のプロセスの開始に失敗しても、プロセスグループがスタックしないようになります。 たとえば、複数のタスクを含むバッチジョブを送信すると、すべてのタスクがスケジュールされるか、スケジュールされません。 オールオアナッシングシナリオでのタスクスケジューリングは、ギャングスケジューリングと呼ばれます。

ACKでは、PodGroupは同時にスケジュールする必要があるポッドのグループです。 オールオアナッシングのスケジューリングが必要なジョブを送信する場合、ポッドにラベルを追加できます。 ラベルには、ジョブが属するPodGroupの名前と、ジョブを実行するためにスケジュールする必要があるタスクの最小数を指定します。 kube-schedulerは、スケジュールする必要のあるタスクの最小数に基づいてタスクをスケジュールします。 タスクは、クラスターリソースが必要な数のタスクをスケジュールするのに十分である場合にのみスケジュールされます。 それ以外の場合、ジョブは保留状態のままです。

ギャングスケジューリングを有効にする方法

  1. ギャングスケジューリングを有効にするには、ポッドにラベルを追加してmin-availablenameを設定します。 このメソッドを使用すると、kube-schedulerは、pod-group.scheduling.sigs.k8s.io /名前ラベルの値の後にという名前のPodGroupを自動的に作成します。 pod-group.scheduling.sigs.k8s.io /名前の値をサブドメイン名に設定する必要があります。 詳細については、「オブジェクト名とID」をご参照ください。

    labels:
        pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu
        pod-group.scheduling.sigs.k8s.io/min-available: "3"
    • name: PodGroupの名前。

    • min-available: ジョブを実行するためにスケジュールする必要があるポッドの最小数。

  2. 次のいずれかの方法を使用して、ギャングスケジューリングを有効にします。 Kubernetes 1.22以降を実行するクラスターでは、kube-schedulerのバージョンは1.xx.xx-aliyun-4.0以降である必要があります。

    • PodGroupを作成し、pod-group.scheduling.sigs.k8s.ioまたはpod-group.scheduling.sigs.k8s.io /名ラベルを使用して、ポッドが属するPodGroupを指定します。 ポッドとPodGroupは同じ名前空間に属している必要があります。

      重要

      バージョン1.31以降、ACKはバージョンscheduling.sigs.k8s.io/v1alphaのPodGroupリソースをサポートしなくなりました。 バージョンscheduling.x-k8s.io/v1alphaのPodGroupリソースのみをサポートします。

      # PodGroup CRD spec
      apiVersion: scheduling.sigs.k8s.io/v1alpha1
      kind: PodGroup
      metadata: 
       name: nginx
      spec: 
       scheduleTimeoutSeconds: 10 
       minMember: 3
      ---
      # Add the pod-group.scheduling.sigs.k8s.io/name label to the pods. 
      labels: 
       pod-group.scheduling.sigs.k8s.io/name: nginx
    • 管理するポッドの設定にmin-availablename annotationsを追加します。 koordinator APIのtotal-numberおよびmodeパラメーターはサポートされていません。

      annotations:  
       gang.scheduling.koordinator.sh/name: "gang-example" 
       gang.scheduling.koordinator.sh/min-available: "2"
説明

同じPodGroupに属するポッドには、同じ優先度を割り当てる必要があります。

高度なギャングスケジューリング設定

制限事項

Kubernetes 1.22以降を実行するクラスターで高度なギャングスケジューリング設定を使用するには、kube-schedulerのバージョンが1.xx.xx-aliyun-4.0以降である必要があります。

GangGroupを宣言する

ギャングスケジューリングを使用する場合、ジョブによっては、min-availableパラメーターの値に対する要件が異なる異なるロールを使用する場合があります。 たとえば、PyTorchトレーニングジョブはパラメータサーバーとワーカーを使用します。 この場合、PodGroupを使用してすべてのロールのポッドを管理すると、異なるロールのmin-availableパラメーターの要件が同時に満たされない場合があります。 ロールに複数のPodGroupsを作成する場合、ロールのポッドを1つのバッチでスケジュールすることはできません。 この問題を解決するには、GangGroup機能を使用して複数のギャングをグループとして管理することを推奨します。 ジョブは、スケジュールされたポッドの数が各ギャングのmin-availableの値に達した場合にのみ実行できます。 これにより、さまざまなロールのmin-availableパラメーターの要件が満たされます。

  • ラベルを使用してギャングスケジューリングを有効にする場合は、ポッドの設定に次のラベルを追加します。

    pod-group.scheduling.sigs.k8s.io/groups: "[\"default/gang-example1\", \"default/gang-example2\"]"
  • PodGroupsを使用してギャングスケジューリングを有効にする場合は、PodGroupsの設定に次のラベルを追加します。

    pod-group.scheduling.sigs.k8s.io/groups: "[\"default/gang-example1\", \"default/gang-example2\"]"
  • アノテーションを使用してギャングスケジューリングを有効にする場合は、ポッドの設定に次のラベルを追加します。

    gang.scheduling.koordinator.sh/groups: "[\"default/gang-example1\", \"default/gang-example2\"]"

マッチポリシーを宣言するDeclare a matchpolicy

ギャングスケジューリングを有効にすると、match-policyを宣言して、PodGroupがポッドをタイプ別にカウントできるようにすることができます。

  • ラベルを使用してギャングスケジューリングを有効にする場合は、ポッドの設定に次のラベルを追加します。

    pod-group.scheduling.sigs.k8s.io/match-policy: "waiting-and-running"
  • PodGroupsを使用してギャングスケジューリングを有効にする場合は、PodGroupsの設定に次のラベルを追加します。

    pod-group.scheduling.sigs.k8s.io/match-policy: "waiting-and-running"
  • アノテーションを使用してギャングスケジューリングを有効にする場合、一度満足した一致方法のみがサポートされます。

次の表では、さまざまな一致方法について説明します。

一致方法

説明

のみ-待っている

リソースの事前割り当てが完了したポッドのみが照合されます。

待機と実行中

実行中状態のポッドと、リソースの事前割り当てが完了したポッドが一致します。

待機-実行-成功

成功状態のポッド、実行状態のポッド、およびリソースの事前割り当てが完了したポッドが一致します。

一度満足

リソースの事前割り当てが完了したポッドのみが照合されます。 ポッドが一致すると、PodGroupは無効になります。

この例では、分散TensorFlowジョブを使用して、ギャングスケジューリングを有効にする方法を示します。 この例で使用されるACKクラスタは、4つのGPUを有する。

  1. Arenaをインストールし、クラスターに環境をデプロイしてTensorFlowジョブを実行します。 詳細については、「アリーナのインストール」をご参照ください。

    説明

    アリーナはKubeflowのサブプロジェクトです。 Kubeflowは、Kubernetesベースの機械学習のためのオープンソースプロジェクトです。 Arenaでは、CLIまたはSDKを使用して、機械学習ジョブのライフサイクルを管理できます。 ライフサイクル管理には、環境セットアップ、データ準備、モデル開発、モデルトレーニング、モデル予測が含まれます。 これにより、データサイエンティストの作業効率が向上します。

  2. 次のテンプレートを使用して、分散TensorFlowジョブをACKクラスターに送信します。 ジョブは、1つのパラメーターサーバー (PS) ポッドと4つのワーカーポッドで実行されます。 各ワーカーポッドには2つのGPUが必要です。

    完全なコンテンツを表示

    apiVersion: "kubeflow.org/v1"
    kind: "TFJob"
    metadata:
      name: "tf-smoke-gpu"
    spec:
      tfReplicaSpecs:
        PS:
          replicas: 1
          template:
            metadata:
              creationTimestamp: null
              labels:
                pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu
                pod-group.scheduling.sigs.k8s.io/min-available: "5"
            spec:
              containers:
              - args:
                - python
                - tf_cnn_benchmarks.py
                - --batch_size=32
                - --model=resnet50
                - --variable_update=parameter_server
                - --flush_stdout=true
                - --num_gpus=1
                - --local_parameter_device=cpu
                - --device=cpu
                - --data_format=NHWC
                image: registry.cn-hangzhou.aliyuncs.com/kubeflow-images-public/tf-benchmarks-cpu:v20171202-bdab599-dirty-284af3
                name: tensorflow
                ports:
                - containerPort: 2222
                  name: tfjob-port
                resources:
                  limits:
                    cpu: '1'
                workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks
              restartPolicy: OnFailure
        Worker:
          replicas: 4
          template:
            metadata:
              creationTimestamp: null
              labels:
                pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu
                pod-group.scheduling.sigs.k8s.io/min-available: "5"
            spec:
              containers:
              - args:
                - python
                - tf_cnn_benchmarks.py
                - --batch_size=32
                - --model=resnet50
                - --variable_update=parameter_server
                - --flush_stdout=true
                - --num_gpus=1
                - --local_parameter_device=cpu
                - --device=gpu
                - --data_format=NHWC
                image: registry.cn-hangzhou.aliyuncs.com/kubeflow-images-public/tf-benchmarks-gpu:v20171202-bdab599-dirty-284af3
                name: tensorflow
                ports:
                - containerPort: 2222
                  name: tfjob-port
                resources:
                  limits:
                    nvidia.com/gpu: 2
                workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks
              restartPolicy: OnFailure
    • ギャングスケジューリングを有効にせずに分散TensorFlowジョブを送信する

      次のコマンドを実行して、TensorFlowジョブを実行するポッドのステータスを照会します。

      kubectl get pods

      出力は、2つのワーカーポッドのみが実行されており、他のワーカーポッドはPending状態であることを示しています。

      NAME                    READY   STATUS    RESTARTS   AGE
      tf-smoke-gpu-ps-0       1/1     Running   0          6m43s
      tf-smoke-gpu-worker-0   1/1     Running   0          6m43s
      tf-smoke-gpu-worker-1   1/1     Running   0          6m43s
      tf-smoke-gpu-worker-2   0/1     Pending   0          6m43s
      tf-smoke-gpu-worker-3   0/1     Pending   0          6m43s

      次のコマンドを実行して、実行中のワーカーポッドのログデータを照会します。

      kubectl logs -f tf-smoke-gpu-worker-0

      返されたログデータは、2つのワーカーポッドが起動され、システムが保留中のワーカーポッドを起動するのを待っていることを示します。 実行中のワーカーポッドによって占有されているGPUリソースは使用されていません。

      INFO|2020-05-19T07:02:18|/opt/launcher.py|27| 2020-05-19 07:02:18.199696: I tensorflow/core/distributed_runtime/master.cc:221] CreateSession still waiting for response from worker: /job:worker/replica:0/task:3
      INFO|2020-05-19T07:02:28|/opt/launcher.py|27| 2020-05-19 07:02:28.199798: I tensorflow/core/distributed_runtime/master.cc:221] CreateSession still waiting for response from worker: /job:worker/replica:0/task:2
    • ギャングスケジューリングを有効にして分散TensorFlowジョブを送信する

      次のコマンドを実行して、TensorFlowジョブを実行するポッドのステータスを照会します。

      kubectl get pods

      クラスター内のコンピューティングリソースが、最小数のポッドをスケジュールするには不十分です。 したがって、PodGroupはスケジュールできず、すべてのポッドはPending状態になります。

      NAME                    READY   STATUS    RESTARTS   AGE
      tf-smoke-gpu-ps-0       0/1     Pending   0          43s
      tf-smoke-gpu-worker-0   0/1     Pending   0          43s
      tf-smoke-gpu-worker-1   0/1     Pending   0          43s
      tf-smoke-gpu-worker-2   0/1     Pending   0          43s
      tf-smoke-gpu-worker-3   0/1     Pending   0          43s

      4つのGPUがクラスターに割り当てられた後、クラスター内のコンピューティングリソースは、最小数のポッドをスケジュールするのに十分です。 PodGroupがスケジュールされると、4つのワーカーポッドの実行が開始されます。 次のコマンドを実行して、TensorFlowジョブを実行するポッドのステータスを照会します。

      kubectl get pods

      期待される出力:

      NAME                    READY   STATUS    RESTARTS   AGE
      tf-smoke-gpu-ps-0       1/1     Running   0          3m16s
      tf-smoke-gpu-worker-0   1/1     Running   0          3m16s
      tf-smoke-gpu-worker-1   1/1     Running   0          3m16s
      tf-smoke-gpu-worker-2   1/1     Running   0          3m16s
      tf-smoke-gpu-worker-3   1/1     Running   0          3m16s

      次のコマンドを実行して、実行中のワーカーポッドのログデータを照会します。

      kubectl logs -f tf-smoke-gpu-worker-0

      次の出力は、トレーニングジョブが開始されたことを示します。

      INFO|2020-05-19T07:15:24|/opt/launcher.py|27| Running warm up
      INFO|2020-05-19T07:21:04|/opt/launcher.py|27| Done warm up
      INFO|2020-05-19T07:21:04|/opt/launcher.py|27| Step  Img/sec loss
      INFO|2020-05-19T07:21:05|/opt/launcher.py|27| 1 images/sec: 31.6 +/- 0.0 (jitter = 0.0) 8.318
      INFO|2020-05-19T07:21:15|/opt/launcher.py|27| 10  images/sec: 31.1 +/- 0.4 (jitter = 0.7) 8.343
      INFO|2020-05-19T07:21:25|/opt/launcher.py|27| 20  images/sec: 31.5 +/- 0.3 (jitter = 0.7) 8.142

エラーメッセージ

  • エラーメッセージ: 「podgroup xxxによって拒否されました」。

  • 考えられる原因: クラスターに複数のPodGroupを作成すると、kube-schedulerのBackOffキューが原因で、PodGroup内のポッドが同時にスケジュールされないことがあります。 この場合、リソースの事前割り当てを完了したポッドは、システムが後続のPodGroupsでポッドをスケジュールするときに拒否される可能性があります。 状況が20分を超えない場合は、エラーを無視できます。 状況が20分以上続く場合、

    チケットを起票してください。

関連ドキュメント

  • kube-schedulerのリリースノートの詳細については、「kube-scheduler」をご参照ください。

  • Kubernetesは、ResourceQuotaオブジェクトを使用してリソースを静的に割り当てます。 この方法では、Kubernetesクラスターのリソース使用率が高くなりません。 ACKクラスターのリソース使用率を向上させるために、Alibaba CloudはYarn容量スケジューラとKubernetesスケジューリングフレームワークに基づく容量スケジューリング機能を開発しました。 この機能は、弾性クォータグループを使用してACKクラスターのリソース要求を満たし、リソースを共有してリソースの使用率を向上させます。 詳細については、「容量スケジューリングの作業」をご参照ください。