TT Lab
はじめる
学ぶ 学習パス コース

GPU Operatorとタイムスライシング

なぜGPU Operatorが生まれたのか

TT Labで続きを見る

一言でいうと

GPU OperatorはGPUを速くしてくれる製品ではありません。ノードごとに手作業で行っていた5、6種類のインストールを、クラスターオブジェクト1枚に移したものであり、その便利さの代償として、ノードのコンテナランタイムの設定をオペレーターが代わりに書き換えることになります。

なぜ必要なのか

GPUノード1台を「使える状態」にする手順は、以前はこうでした。

  1. カーネルヘッダーを合わせてインストールし、ドライバーをビルドして読み込みます。失敗したら、カーネルのバージョンから見直します。
  2. nvidia-container-toolkitをインストールします。
  3. containerdの設定に、nvidiaランタイムハンドラーを登録します。
  4. containerdを再起動します。
  5. nvidia-device-pluginを起動して、GPUをリソースとしてアドバタイズさせます。
  6. dcgm-exporterを起動して、使用率を収集します。

ノード1台に30分かかり、7台なら1日が終わります。問題は時間ではなく、ドリフトです。3月に作ったノードはドライバー535、8月に追加したノードは550です。カーネルの自動更新が走ると、そのノードだけドライバーが壊れます。人が繰り返す手順は必ずばらつき、ばらついたクラスターは「なぜあのノードだけ動かないのか」という質問を毎週生みます。

GPU Operatorは、この手順を丸ごと望ましい状態の宣言に置き換えます。ClusterPolicyというカスタムリソースを1枚書くと、オペレーターが必要なDaemonSetを立ち上げ、ノードが新しく入ってくれば、自動で同じ手順を実行します。ノードを作り直しても結果が同じになること。それがこのオペレーターが売る唯一の商品です。

どう動くのか

ClusterPolicy1つの下に、複数のDaemonSetが立ち上がります。それぞれが、上の手順の1段階を受け持ちます。

DaemonSet 役割 ない場合に起きる症状
nvidia-driver-daemonset ドライバーをコンテナ内でビルドして読み込みます nvidia-smi自体がありません
nvidia-container-toolkit-daemonset ノードのcontainerdの設定に、ランタイムハンドラーを登録します PodがRuntimeHandlerエラーで作成に失敗します
nvidia-device-plugin-daemonset ノードのstatusにnvidia.com/gpuをアドバタイズします PodがいつまでもPendingになります
gpu-feature-discovery GPUのモデルとメモリをノードのラベルにします スケジューリング条件をラベルで書けません
nvidia-dcgm-exporter 使用率・温度・ECCのメトリクスを公開します 誰がGPUを使っているのかわかりません

ここには、順序の依存があります。ドライバーの準備ができる前にtoolkitが起動しても意味がなく、toolkitがランタイムを登録する前にdevice pluginがGPUをアドバタイズすると、スケジューラーはPodを送ってくるのに、ノードはそのPodを作れません。そのためオペレーターは、ノードのラベル(nvidia.com/gpu.deploy.*)で各段階をゲーティングします。人が順序を覚えていなくてもよいようにした仕組みです。

そしてここで、必ず押さえておくべき事実が1つあります。2つ目のDaemonSetは、ノードの/etc/containerd/を直接書き換えます。クラスター内のオブジェクトを作るのではなく、ホストのファイルシステムに書き込みます。このコースの残り半分は、すべてこの一文から出てきた話です。

現場での姿

第一に、ドライバーはたいていノードに事前にインストールします。driver.enabled=falseにして、OSイメージにドライバーを焼き込んでおく組織が多くあります。コンテナ内でドライバーをビルドする方式は、カーネルが更新されるたびに、ノードが数分間GPUなしで動く区間を作りますし、エアギャップ環境ではヘッダーパッケージの取得から行き詰まります。そうなると、GPU Operatorが行う作業は、実質的に「toolkit + device plugin + メトリクス」の3つに減ります。

第二に、バージョンマトリクスが本当の制約です。ドライバー・CUDA・toolkit・オペレーター・Kubernetesが、それぞれ互いのサポート範囲を持っています。オペレーターを更新することは、その5つを一度に動かすことなので、他のアップグレードと同じ作業ウィンドウに入れると、原因を切り分けられません。

第三に、監査の観点では、このオペレーターは特権ソフトウェアです。ノードのファイルシステムに書き込み、ホストのPIDネームスペースを見て、カーネルモジュールを読み込みます。「Kubernetesの上で動くPodだから分離されている」という直感は、ここでは通用しません。インストールを承認するときにこの事実を文書に残しておかないと、あとで必ず問題になります。

続く記事で見ること

すぐ次の記事では、ClusterPolicyの下のDaemonSetが、RuntimeClassとnvidia.com/gpuリソースにどうつながるのかを見ます。この2つの流れはまったく別のゲートであり、両者を取り違えると、「PodがPendingなのに原因が見つからない」状態にそのまま陥ります。