Container Service for Kubernetes(ACK)が提供するギャングスケジューリング機能は、新しい kube-scheduler フレームワーク上に開発されています。ギャングスケジューリングは、関連するポッドのグループが同時にスケジュールされることを保証します。スケジューリング要件が満たされない場合、ポッドはスケジュールされません。ギャングスケジューリングは、All-or-Nothing シナリオでのジョブスケジューリングのソリューションを提供します。 Spark ジョブや Hadoop ジョブなど、すべてのビッグデータコンピューティングジョブのリソースを同時にスケジュールまたは共有することを厳密に要求する分散アプリケーションに適しています。このトピックでは、ギャングスケジューリングを有効にする方法について説明します。
使用上の注意
使用するエラスティックノードプールのリソース容量とノードラベルがポッドスケジューリングの要件を満たしていることを確認してください。そうでない場合、ポッドはノードプール内のノードにスケジュールされない可能性があります。
前提条件
Kubernetes 1.16 以降を実行している ACK マネージド Pro クラスタ が作成されています。必要に応じて、クラスタをスペックアップする ことができます。
使用上の注意
Kubernetes はオンラインサービスのオーケストレーションに優れていますが、ACK はクラスタの利用率と効率を向上させるために、オンラインとオフラインの両方のワークロードに対応する 統合プラットフォーム へと拡張することを目指しています。ただし、デフォルトのスケジューラの制限により、特定のオフラインジョブ、特に all-or-nothing 実行を必要とするジョブが効果的に実行されない場合があります。
これらのシナリオでは、ジョブのすべてのタスクを同時にスケジュールする必要があります。タスクの一部のみが起動された場合、残りのタスクがスケジュールされるのを待機している間、リソースを消費しながらアイドル状態になります。これはリソースの浪費につながり、最悪の場合、ジョブが進行できないクラスタ全体のデッドロックにつながります。これは ギャングスケジューリング が不可欠になる場合です。
ギャングスケジューリングは、事前に定義されたグループ内のすべてのポッドが同時に起動されるようにするポリシーです。 all-or-nothing 原則により、デッドロックを引き起こす部分的な実行の問題を防ぎます。ジョブは、必要なすべてのメンバーに十分なリソースが利用可能になった場合にのみ開始されます。そうでない場合、グループ全体が待機します。
ACK は PodGroup と呼ばれる概念を通じてギャングスケジューリングを実装します。ジョブを送信するときは、ラベル を使用して PodGroup 内のメンバーシップを定義し、ジョブの開始に必要な 最小ポッド数 を指定します。スケジューラは、この最小要件を満たすことができる場合にのみ、ポッドのグループ全体をディスパッチします。それまでは、グループ内のすべてのポッドは pending 状態のままになり、リソースを prematurely 消費することを防ぎます。
ギャングスケジューリングを有効にする方法
ギャングスケジューリングを有効にするには、ポッドに ラベル を追加して、min-available と name を設定します。このメソッドを使用すると、kube-scheduler は
pod-group.scheduling.sigs.k8s.io/nameラベルの値にちなんで名付けられた PodGroup を自動的に作成します。pod-group.scheduling.sigs.k8s.io/nameの値をサブドメイン名に設定する必要があります。詳細については、「オブジェクト名と 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: ジョブを実行するためにスケジュールする必要があるポッドの最小数。
次のいずれかの方法を使用して、ギャングスケジューリングを有効にできます。 Kubernetes 1.22 以降を実行するクラスタでは、kube-scheduler のバージョンは
1.xx.xx-aliyun-4.0以降である必要があります。PodGroup を作成し、
pod-group.scheduling.sigs.k8s.ioまたはpod-group.scheduling.sigs.k8s.io/nameラベルを使用して、ポッドが属する PodGroup を指定します。ポッドと PodGroup は同じ名前空間に属している必要があります。重要バージョン 1.31 以降、ACK はバージョン
scheduling.sigs.k8s.io/v1alpha1の PodGroup リソースをサポートしなくなりました。バージョンscheduling.x-k8s.io/v1alpha1の PodGroup リソースのみをサポートしています。# PodGroup CRD spec apiVersion: scheduling.sigs.k8s.io/v1alpha1 kind: PodGroup metadata: name: nginx spec: scheduleTimeoutSeconds: 10 minMember: 3 --- # ポッドに pod-group.scheduling.sigs.k8s.io/name ラベルを追加します。 labels: pod-group.scheduling.sigs.k8s.io/name: nginx管理するポッドの構成に min-available および name 注釈 を追加します。 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 パラメータの要件が同時に満たされない場合があります。ロールに複数の PodGroup を作成すると、ロールのポッドを 1 つのバッチでスケジュールできません。この問題を解決するには、GangGroup 機能を使用して複数のギャングをグループとして管理することをお勧めします。ジョブは、スケジュールされたポッドの数が各ギャングの min-available の値に達した場合にのみ実行できます。これにより、異なるロールの min-available パラメータの要件が満たされます。
ラベルを使用してギャングスケジューリングを有効にする場合は、ポッドの構成に次のラベルを追加します。
pod-group.scheduling.sigs.k8s.io/groups: "[\"default/gang-example1\", \"default/gang-example2\"]"PodGroup を使用してギャングスケジューリングを有効にする場合は、PodGroup の構成に次のラベルを追加します。
pod-group.scheduling.sigs.k8s.io/groups: "[\"default/gang-example1\", \"default/gang-example2\"]"注釈を使用してギャングスケジューリングを有効にする場合は、ポッドの構成に次のラベルを追加します。
gang.scheduling.koordinator.sh/groups: "[\"default/gang-example1\", \"default/gang-example2\"]"
matchpolicy を宣言する
ギャングスケジューリングを有効にすると、match-policy を宣言して、PodGroup がポッドをタイプ別にカウントできるようにすることができます。
ラベルを使用してギャングスケジューリングを有効にする場合は、ポッドの構成に次のラベルを追加します。
pod-group.scheduling.sigs.k8s.io/match-policy: "waiting-and-running"PodGroup を使用してギャングスケジューリングを有効にする場合は、PodGroup の構成に次のラベルを追加します。
pod-group.scheduling.sigs.k8s.io/match-policy: "waiting-and-running"注釈を使用してギャングスケジューリングを有効にする場合は、
once-satisfied一致メソッドのみがサポートされます。
次の表に、さまざまな一致メソッドを示します。
一致メソッド | 説明 |
only-waiting | リソースの事前割り当てが完了したポッドのみが一致します。 |
waiting-and-running | 実行中状態のポッドとリソースの事前割り当てが完了したポッドが一致します。 |
waiting-running-succeed | 成功状態のポッド、実行中状態のポッド、およびリソースの事前割り当てが完了したポッドが一致します。 |
once-satisfied | リソースの事前割り当てが完了したポッドのみが一致します。ポッドが一致すると、PodGroup は無効になります。 |
例
この例では、分散 TensorFlow ジョブを使用して、ギャングスケジューリングを有効にする方法を示します。この例で使用される ACK クラスタには、4 つの GPU があります。
Arena をインストールし、TensorFlow ジョブを実行するための環境をクラスタにデプロイします。詳細については、「Arena のインストール」をご参照ください。
説明Arena は Kubeflow のサブプロジェクトです。 Kubeflow は、Kubernetes ベースの機械学習のためのオープンソースプロジェクトです。 Arena を使用すると、CLI または SDK を使用して機械学習ジョブのライフサイクルを管理できます。ライフサイクル管理には、環境設定、データ準備、モデル開発、モデルトレーニング、モデル予測が含まれます。これにより、データサイエンティストの作業効率が向上します。
次のテンプレートを使用して、分散 TensorFlow ジョブを ACK クラスタに送信します。ジョブは、1 つのパラメータサーバー(PS)ポッドと 4 つのワーカーポッドで実行されます。各ワーカーポッドには 2 つの GPU が必要です。
ギャングスケジューリングを有効にせずに分散 TensorFlow ジョブを送信する
次のコマンドを実行して、TensorFlow ジョブを実行するポッドのステータスをクエリします。
kubectl get pods出力は、2 つのワーカーポッドのみが実行中で、他のワーカーポッドは保留中状態であることを示しています。
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 をスケジュールできず、すべてのポッドは保留中状態です。
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 43s4 つの 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 内のポッドが同時にスケジュールされない場合があります。この場合、リソースの事前割り当てが完了したポッドは、システムが後続の PodGroup 内のポッドをスケジュールするときに拒否される可能性があります。状況が 20 分以内であれば、エラーを無視できます。状況が 20 分以上続く場合は、チケットを送信 してください。
参考資料
kube-scheduler のリリースノートの詳細については、「kube-scheduler」をご参照ください。
Kubernetes は ResourceQuota オブジェクトを使用してリソースを静的に割り当てます。このメソッドでは、Kubernetes クラスタでの高いリソース使用率は保証されません。 ACK クラスタのリソース使用率を向上させるために、Alibaba Cloud は Yarn 容量スケジューラと Kubernetes スケジューリングフレームワークに基づいて容量スケジューリング機能を開発しました。この機能は、エラスティッククォータグループを使用して ACK クラスタ内のリソースリクエストを満たし、リソースを共有してリソース使用率を向上させます。詳細については、「容量スケジューリングの操作」をご参照ください。