0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Slinky・Slurm・Kubernetesハイブリッドで実現するAIクラスタのジョブスケジューリング最適化

0
Last updated at Posted at 2026-05-10

Slinky・Slurm・Kubernetesハイブリッドで実現するAIクラスタのジョブスケジューリング最適化

この記事でわかること

  • Slinkyプロジェクト(slurm-operator / slurm-bridge)の2コンポーネント構成とそれぞれの役割
  • SlurmのHPCスケジューリングとKubernetesのコンテナオーケストレーションを1つのクラスタで共存させるアーキテクチャ
  • Kueue・Volcano・Slinkyの3スケジューラのベンチマーク比較と使い分け基準
  • NVIDIAの本番環境で8,000超GPUに対応した運用パターンと落とし穴
  • GPU利用効率を下げずにSlurm/K8sワークロードを動的に切り替える設計手法

対象読者

  • 想定読者: MLエンジニア・インフラエンジニアでGPUクラスタの運用に携わっている方
  • 必要な前提知識:
    • Kubernetesの基本概念(Pod、Deployment、CRD)の理解
    • kubectl コマンドの基本操作
    • GPUを使った学習・推論ジョブの運用経験(Slurm未経験でもOK)

結論・成果

SlurmとKubernetesのハイブリッド構成は、2025〜2026年にかけてSlinkyプロジェクト(SchedMD/NVIDIA)とSUNK(CoreWeave)の2つのアプローチで急速に実用段階に入りました。NVIDIAの報告によると、Slinky slurm-operatorは本番環境で8,000超GPUにスケールし、NCCLベンチマーク(all-reduce / all-gather)で非コンテナ化Slurmと同等の性能を達成しています。一方、このハイブリッド構成には「ノード予約によるGPU利用効率低下」という固有の課題があり、設計段階での対策が不可欠です。

SlurmとKubernetesを統合する背景を理解する

なぜ「どちらか一方」では不十分なのか

AIクラスタの運用では、大規模分散学習と推論サービングという根本的に異なる2つのワークロードが同じGPUプールを取り合います。Slurmは2003年の誕生以来、HPC向けバッチスケジューリングの標準として「gang scheduling」(必要な全リソースを一括確保してからジョブを開始する方式)をデフォルト動作で提供してきました。一方、Kubernetesは2014年にGoogleで生まれ、ステートレスなマイクロサービスの水平スケーリングに最適化されています。

この設計思想の違いが実務上の問題を生みます。Kubernetesのデフォルトスケジューラにはgang schedulingが存在しません。70Bパラメータのモデルを64 GPUで分散学習する場合、63 GPUだけ確保できても残り1 GPUが来るまでジョブは開始できず、確保済みのGPUが無駄になります。これが「partial allocation deadlock」と呼ばれる問題です。

逆にSlurmには、推論サービングの常時稼働・オートスケールが苦手という弱点があります。SkyPilotのブログでは、Slurmでの推論サービングを「awkward(不自然)」と表現しており、Kubernetesのエコシステム(Kubeflow、KServe、Istio等)と比べるとサービングの運用ツールが不足しています。

よくある間違い: 「Slurmは古いからKubernetesに移行すればよい」と考えがちですが、Kubernetesでgang schedulingを実現するにはVolcanoやKueueといった追加プラグインが必要です。また、Kubernetesのジョブ定義YAMLは、同等のSlurmバッチスクリプトと比べて3倍以上の記述量になるという報告もあります。

Slinkyプロジェクトの全体像

SchedMD(Slurmの開発元)とNVIDIAが共同開発するSlinkyプロジェクトは、この2つの世界を橋渡しするオープンソースツールセットです。Slinkyは以下の2つのコンポーネントで構成されます。

コンポーネント リリース 機能 ユースケース
slurm-operator 2024年11月(v0.1.0) Slurm on K8s: Slurmクラスタ全体をK8s上で運用 既存SlurmワークロードのK8s移行
slurm-bridge 2025年6月(v1.0.0) Slurm as K8s Scheduler: K8s PodをSlurmでスケジュール K8s/Slurmワークロードの共存

この2つは排他的ではなく、組み合わせて使用可能です。slurm-operatorでSlurmクラスタをK8s上に構築し、slurm-bridgeで通常のK8s PodもSlurmスケジューラに統合する、という構成が推奨パターンです。

