Dynamic Resource Allocation(DRA)は、KubernetesにおけるGPU共有のためのHAMiプロジェクトを不要にするのではなく、両者の役割分担を変える。DRAがKubernetes v1.34で一般提供に達し、v1.35以降デフォルトで有効になったことで、Kubernetesはデバイスリソースの部分的な割り当て要求をネイティブに理解し、スケジューリングできるようになった。一方、CUDA呼び出し時にコンテナ内でこれらの割り当てを強制することはDRAの役割ではなく、ここでHAMi-coreが引き続き重要な役割を担う。
Mesut Oezdilが執筆したCNCFの記事は、この2つの段階の違いを分析し、HAMiがプロジェクトを放棄するのではなく、DRA上にエコシステムの一部を再構築する方法を説明している。筆者が示す問いは、どちらか一方のプロジェクトがもう一方を置き換えるかどうかではなく、HAMiのどの機能がKubernetesのネイティブ機能によってカバーされるようになったのか、という点である。
GPU共有にはなぜ特別なソリューションが必要だったのか?
KubernetesのDevice Pluginインターフェースは、基本的にデバイスを数える機能しか持っていなかった。nvidia.com/gpu: 1のような従来の要求は、カード全体を予約することを意味し、カードのメモリ8,000メガバイトや計算能力の10%を要求するネイティブな記述方法は存在しなかった。
これに対応するため、HAMiはnvidia.com/gpumemやnvidia.com/gpucoresなどの拡張リソースを使用する。しかし、Kubernetesのデフォルトスケジューラーはこれらの値を意味のない数値として扱う。メモリと計算能力が同じ物理カードから提供される必要があることを理解できず、複数の割り当てが特定のカードの容量を超えるかどうかを単独で判断することもできない。
そのため従来の方式では、要求を変更するwebhook、ノードをフィルタリングしてデバイスIDを選択するスケジューラー拡張、そして決定をannotationに記録する仕組みに依存する。Device Pluginは後からこの決定を読み取り、CUDA_DEVICE_MEMORY_LIMIT_0=8000mやCUDA_DEVICE_SM_LIMIT=10などの制限を注入するとともに、libvgpu.soを事前ロードして制限を強制する。
記事によると、DaoCloudはこの方式で10を超えるデータセンターにわたり、10,000を超えるGPUを稼働させた。しかし、そのアーキテクチャは依然として、HAMiが理解する独自のannotation形式とコンポーネントに結び付いており、これがDRAが解決するために設計されたギャップである。
DRAは何を追加するのか?
DRAはデバイスを数えるモデルを要求モデルに置き換え、resource.k8s.io/v1インターフェースに4つの主要オブジェクトを導入する。
- ResourceSlice:デバイスドライバーが公開し、モデル、メモリ、アーキテクチャを含む各ノードの実際のハードウェアを記述する。
- DeviceClass:CEL式を使用してデバイスのクラスとフィルターを定義する。
- ResourceClaim:ワークロードの所有者が作成し、クラス、セレクター、制約に従ってデバイスを要求する。
- ResourceClaimTemplate:ワークロードの各レプリカ用に個別のクレームを作成する。
スケジューラーはコンテナをバインドする前に、要求に特定のデバイスを割り当てる。その結果はResourceClaimのステータスに構造化されたAPIオブジェクトとして現れる。これにより、決定をkubectlで読み取れるネイティブな場所に置き、RBACで保護し、他のコントローラーがその上に構築できるようになる。annotation内に文字列として保存する必要はない。
しかし、HAMi方式でメモリを共有するには、基本的なDRAだけでは不十分である。ここで重要になる拡張がConsumable Capacityであり、v1.34ではDRAConsumableCapacityゲートの背後で実験的に導入され、v1.36以降は実験的機能としてデフォルトで有効になった。この拡張により、デバイスドライバーはデバイスが複数の割り当てを受け入れられることを公開でき、クレームはメモリや計算能力など、デバイス上の名前付きリソースについて特定量の容量を要求できる。
これにより、HAMiのリソース対応はほぼ直接的になる。gpumemはメモリ容量の要求に、gpucoresは計算容量の要求に変換され、カードに要求された容量がまだ残っているかどうかの計算は、HAMiのスケジューリング拡張からKubernetes自身のスケジューラーへ移行する。
スケジューリングは制限の強制を意味しない
分析では、DRAはスケジューラーが提示した約束を追跡するが、実行中にコンテナがそれを超えることを阻止するわけではないと強調している。CUDA呼び出しはResourceClaimの内容を認識せず、貪欲なワークロードが別のコンテナの犠牲の上に追加のメモリを消費しようとする可能性がある。
この機能を担うのがHAMi-coreであり、Cライブラリlibvgpu.soによってCUDAおよびNVIDIA Management Libraryの呼び出しを傍受し、ユーザー空間から制限を適用する。記事の例によると、2つのコンテナがそれぞれ8,000メガバイトを割り当てられた場合、割り当てを超えたコンテナは上限に達した時点でCUDAのメモリ不足エラーを受け、もう一方のコンテナは動作を継続する。
このソフトウェアによる保護は、敵対的なマルチテナント環境におけるハードウェア分割の代替ではない。ライブラリのプリロードを回避するワークロード、CUDAドライバーへの静的リンクを使用するワークロード、またはCUDA_DISABLE_CONTROLなどの設定を利用するワークロードは、傍受を逃れる可能性がある。筆者は、NVIDIA Multi-Instance GPU(MIG)はハードウェア分離に適している一方、ソフトウェアによる傍受は、固定されたMIGプロファイルと比べて、メモリでは1メガバイト単位、計算能力では1%単位の精度を提供すると述べている。
HAMiはDRA上でどのようにエコシステムを再構築するのか?
新しいアーキテクチャは、異なる役割を担う3つのリポジトリに分かれている。
- k8s-dra-driver:各GPUのメモリと計算能力をResourceSlices内で消費可能な容量として公開し、kubeletプラグインを実行し、CDIを通じてコンテナを接続するとともに、HAMi-coreの強制機能を付加する。
- HAMi-DRA:アドミッション変更webhookとして、従来の拡張リソースを要求から削除して同等のResourceClaimsを作成し、UUIDによるターゲティングとデバイスタイプに関するannotationは維持する。記事によると、HAMi-DRA v0.2.0はHAMi v2.9とともに本番利用可能になり、その後リリース系列はv0.2.1へ移行した。
- HAMi:v2.8からDRAモードをインストールオプションとして文書化しており、監視コンポーネントをデフォルトで有効化し、ポート31995上のPrometheusを通じてコンテナごとのデバイスメトリクスを公開する。
HAMi-DRAの利点の一つは、スケジューリングをクラスターを管理するスケジューラーに任せることにある。これにより、Volcano、KAI Scheduler、その他DRAを理解するスケジューラーを、HAMi専用の統合を追加せずに使用できる。しかし、この決定にはコストもある。HAMi-DRAは独自のスケジューラーを持たないため、NVLinkで接続されたGPUのペアを選ぶといった、トポロジーを考慮した決定は保証されない。
要件と実際の選択
DRAモードには、DRAConsumableCapacityを有効にしたKubernetes v1.34以降が必要である。v1.34およびv1.35では、このゲートは実験的でデフォルトでは無効になっているため、APIサーバーの設定変更を許可しないマネージドサービスでは利用できない可能性がある。v1.36では実験的機能としてデフォルトで有効になった。また、containerdやCRI-Oなど、CDIをサポートし、CDIが有効になっているランタイム、バージョン440以降のNVIDIAドライバー、さらにアクセラレーターの種類に適したDRAドライバーが必要である。
記事では、NVIDIAの方式が最も成熟していると説明しており、AscendとEnflameのサポートが利用可能で、Hygon DCUはk8s-dcu-dra-driverによって文書化されている。一方、従来のHAMiモードはv2.9以降、Cambricon MLUs、Iluvatar、MetaX、Moore Threads、Kunlunxin、AWS Neuron、Vastaiを含む12を超えるデバイスファミリーをカバーしている。そのため、マルチベンダークラスターは、DRAドライバーの対応範囲が拡大するまでは、従来の方式を使い続ける可能性が高い。
同じクラスタ内でDRAモードと従来のDevice Pluginモードを同時に有効にすべきではありません。両方のスケジューリングシステムが、相手のシステムによる予約を認識しないまま、同じ容量を管理しているように動作するためです。筆者の評価によれば、従来モードは、フィーチャーゲートを利用できないマネージドクラスタ、旧バージョン、複数ベンダーのフリートに適しています。一方、Kubernetesのコントロールプレーンを管理するNVIDIAクラスタ、特にv1.36では、既存のデプロイメントファイルを変更せずに済むよう、まずHAMi-DRAからテスト環境でDRAモードを試すことができます。
Consumable Capacityは、Kubernetesにおいて依然として完全には安定していません。また、k8s-dra-driverのHelmチャートは現在も作業中と分類されており、DRA側のベンダー対応範囲は従来モードより狭いままです。記事の結論は、DRAが要求とスケジューリングの言語を担い、HAMi-coreがコンテナ内の実行能力を保持するというものです。つまり、両者の関係は置き換えではなく、統合へと向かっています。