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

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

最終更新日:Mar 26, 2026

Apache Spark、Apache Hadoop、TensorFlow トレーニングなどの分散ジョブでは、すべての Pod を同時に実行する必要があります。ギャングスケジューリングがない場合、一部の Pod が起動してリソースを確保したまま、残りの Pod を待機するため、どのジョブも進行しないクラスター全体のデッドロックが発生する可能性があります。ギャングスケジューリングは、All-or-Nothing の保証によってこの問題を解決します。つまり、必要なすべての Pod が一括でディスパッチされるか、まったくディスパッチされないかのいずれかになります。このトピックでは、Container Service for Kubernetes (ACK) でギャングスケジューリングを有効にして設定する方法について説明します。

仕組み

ACK は、PodGroup リソースを通じてギャングスケジューリングを実装します。分散ジョブの各 Pod は PodGroup に割り当てられ、最小 Pod 数 (min-available) を指定します。スケジューラは、最小要件を満たすまでグループ全体を Pending 状態に保持します。要件が満たされると、グループ内のすべての Pod が一括でディスパッチされます。

ACK は、PodGroup を定義するために 3 つの方法をサポートしています。

方法Pod のグループ化方法最適なケース
ラベルkube-scheduler が PodGroup を自動的に作成単純なジョブ、個別の PodGroup オブジェクトは不要
PodGroup CRDタイムアウト制御が可能な明示的な PodGroup リソースscheduleTimeoutSeconds
Koordinator アノテーションアノテーションベースのグループ化Koordinator スケジューリングスタックを使用するクラスター

3 つの方法すべてで、Pod とその PodGroup が同じ名前空間にある必要があります。PodGroup 内のすべての Pod は、同じ優先度を共有する必要があります。

前提条件

開始する前に、以下を確認してください。

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

ギャングスケジューリングの有効化

方法 1: ラベル (推奨)

各 Pod に 2 つのラベルを追加します。kube-scheduler は、pod-group.scheduling.sigs.k8s.io/name の値にちなんで名付けられた PodGroup を自動的に作成します。

labels:
  pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu       # PodGroup 名 (有効な DNS サブドメインである必要があります)
  pod-group.scheduling.sigs.k8s.io/min-available: "3"       # ジョブの開始に必要な最小 Pod 数

pod-group.scheduling.sigs.k8s.io/name の値は、有効な DNS サブドメイン名である必要があります。命名規則については、「オブジェクト名と ID」をご参照ください。

方法 2: PodGroup CRD

PodGroup リソースを明示的に作成し、各 Pod からラベルを使用して参照します。

重要

ACK バージョン 1.31 以降、scheduling.x-k8s.io/v1alpha1 API バージョンのみがサポートされています。scheduling.sigs.k8s.io/v1alpha1 バージョンはサポートされなくなりました。

# PodGroup リソース
apiVersion: scheduling.x-k8s.io/v1alpha1
kind: PodGroup
metadata:
  name: nginx
spec:
  scheduleTimeoutSeconds: 10   # min-available が満たされない場合にグループを拒否するまでの待機秒数
  minMember: 3                 # ジョブの開始に必要な最小 Pod 数
---
# Pod ラベル — PodGroup の名前と名前空間に一致する必要があります
labels:
  pod-group.scheduling.sigs.k8s.io/name: nginx

方法 3: Koordinator アノテーション

各 Pod にアノテーションを追加します。この方法は、Koordinator API の total-number または mode パラメーターをサポートしていません。

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

詳細設定

複数のギャングのグループ化 (GangGroup)

一部のジョブでは、パラメータサーバーとワーカーを持つ PyTorch ジョブのように、異なるロールで個別の min-available 要件を使用します。単一の PodGroup ではロールごとの最小要件を表現できず、別々の PodGroup ではロール間のスケジューリングを調整できません。

GangGroup は、複数の PodGroup をリンクすることでこの問題を解決します。ジョブは、グループ内のすべてのギャングが自身の min-available を満たしたときにのみ開始されます。各 Pod または PodGroup に次のラベルを追加します (Koordinator メソッドの場合はアノテーションキーを使用します):

方法リソースキー
ラベルPodpod-group.scheduling.sigs.k8s.io/groups
PodGroup CRDPodGrouppod-group.scheduling.sigs.k8s.io/groups
Koordinator アノテーションPodgang.scheduling.koordinator.sh/groups

