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

Container Service for Kubernetes:ACK Lingjun クラスターでのネットワークトポロジー対応スケジューリングの使用

最終更新日:Mar 26, 2026

分散型 AI トレーニングおよびビッグデータワークロードでは、Pod 間の通信が頻繁に行われます。Kubernetes のデフォルトスケジューラは Pod をノード間で均等に分散配置するため、複数のスイッチホップを挟んだ異なるノードに Pod が配置される可能性があります。ホップ数が増えるほどレイテンシが増加し、スループットが低下します。ネットワークトポロジー対応スケジューリングは、ジョブ内のすべての Pod を同一のレイヤー 1 またはレイヤー 2 転送ドメイン内のノードに割り当てることで、スイッチホップを最小限に抑え、ジョブ完了を高速化します。

仕組み

ネットワークトポロジー対応スケジューリングは、貪欲アルゴリズムを使用して、トポロジースパンが最小となる Lingjun ノードにジョブを割り当てます。

ACK Lingjun クラスターには、2 階層のネットワークトポロジー構造があります。

  • アクセススイッチ (ASW):Lingjun ノードへの直接インターフェイスです。同一 ASW 配下のノード間の通信には、少なくとも 1 ホップ必要です。

  • Point of Delivery (PoD):複数の ASW をまとめる上位トポロジー階層です。同一 PoD 内で異なる ASW 配下にあるノード間の通信には、少なくとも 2 ホップ必要です。

ノード間のスイッチ階層が少ないほど、レイテンシは低くなります。スケジューラは、可能な限り低いトポロジーレベル内にすべての Pod を収めるよう試みます。

  • 2 ノードジョブ:同一 ASW 内のノードに割り当てられます(例:ノードペア A-B または E-F)。

  • 4 ノードジョブ:同一 PoD 内のノードに割り当てられます(例:ノードペア A-D または E-H)。

image

ノードラベルにより、各ノードがどの ASW および PoD に属しているかを識別できます。

  • alibabacloud.com/asw-id:ASW を識別します。

  • alibabacloud.com/point-of-delivery:PoD を識別します。

ACK Lingjun クラスターでは、lingjun-networktopology-collector コンポーネントが自動的にこの情報を収集し、Lingjun ノードにこれらのラベルを適用します。その他のノードタイプまたはクラスタータイプでは、手動でラベルを追加し、ラベルキーが labelKey 値と ClusterNetworkTopology 構成で一致していることを確認してください。

スケジューリング戦略

次の 2 つの戦略により、トポロジーレベル内で Pod をどの程度厳密にグループ化するかを制御します。

戦略動作
PreferGather可能な場合はレイヤー内で Pod をグループ化しますが、リソースが不足している場合はクロスレイヤースケジューリングを許可します。
MustGatherすべての Pod を同一レイヤー内に配置することを必須とし、単一レイヤーでジョブを収容できない場合はスケジューリングが失敗します。

前提条件

作業を開始する前に、以下の要件を満たしていることを確認してください。

  • ACK Lingjun クラスター

  • クラスターへの接続用に kubectl が設定済みであること

  • トポロジーラベルが適用された十分なノードがあること

ネットワークトポロジー対応スケジューリングの構成とデプロイ

ネットワークトポロジー対応スケジューリングを構成するには、次の 3 つの YAML ファイルが必要です。クラスター全体のトポロジー構造を定義するファイル、特定のジョブに対するスケジューリング制約を宣言するファイル、およびジョブ自体の定義ファイルです。

ステップ 1:クラスタートポロジーの定義

クラスターの 2 階層トポロジー構造を宣言するための cluster-network-topology.yaml を作成します。

apiVersion: scheduling.koordinator.sh/v1alpha1
kind: ClusterNetworkTopology
metadata:
  # 変更しないでください。
  name: default