slurm-operatorでSlurmクラスタをKubernetes上に構築する

CRDベースのアーキテクチャ

slurm-operatorは、Slurmの各デーモンをKubernetesのCustom Resource Definition(CRD)として定義します。Pythonの__init__のようにオブジェクトの初期化を宣言的に定義するのと同じ発想で、Slurmクラスタの構成をYAMLで宣言的に記述できます。

Slurmの4つのコアコンポーネントがそれぞれCRDとしてマッピングされます。

# slurm-cluster.yaml - Slurmクラスタの宣言的定義(例)
# 実際のCRDスキーマはSlinky公式ドキュメントを参照
apiVersion: slinky.slurm.net/v1alpha1
kind: SlurmCluster
metadata:
  name: ai-training-cluster
  namespace: slurm-system
spec:
  slurmctld:
    replicas: 2          # HA構成
    image: ghcr.io/slinkyproject/slurmctld:25.05
  slurmdbd:
    replicas: 1
    image: ghcr.io/slinkyproject/slurmdbd:25.05
    storage:
      size: 100Gi        # アカウンティングDB用
  slurmd:
    replicas: 64          # GPU計算ノード数
    image: ghcr.io/slinkyproject/slurmd:25.05
    resources:
      limits:
        nvidia.com/gpu: 8 # ノードあたり8 GPU
  slurmrestd:
    replicas: 2
    image: ghcr.io/slinkyproject/slurmrestd:25.05

なぜCRDベースの設計を選んだか:

  • 宣言的管理: kubectl apply 一発でクラスタ構成を適用。手動でのデーモン起動が不要
  • 自己修復: Podがクラッシュしても、Operatorが自動で再生成(PodDisruptionBudgetで実行中ジョブを保護)
  • ローリングアップデート: Slurm設定変更時にダウンタイムゼロで反映

注意: slurm-operatorは現時点で「1ワーカーPod = 1物理ノード」の前提で動作します。1ノードに複数のslurmd Podを配置する構成はサポートされていません。DaemonSet-styleスケーリング(v1.1.0〜)を使うことで、ノード追加時に自動でslurmd Podが起動します。

本番運用で確認された性能

NVIDIAの本番環境での報告によると、slurm-operatorは以下の実績を示しています。

指標 結果 条件
スケール上限 8,000超GPU 複数クラスタ構成
NCCL all-reduce性能 非コンテナ同等 性能差測定不能レベル
NCCL all-gather性能 非コンテナ同等 K8sレイヤのオーバーヘッドなし
ローリングアップデート ダウンタイムゼロ PodDisruptionBudget使用

出典: Running Large-Scale GPU Workloads on Kubernetes with Slurm | NVIDIA Technical Blog

制約条件: これらの数値はNVIDIAの大規模環境(DGX/HGX系ハードウェア、高速インターコネクト)での結果です。一般的なクラウドGPUインスタンス(例: AWS p4d.24xlarge)では、ネットワーク帯域の違いにより異なる結果になる可能性があります。

ハイブリッド構成: ベアメタルslurmdの統合

slurm-operatorの特徴的な機能の1つが、ベアメタルのslurmdノードをK8s上のSlurmクラスタに参加させる「ハイブリッド構成」です。これにより、既存のオンプレミスGPUサーバーを維持しながら、管理プレーン(slurmctld)だけをK8sに移行する段階的な移行が可能になります。

この構成では、slurmctldがK8s内のslurmd PodとオンプレミスのベアメタルslurmdをSlurmの統一的なビュー(パーティション)で管理します。ユーザーは srunsbatch を通常通り使用でき、ジョブが物理マシンとコンテナのどちらで動いているかを意識する必要がありません。

slurm-bridgeでKubernetesワークロードをSlurmスケジューラに統合する

Scheduling Pluginとしてのslurm-bridge

slurm-bridgeは、KubernetesのScheduling FrameworkにSlurmをプラグインとして組み込むコンポーネントです。2025年6月にSlurm 25.05と同時にリリースされ、通常のKubernetes Podに対してSlurmのスケジューリングアルゴリズム(Backfill、Fair Share、Preemption等)を適用できます。

通常のK8sスケジューラとslurm-bridgeの動作の違いを見てみましょう。