値の例 (JSON 配列の <namespace>/<gang-name> エントリ):

pod-group.scheduling.sigs.k8s.io/groups: "[\"default/gang-example1\", \"default/gang-example2\"]"
GangGroup には、Kubernetes 1.22 以降と、1.xx.xx-aliyun-4.0 より新しいバージョンの kube-scheduler が必要です。

マッチポリシーの設定

デフォルトでは、PodGroup はリソースの事前割り当てを完了した Pod のみ (only-waiting) をカウントします。match-policy を使用して、他の状態の Pod を最小カウントに含めることができます。たとえば、以前のスケジューリングサイクルの一部の Pod がまだ実行中であり、最小カウントに含めるべき場合などです。

ラベルを各 Pod (ラベルメソッド) または PodGroup リソース (PodGroup CRD メソッド) に追加します。Koordinator アノテーションメソッドは once-satisfied のみをサポートします。

マッチポリシーmin-available にカウントされる Pod使用するケース
only-waitingリソースの事前割り当てを完了した Pod最も厳格 — 実行中の Pod が新しいスケジューリングサイクルでカウントされるのを防ぎます。以前のサイクルからの持ち越しがないステートレスジョブに使用します。
waiting-and-runningRunning 状態の Pod + 事前割り当てを完了した Pod以前のサイクルの一部の Pod がまだ実行中であり、最小カウントに含めるべき場合に使用します。過度に厳格なカウントによるアイドルリソースの確保のリスクを軽減します。
waiting-running-succeedSucceeded 状態の Pod + Running + 事前割り当てを完了した Pod部分的な再起動を許容するジョブに使用します — すでに成功した Pod もカウントされます。すでに完了した Pod の再スケジューリングを回避します。
once-satisfiedリソースの事前割り当てを完了した Pod。PodGroup は一度満たされると無効になりますワンショットジョブに使用します。ギャングがディスパッチされると、PodGroup は無効になります。

ラベルベースの例:

pod-group.scheduling.sigs.k8s.io/match-policy: "waiting-and-running"

PodGroup CRD の例 (Pod ではなく PodGroup に追加):

pod-group.scheduling.sigs.k8s.io/match-policy: "waiting-and-running"
マッチポリシーの設定には、Kubernetes 1.22 以降と、1.xx.xx-aliyun-4.0 より新しいバージョンの kube-scheduler が必要です。

例: 分散 TensorFlow ジョブ

この例では、ギャングスケジューリングを使用して分散 TensorFlow ジョブを実行する場合と使用しない場合の違いを示します。クラスターには 4 つの GPU があります。ジョブは 1 つのパラメータサーバー (PS) Pod と 4 つのワーカー Pod を実行します。各ワーカーは 2 つの GPU を必要とし、最小 Pod 数は 5 です。

ステップ 1: Arena をインストールし、TensorFlow ジョブを実行できるようにクラスターを準備します。セットアップ手順については、「Arena のインストール」をご参照ください。

Arena は Kubeflow のサブプロジェクトであり、CLI または SDK を通じて、環境設定、データ準備、モデル開発、モデルトレーニング、予測など、機械学習ジョブのライフサイクルを管理します。

ステップ 2: 次のマニフェストを使用して TensorFlow ジョブを送信します。PS とワーカーの両方のテンプレートには、min-available: "5" を持つギャングスケジューリングラベルが含まれています。

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

ギャングスケジューリングを有効にしない場合:

次のコマンドを実行して Pod のステータスを確認します。

kubectl get pods

利用可能な GPU が 4 つしかないため、2 つのワーカー Pod が Running 状態になりすべての GPU を確保し、残りの 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

ログは、ワーカーが Pending 状態の Pod を待機してストールしていることを示しています — 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

ギャングスケジューリングを有効にした場合:

クラスターに min-available: 5 を満たすのに十分なリソースができるまで、5 つの Pod すべてが 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 が追加されると、スケジューラは 5 つの Pod すべてを同時にディスパッチします。

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

トラブルシューティング

エラー:「rejected by podgroup xxx」

クラスター内に複数の PodGroup が存在する場合、kube-scheduler のバックオフキューにより、あるスケジューリングサイクルでリソースの事前割り当てを完了した Pod が、後の PodGroup が処理される際に拒否されることがあります。

これは想定される動作です。この状況が 20 分以上続かない場合は、このエラーを無視できます。エラーが 20 分以上続く場合は、チケットを送信してください。

次のステップ