spec:
  networkTopologySpec:
  # parentTopologyLayer は上位トポロジー構造を宣言します。
  - parentTopologyLayer: ASWTopologyLayer
  # Lingjun ノードの最下位レベルは必ず NodeTopologyLayer にしてください。
    topologyLayer: NodeTopologyLayer
  # 以下はクロスレイヤートポロジーマッピングを定義します。通常、変更は不要です。
  - labelKey:
    - alibabacloud.com/point-of-delivery
    topologyLayer: PoDTopologyLayer
  - labelKey:
    - alibabacloud.com/asw-id
    parentTopologyLayer: PoDTopologyLayer
    topologyLayer: ASWTopologyLayer

ステップ 2:ジョブのトポロジー制約の宣言

各トポロジーレベルにおけるスケジューリング戦略を指定するための sample-network-topology.yaml を作成します。

apiVersion: scheduling.koordinator.sh/v1alpha1
kind: JobNetworkTopology
metadata:
  labels:
    network-topology-permit-wait-time: "999999"
  # ジョブ名。
  name: sample-network-topology
  # ジョブが属する名前空間。
  namespace: sample-network-topology
spec:
  topologyStrategy:
  # PreferGather:リソースが不足している場合、ASW をまたいだスケジューリングを許可します。
  - layer: ASWTopologyLayer
    strategy: PreferGather
  - layer: NodeTopologyLayer
    strategy: PreferGather
  # MustGather:PoD をまたいだスケジューリングは許可されません。
  - layer: PoDTopologyLayer
    strategy: MustGather
  # Job マニフェストの spec.parallelism および pod-group.scheduling.sigs.k8s.io/min-available と一致させる必要があります。
  workerNum: 2

ステップ 3:ジョブの作成

ジョブを定義し、トポロジー制約を参照するための pi.yaml を作成します。

apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  # JobNetworkTopology の workerNum と一致させる必要があります。
  parallelism: 2
  template:
    metadata:
      labels:
        # JobNetworkTopology の workerNum と一致させる必要があります。
        pod-group.scheduling.sigs.k8s.io/min-available: "2"
        pod-group.scheduling.sigs.k8s.io/name: sample-gang
        # ステップ 2 で作成した JobNetworkTopology を参照します。
        network-topology-job-name: sample-network-topology
        network-topology-job-namespace: sample-network-topology
    spec:
      schedulerName: default-scheduler
      containers:
      - name: pi
        image: perl:5.34.0
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
        resources:
          limits:
            # この例では GPU を 1 枚使用します。必要に応じて調整してください。
            nvidia.com/gpu: 1
      restartPolicy: Never
  backoffLimit: 4

ステップ 4:構成のデプロイ

次のコマンドで、3 つのファイルをクラスターに適用します。

kubectl apply -f cluster-network-topology.yaml
kubectl apply -f sample-network-topology.yaml
kubectl apply -f pi.yaml

スケジューリング結果の確認

クラスタートポロジーの確認

トポロジー構造を確認するため、ノードのトポロジーラベルを取得します。

# ネットワークトポロジー:
#              test-pod-1                     test-pod-2
#        /          |           \                   |
#    test-1      test-2      test-3               test-4
#     /   \         |           |                   |
#   0.12  0.14     0.15        0.16                0.17

kubectl get no -l alibabacloud.com/asw-id,alibabacloud.com/point-of-delivery -ojson | jq '.items[] | {"Name":.metadata.name, "ASW":.metadata.labels."alibabacloud.com/asw-id", "POD":.metadata.labels."alibabacloud.com/point-of-delivery"}'

期待される出力:

{
  "Name": "cn-hongkong.10.1.0.12",
  "ASW": "test-1",
  "POD": "test-pod-1"
}
{
  "Name": "cn-hongkong.10.1.0.14",
  "ASW": "test-1",
  "POD": "test-pod-1"
}
{
  "Name": "cn-hongkong.10.1.0.15",
  "ASW": "test-2",
  "POD": "test-pod-1"
}
{
  "Name": "cn-hongkong.10.1.0.16",
  "ASW": "test-3",
  "POD": "test-pod-1"
}
{
  "Name": "cn-hongkong.10.1.0.17",
  "ASW": "test-4",
  "POD": "test-pod-2"
}

シナリオ 1:2 Pod ジョブ