# 通常のK8s Pod(デフォルトスケジューラ)
apiVersion: v1
kind: Pod
metadata:
  name: training-job
spec:
  schedulerName: default-scheduler  # K8sデフォルト
  containers:
  - name: train
    image: nvcr.io/nvidia/pytorch:24.05-py3
    resources:
      limits:
        nvidia.com/gpu: 8
# slurm-bridgeを使うPod
apiVersion: v1
kind: Pod
metadata:
  name: training-job
  labels:
    slurm.schedmd.com/partition: "gpu-a100"
    slurm.schedmd.com/qos: "high"
    slurm.schedmd.com/gres: "gpu:8"
spec:
  schedulerName: slurm-bridge  # Slurmスケジューラを指定
  containers:
  - name: train
    image: nvcr.io/nvidia/pytorch:24.05-py3
    resources:
      limits:
        nvidia.com/gpu: 8

ポイント: schedulerNameslurm-bridge に変更し、Slurm固有のラベル(partition、QoS、GRES)を付与するだけで、そのPodはSlurmのスケジューリングキューに入ります。既存のK8sワークロード(推論サービス等)は default-scheduler のまま維持できるため、段階的な導入が可能です。

Converged Clusterの実現

slurm-bridgeの真価は、1つのハードウェアプールでSlurmジョブとK8s Podを混在させる「Converged Cluster」を実現できる点です。これにより、学習ジョブ(Slurm管理)と推論サービス(K8s管理)が同じGPUノード群を共有し、時間帯やワークロードの変動に応じて動的にリソースを割り当てできます。

トレードオフ: Converged Clusterでは、SlurmがノードをDRAIN状態にしてからK8sに返却するまでの「遷移時間」が発生します。この間GPUは非生産的な状態になるため、頻繁にワークロードタイプが切り替わる環境では、専用ノードプールを分離する方が効率的な場合があります。

Kueue・Volcano・Slinkyの3スケジューラを比較する

ベンチマーク結果の概要

Kubernetesでバッチスケジューリングを実現する方法は、Slinky以外にもKueue(Google主導)とVolcano(CNCF Incubating)が存在します。Radiantのベンチマークでは、模擬GPUジョブ(nvidia/cuda:12.4.0ベース)を使って3つのスケジューラを比較しています。

評価項目 Kueue Volcano Slinky
設計思想 K8sネイティブキューイング HPC向けバッチスケジューラ Slurm互換スケジューリング
優先度制御の効果 66秒短縮 63秒短縮 60秒短縮
プリエンプション速度 約1秒 約35秒(クロスキュー) 1秒未満(QoS経由)
障害復旧時間 Pass 約4秒 Pass
導入の容易さ 低〜中 高(Slurm知識必要)
Gang Scheduling v0.10+でサポート ネイティブサポート Slurm標準動作

出典: Benchmarking Kueue, Volcano, and Slinky on Radiant

3スケジューラの使い分け基準

それぞれのスケジューラには明確な適用領域があります。チーム構成とワークロード特性に基づいて選定してみましょう。

Kueueが適するケース:

  • Kubernetesネイティブなチームで、追加のスケジューラを導入したくない
  • CPU/GPUバッチジョブが混在し、軽量なキューイングレイヤが欲しい
  • デフォルトのkube-schedulerをそのまま活かしたい(Kueueはジョブの「入場管理」のみを担当し、Pod配置はkube-schedulerに委譲)

Volcanoが適するケース:

  • MPI/Horovodベースの分散学習が主ワークロード
  • ネットワークトポロジを考慮したGPU配置が必要
  • Slurmの経験はないが、HPC的なバッチスケジューリングが必要

Slinkyが適するケース:

  • 既存のSlurmクラスタ・ワークフローをKubernetesに移行したい
  • Slurmのsbatch/srunに慣れた研究者チームがいる
  • 1秒未満のプリエンプション(QoS経由)が必要な優先度管理

注意: Slinkyの導入にはSlurm自体の知識(パーティション設計、QoS設定、Fair Share設定等)が前提となります。Slurm未経験のチームがSlinkyから始めるのは学習コストが高く、Kueueから導入して段階的にSlinkyに移行する方が現実的です。

用語の違いに注意: 「Gang Scheduling」の意味

SlurmとKubernetesコミュニティでは「gang scheduling」の定義が異なります。この用語の混乱はアーキテクチャ設計の議論で頻繁に問題を引き起こすため、ここで整理します。

コミュニティ 「Gang Scheduling」の意味
Kubernetes 必要な全リソースを一括確保してからジョブを開始する(Slurmではデフォルト動作
Slurm 複数ジョブがリソースを時分割で共有する方式

SkyPilotのブログでは、「Kubernetesが『gang scheduling』と呼んでいるもの(一括リソース確保)は、Slurmのデフォルトのスケジューリング動作に過ぎない」と指摘しています。この違いを理解していないと、Volcanoの「gang scheduling対応」とSlurmの「gang scheduling対応」を同じ機能だと誤解するリスクがあります。

出典: Slurm vs K8s for AI Infra | SkyPilot Blog

SUNK(CoreWeave)との違いを理解する

SUNKの独自アーキテクチャ

SlinkyがSchedMD/NVIDIA主導であるのに対し、SUNK(Slurm on Kubernetes) はCoreWeaveが独自に開発したSlurm/K8s統合ソリューションです。SUNKは以下の3コンポーネントで構成されます。

コンポーネント 役割
Nodeset CRD Slurmノードを定義するCRD。K8sノードと1:1マッピング。ノードの準備状態、ドレイン条件、Slurm状態同期を管理
Syncer Slurm REST APIを通じた双方向の状態同期。効率的なキャッシュで大規模クラスタに対応
Scheduler カスタムK8sスケジューラ。SlurmジョブとK8s Podの混在スケジューリングを実現

出典: A Slurm on Kubernetes Implementation | CoreWeave

SlinkyとSUNKの選定基準

2つのソリューションは目的が近いものの、設計哲学が異なります。

観点 Slinky SUNK
開発元 SchedMD / NVIDIA CoreWeave
ライセンス OSS(Apache 2.0) CoreWeave環境専用
アーキテクチャ Operator + Bridge の2段構成 Nodeset + Syncer + Scheduler の3段構成
対応環境 AWS EKS、OpenShift、汎用K8s CoreWeaveプラットフォーム
ベアメタル統合 slurmd ハイブリッド対応 K8s内完結
適用シーン マルチクラウド・オンプレミス混在 CoreWeave利用者

ハマりポイント: SUNKはCoreWeaveのプラットフォームに最適化されているため、他のクラウド環境やオンプレミスに移植するのは困難です。マルチクラウドやオンプレミス混在環境では、Slinkyを選択するのが安全です。

GPU利用効率を最大化する運用パターンを設計する

ノード予約問題と対策

Slurm-on-K8sのハイブリッド構成で最も注意すべきは、ノード予約によるGPU利用効率の低下です。SkyPilotの分析では、Slurm-on-K8s実装が「Slurmプロセス用にK8sノードを丸ごと予約してしまい、Slurmジョブが走っていなくてもGPUが遊んでしまう」リスクを指摘しています。

この問題への対策を3つのレベルで整理します。

# 対策レベル1: パーティション分離(最もシンプル)
# slurm.conf の設定例
SLURM_PARTITION_CONFIG = """
# 学習専用パーティション(Slurm管理)
PartitionName=train
    Nodes=gpu-node[001-032]
    Default=YES
    MaxTime=72:00:00
    State=UP

# 推論専用パーティション(K8s管理、slurm-bridge経由)
PartitionName=inference
    Nodes=gpu-node[033-048]
    MaxTime=UNLIMITED
    State=UP

# 共有パーティション(時間帯で切り替え)
PartitionName=shared
    Nodes=gpu-node[049-064]
    MaxTime=24:00:00
    State=UP
    PreemptMode=REQUEUE  # 推論Podに割り込まれたらリキュー
"""
# 対策レベル2: オートスケーリング連携
# Slinky slurm-operator + Kubernetes Cluster Autoscaler

# K8s Cluster Autoscalerの設定例
AUTOSCALER_CONFIG = {
    "scaleDown": {
        "enabled": True,
        "delayAfterAdd": "10m",
        "unneededTime": "5m",
    },
    "nodeGroups": [
        {
            "name": "gpu-a100-pool",
            "minSize": 8,    # 最小8ノード(常時稼働)
            "maxSize": 64,   # 最大64ノード(バースト対応)
            "instanceType": "p4d.24xlarge",
        }
    ],
}

# slurm-operatorのautoscaling設定
# ワークロードの増減に応じてslurmd Podを自動スケール
# drain-before-terminate でジョブ安全に終了後にスケールイン
# 対策レベル3: QoSベースの優先度管理
# slurm.conf の QoS設定例

QOS_CONFIG = """
# 高優先度: 大規模学習ジョブ(プリエンプション権限あり)
# sacctmgr add qos high_priority Priority=1000 Preempt=low_priority

# 低優先度: 実験・探索ジョブ(プリエンプトされうる)
# sacctmgr add qos low_priority Priority=100 PreemptMode=requeue

# 推論: 常時稼働(プリエンプトされない)
# sacctmgr add qos inference Priority=500 Preempt= PreemptMode=off
"""

Prometheus/Grafanaによる統合監視

Slurm-on-K8s環境では、SlurmメトリクスとKubernetesメトリクスの統合監視が運用の鍵になります。slurm-operatorはPrometheusメトリクスエクスポーターを内蔵しており、以下のようなメトリクスを公開します。

メトリクス 説明 用途
slurm_jobs_pending 待機中ジョブ数 キュー詰まりの検知
slurm_jobs_running 実行中ジョブ数 クラスタ使用率の把握
slurm_nodes_idle アイドルノード数 スケールダウン判断
slurm_scheduler_latency_seconds スケジューリング遅延 スケジューラの健全性
slurm_partition_gpu_utilization パーティション別GPU使用率 リソース配分の最適化

これらをKubernetesの標準メトリクス(kube_pod_status_phasenode_gpu_utilization 等)と同じGrafanaダッシュボードに統合することで、「Slurmジョブが詰まっているのにK8s側のGPUノードが遊んでいる」といった非効率を即座に検知できます。

# prometheus-slurm-exporter の ServiceMonitor設定例
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: slurm-metrics
  namespace: slurm-system
spec:
  selector:
    matchLabels:
      app: slurm-exporter
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics

よくある問題と解決方法

問題 原因 解決方法
slurmd PodがCrashLoopBackOff Slurm設定ファイルの不整合 ConfigMapのslurm.confを確認。SlurmctldParameters=enable_configlessが有効か確認
ジョブ投入後にPendingのまま進まない パーティションのノード数不足 or GRES設定ミス scontrol show partitionscontrol show node でリソース状態を確認
NCCLテストで性能低下 Pod間のネットワーク設定不備 hostNetworkモード or Multus CNIでRDMA/GPUDirectを有効化
slurm-bridgeでPodがスケジュールされない schedulerNameの指定漏れ Pod spec に schedulerName: slurm-bridge を明示
スケールイン時にジョブが中断 PodDisruptionBudget未設定 minAvailable を設定し、実行中ジョブのあるノードを保護
Slurmアカウンティングが記録されない slurmdbd Podのストレージ不足 PersistentVolumeClaimのサイズを拡大。定期的なsacctmgrでのパージを設定

まとめと次のステップ

まとめ:

  • Slinkyプロジェクトはslurm-operator(Slurm on K8s)とslurm-bridge(Slurm as K8s Scheduler)の2コンポーネントで構成され、NVIDIAの本番環境で8,000超GPUの実績がある
  • 3スケジューラの使い分け: K8sネイティブならKueue、HPC/MPIならVolcano、Slurm移行ならSlinky。プリエンプション速度ではSlinkyが1秒未満で最速
  • GPU利用効率の最大化にはパーティション分離、オートスケーリング連携、QoSベースの優先度管理の3段階の対策が有効
  • ハイブリッド構成(ベアメタルslurmd + K8s上slurmd)により、既存環境を維持しながらの段階的移行が可能

次にやるべきこと:

  1. Slinky公式ドキュメントのQuick Startで、ローカルKindクラスタ上にslurm-operatorを試す
  2. チームのワークロード特性(学習/推論の比率、ジョブサイズ分布)を整理し、パーティション設計を検討する
  3. 既存のSlurm環境がある場合は、slurmctldだけをK8sに移行するハイブリッド構成から始める

参考


注意: この記事はAI(Claude Code)により自動生成されました。内容の正確性については複数の情報源で検証していますが、実際の利用時は公式ドキュメントもご確認ください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?