workerNum: 2 の設定により、両方の Pod が同一 ASW(test-1)内のノードにスケジュールされます。

kubectl get pod -owide
NAME       READY   STATUS              RESTARTS   AGE   IP               NODE                    NOMINATED NODE   READINESS GATES
pi-8p89l   1/1     Running             0          4s    172.30.240.197   cn-hongkong.10.1.0.14   <none>           <none>
pi-p8swv   0/1     ContainerCreating   0          4s    <none>           cn-hongkong.10.1.0.12   <none>           <none>

両方の Pod は test-1(ASW)に配置され、最低ホップ数のネットワークパスを共有します。

シナリオ 2:4 Pod ジョブ

pi.yamlparallelism および pod-group.scheduling.sigs.k8s.io/min-available、ならびに sample-network-topology.yamlworkerNum4 に更新し、両ファイルを再適用します。

PoDTopologyLayer に設定された MustGather により、PoD をまたいだスケジューリングが禁止されるため、スケジューラはすべての 4 つの Pod を test-pod-1 内に割り当てます。test-pod-2 配下のノードはスケジュールされません。

NAME       READY   STATUS              RESTARTS   AGE   IP               NODE                    NOMINATED NODE   READINESS GATES
pi-2kwq9   1/1     Running             0          4s    172.30.241.123   cn-hongkong.10.1.0.12   <none>           <none>
pi-87hm5   0/1     ContainerCreating   0          4s    <none>           cn-hongkong.10.1.0.16   <none>           <none>
pi-bsvx8   1/1     Running             0          4s    172.30.240.198   cn-hongkong.10.1.0.14   <none>           <none>
pi-dvwhl   0/1     ContainerCreating   0          4s    <none>           cn-hongkong.10.1.0.15   <none>           <none>

シナリオ 3:5 Pod ジョブ(スケジューリング失敗)

同様のパラメーターを 5 に更新します。ジョブは失敗します。理由は、test-pod-1 には空きスロットが 4 つしかなく、PoDTopologyLayerMustGather により、test-pod-2 の単一ノードを使用することが禁止されているためです。

すべての Pod は Pending 状態のままになります。

NAME       READY   STATUS    RESTARTS   AGE
pi-75qf5   0/1     Pending   0          2s
pi-8k4nd   0/1     Pending   0          2s
pi-b2pmc   0/1     Pending   0          2s
pi-n7c2b   0/1     Pending   0          2s
pi-wf4zn   0/1     Pending   0          2s

スケジューリング失敗メッセージを確認します。

kubectl get pod -ojson | jq '.items[].status'

スケジューリング失敗メッセージには次のような内容が含まれます。

0/6 nodes are available: 1 Insufficient nvidia.com/gpu, 1 [NetworkTopology begin] cluster total nodes:6, 5 node provide 5 freeSlot, 1 node unavailable cause Insufficient nvidia.com/gpu, job desireNum:5, all fail topology paths by MustGather reason: [path:RootNode->test-pod-1, freeSlotNum:4], [path:RootNode->DefaultTopologyName, freeSlotNum:0], [path:RootNode->test-pod-2, freeSlotNum:1] [NetworkTopology end], 4 NetworkTopology bestPlan empty. network topology job sample-network-topology/sample-network-topology gets rejected due to pod is unschedulable...

メッセージ内の主なフィールド:

フィールド意味
job desireNum5スケジューラは、単一の PoD レベルドメイン内に 5 つのスロットを必要としています。
path:RootNode->test-pod-1, freeSlotNum4test-pod-1 には空きスロットが 4 つしかなく、5 つの Pod を収容できません。
path:RootNode->test-pod-2, freeSlotNum1test-pod-2 には 1 つのスロットがありますが、MustGather により、ジョブを複数の PoD に分割することが禁止されています。
NetworkTopology bestPlan empty有効なトポロジープランが存在せず、スケジューリングがブロックされています。

この問題を解決するには、workerNum を単一の PoD に収まるように減らすか、PoDTopologyLayer の戦略を MustGather から PreferGather に変更して、PoD をまたいだスケジューリングを許可してください。