デバイスを持つPodでの障害への対処

Kubernetesはコンテナオーケストレーションのデファクトスタンダードですが、GPUやその他のアクセラレーターのような専用ハードウェアを扱うとなると、少し複雑になります。 この記事では、Kubernetesでデバイスを持つPodを運用する際の故障モード管理の課題について、KubeCon NA 2024でのSergey KanzhelevとMrunal Patelのセッションの知見に基づいて掘り下げます。 スライド録画のリンクもご確認ください。

AI/MLブームとKubernetesへの影響

AI/MLワークロードの台頭は、Kubernetesに新たな課題をもたらしています。 これらのワークロードは専用ハードウェアに大きく依存することが多く、デバイスの故障はパフォーマンスに重大な影響を与え、腹立たしくなる中断につながる可能性があります。 2024年のLlama論文で強調されているように、ハードウェアの問題、特にGPUの故障はAI/MLトレーニングにおける中断の主要原因です。 また、Ryan HalliseyとPiotr ProkopによるKubeConセッション「All-Your-GPUs-Are-Belong-to-Us: An Inside Look at NVIDIA's Self-Healing GeForce NOW Infrastructure」(録画)からも、NVIDIAがデバイス障害とメンテナンスの処理にどれだけの労力をかけているかがわかります。 それによると、1000ノードあたり1日19件の修復リクエストが発生しているそうです! また、データセンターではスポット消費モデルを提供し電力を過剰に供給しているため、デバイスの故障が日常的なものとなり、ビジネスモデルの一部となっているケースも見られます。

しかし、Kubernetesのリソースに対する見方は依然として非常に静的です。 リソースは存在するか存在しないかのどちらかです。 存在する場合、それが完全に機能し続けると想定されています。 Kubernetesは、完全または部分的なハードウェア障害を処理するための適切なサポートを欠いています。 これらの以前からある前提と設定全体の複雑さが相まって、様々な故障モードが発生します。 本記事ではこれについて議論します。

AI/MLワークロードの理解

一般的に、すべてのAI/MLワークロードは専用ハードウェアを必要とし、スケジューリング要件が難しく、アイドル時にコストがかかります。 AI/MLワークロードは通常、トレーニングと推論の2つのカテゴリに分類されます。 以下は、これらのカテゴリの特性を非常に単純化した見方であり、Webサービスなどの従来のワークロードとは異なります:

トレーニング
これらのワークロードはリソース集約的で、しばしばマシン全体を消費し、Podのグループとして実行されます。 トレーニングジョブは通常「完了まで実行」されますが、それは数日、数週間、さらには数ヶ月かかることもあります。 単一のPodで障害が起こった場合もすべてのPodでステップ全体を再起動する必要があります。
推論
これらのワークロードは通常、長時間実行されるか無限に実行されます。 ノードのデバイスのサブセットを消費する程度の小さなものでも、複数のノードにまたがるほど大きなものでもかまいません。 モデルの重みを含む巨大なファイルのダウンロードが必要になることがよくあります。

これらの類のワークロードは、特に多くの前提を覆します:

ワークロードの前提: 以前と現在
以前現在
より良いCPUを使えば、アプリはより速く動作する。実行には特定のデバイス(またはデバイスクラス)が必要。
何かが動作しない場合は、再作成すればよい。割り当てまたは再割り当ては高コスト。
どのノードでも動作する。Pod間での調整は不要。特別な方法でスケジュールされる - デバイスはしばしばノード間トポロジーで接続される。
各Podは、障害が発生した場合にプラグアンドプレイで置き換え可能。Podはより大きなタスクの一部。タスク全体のライフサイクルは各Podに依存する。
コンテナイメージはスリムで簡単に利用可能。コンテナイメージは特別な処理が必要なほど大きい場合がある。
長時間の初期化は漸進的なロールアウトで相殺できる。初期化は長くなる可能性があり最適化が必要。場合によっては複数のPodをまとめて最適化。
コンピューティングノードはコモディティ化されており比較的安価であるため、アイドル時間は許容される。専用ハードウェアを搭載したノードは、非搭載のノードよりも桁違いに高価である可能性があるため、アイドル時間は非常に無駄が多い。

既存の障害モデルは古い前提に基づいていました。 新しいワークロードタイプでもまだ機能する可能性がありますが、デバイスに関するナレッジが限られており、非常にコストがかかります。 場合によってはありえないほど高コストになることもあります。 この記事の後半でさらに多くの例をお見せします。

Kubernetesが依然として王者である理由

この記事では、AI/MLワークロードが従来のKubernetesワークロードと非常に異なるのに、なぜゼロから始めないのかという疑問については深く掘り下げません。 多くの課題があるにもかかわらず、Kubernetesは依然としてAI/MLワークロードのプラットフォームとして選ばれ続けています。 その成熟度、セキュリティ、豊富なツールエコシステムが、魅力的な選択肢となっています。 代替手段は存在しますが、それらの多くはKubernetesが提供する長年の開発と改良の成果には及びません。 そしてKubernetesの開発者たちは、本記事で指摘された課題やそれ以上の課題に積極的に取り組んでいます。

デバイス障害処理の現状

このセクションでは、さまざまな故障モードと今日使用されているベストプラクティス、そしてDIY(Do-It-Yourself)ソリューションの概要を説明します。 次のセッションでは、それらの故障モードの改善のロードマップを説明します。

故障モード: K8sインフラストラクチャ

Kubernetesインフラストラクチャに関連する障害を理解するには、ノード上でPodをスケジュールする際にどれほど多くの要素が関わっているかを理解する必要があります。 Podがノードにスケジュールされる際の一連のイベントは以下のとおりです:

  1. デバイスプラグインがノードにスケジュールされる
  2. ローカルgRPCを介してデバイスプラグインkubeletに登録される
  3. Kubeletデバイスプラグインを使用してデバイスを監視し、ノードの容量を更新する
  4. 更新された容量に基づいてスケジューラーUser Podをノードに配置する
  5. デバイスプラグインUser Podのデバイスを割り当てるよう、Kubeletが依頼する
  6. 割り当てられたデバイスが接続されたUser PodKubeletが作成する

この図は、関与するアクターの一部を示しています:

この図は、kubelet、デバイスプラグイン、およびUser Pod間の関係を示しています。kubeletがmy-deviceという名前のデバイスプラグインに接続し、kubeletがmy-deviceの利用可能数とともにノードステータスを報告し、User Podがmy-deviceを2つリクエストしていることを示しています。

多くのアクターが相互接続されているため、各アクターと各接続で中断が発生する可能性があります。 これは、しばしば障害と見なされる多くの例外的な状況につながり、深刻なワークロード中断を引き起こす可能性があります:

  • Podがライフサイクルのさまざまな段階で受け入れに失敗する
  • 完璧に正常なハードウェアでPodが実行できない
  • スケジューリングに予想外に長い時間がかかる
上記と同じ図ですが、個々のコンポーネントにオレンジ色のバン(警告)の絵が重ねられており、そのコンポーネントで何が壊れるかが記されています。kubeletの上には「kubelet restart: looses all devices info before re-Watch(kubelet 再起動: 再監視前に全てのデバイス情報が消失する)」と記されています。デバイスプラグインの上には「device plugin update, evictIon, restart: kubelet cannot Allocate devices or loses all devices state(デバイスプラグインの更新、強制終了、再起動: kubeletがデバイスを割り当てられない、またはすべてのデバイスのステータスが消失する)」と記されています。User Podの上には「slow pod termination: devices are unavailable(Pod終了の遅延: デバイスが利用できない)」と表示されています。

Kubernetesの目標は、これらのコンポーネント間の中断を可能な限り信頼性の高いものにすることです。 Kubeletはすでにリトライ、終了前の猶予期間、その他の技術を実装してこれを改善しています。 ロードマップセクションでは、Kubernetesプロジェクトが追跡している他のエッジケースについて詳しく説明します。 ただし、これらの改善はすべて、これらのベストプラクティスに従った場合にのみ機能します:

  • ワークロードを中断しないように、できるだけ早くkubeletとコンテナランタイム(containerdやCRI-Oなど)を設定して再起動する。
  • デバイスプラグインの健全性を監視し、アップグレードを慎重に計画する。
  • デバイスプラグインやその他のコンポーネントの中断を防ぐため、ノードを重要度の低いワークロードで過負荷にしない。
  • ノードの準備状態の一時的な不安定さに対処するため、User Podのtolerationsを設定する。
  • デバイスを長時間ブロックしないよう、適切な終了ロジックを慎重に設定・コーディングする。

Kubernetesインフラ関連の問題の別の類は、ドライバー関連です。 CPUやメモリなどの従来のリソースでは、アプリケーションとハードウェア間の互換性チェックは必要ありませんでした。 ハードウェアアクセラレーターのような専用デバイスでは新たな故障モードがあります。 ノードにインストールされているデバイスドライバーは以下を満たす必要があります:

  • ハードウェアに適合していること
  • アプリとの互換性があること
  • 他のドライバー(ncclなど)と連携可能であること

ドライバーバージョンの処理に関するベストプラクティス:

  • ドライバーインストーラーの健全性を監視する
  • インフラストラクチャとPodのアップグレードを計画してバージョンを一致させる
  • 可能な限りカナリアデプロイメントを使用する

このセクションのベストプラクティスに従い、信頼できるソースからのデバイスプラグインおよびデバイスドライバーインストーラーを使用することで、この種の障害は一般的に解消されます。 Kubernetesはこの領域をさらに改善するための取り組みを追跡しています。

故障モード: デバイスの障害

現在、Kubernetesではデバイス障害に関する処理がほとんどありません。 デバイスプラグインは、割り当て可能なデバイスの数を変更することによってのみデバイス障害を報告します。 また、Kubernetesは、liveness probeやコンテナ障害などの標準的なメカニズムを利用して、Podがkubeletに障害状態を伝達できるようにしています。 ただし、Kubernetesはデバイス障害とコンテナクラッシュを関連付けず、同じデバイスに接続されたままコンテナを再起動する以外の軽減策を提供しません。

これが、様々なシグナルに基づいてデバイス障害を処理する多くのプラグインとDIYソリューションが存在する理由です。

ヘルスコントローラー

多くの場合、故障したデバイスによって復旧不能になり、非常に高価なノードが何もできなくなってしまいます。 これに対するシンプルなDIYソリューションは、ノードヘルスコントローラー です。 コントローラーは、デバイスの割り当て可能数と容量を比較し、容量が大きい場合、タイマーを開始します。 タイマーがしきい値に達すると、ヘルスコントローラーはノードを強制終了して再作成します。

ヘルスコントローラー アプローチにはいくつかの問題があります:

  • デバイス障害の根本原因は通常不明
  • コントローラーはワークロードを認識しない
  • 故障したデバイスが使われていないとしても、(ノードが再作成されることで)他のデバイスの稼働を継続できない
  • 非常に汎用的であるため、検出が遅すぎる可能性がある
  • ノードがより大きなノードセットの一部である可能性があり、他のノードとの連携なしでは単独で削除できない

上記の問題の一部を解決できるヘルスコントローラーのバリエーションもあります。 しかし、ここでの全体的なテーマは、故障したデバイスを最適に処理するには、特定のワークロード用のカスタマイズされた処理が必要であるということです。 Kubernetesは、デバイスがノード、クラスター、および割り当てられたPodにとってどれほど重要であるかを表現するのに十分な抽象化をまだ提供していません。

Pod失敗ポリシー

デバイス障害処理の別のDIYアプローチは、故障したデバイスに対するPodごとの対応です。 このアプローチは、Jobとして実装されたトレーニングワークロードに適用できます。

Podは、デバイス障害の特別なエラーコードを定義できます。 たとえば、デバイスが予期しない振る舞いをした場合、Podは特別な終了コードで終了します。 その後、Pod失敗ポリシーは、デバイス障害を特別な方法で処理できます。 詳細については、Pod失敗ポリシーによる再試行可能および再試行不可能なPod障害の処理を参照してください。

Jobに対する Pod失敗ポリシー アプローチにはいくつかの問題があります:

  • よく知られた device failed 状態が存在しないため、このアプローチは一般的なPodケースでは機能しない
  • エラーコードは慎重にコーディングする必要があり、場合によっては保証が難しい
  • Pod失敗ポリシー機能の制限により、restartPolicy: NeverのJobでのみ機能する

したがって、このソリューションは適用範囲が限られています。

カスタムPod watcher

より汎用的なアプローチは、DIYソリューションとしてPod watcherを実装するか、この機能を提供するサードパーティツールを使用することです。 Pod watcherは、推論ワークロードのデバイス障害を処理するためによく使用されます。

Kubernetesは、デバイスが不健全と報告されている場合でも、デバイスに割り当てられたPodを維持するだけであるため、Pod watcherでこの状況を検出し何らかの修復を適用するというアイデアです。 これは、ノード上のPod Resources APIを使用してデバイスの健全性ステータスとそのPodへのマッピングを取得することが多いです。 デバイスが故障した場合、修復措置として接続されたPodを削除できます。 レプリカセットが健全なデバイスでPodの再作成を処理します。

このwatcherを実装する他の理由:

  • これがないと、Podは故障したデバイスにいつまでも割り当てられ続ける
  • restartPolicy=AlwaysのPodには スケジューリング解除 がされない
  • CrashLoopBackoff状態のPodを削除する組み込みコントローラーがない

カスタム Pod watcher の問題点:

  • Pod watcherのシグナルを取得するのは高コストで、いくつかの特権的な操作が必要
  • カスタムソリューションであり、Podに対するデバイスの重要性を前提としている
  • Pod watcherは、Podの再スケジュールを外部コントローラーに依存している

デバイス障害や今後のメンテナンスを処理するためのDIYソリューションには、さらに多くのバリエーションがあります。 全体的に、Kubernetesにはこれらのソリューションを実装するのに十分な拡張ポイントがあります。 ただし、一部の拡張ポイントは、ユーザーの許容を超える高い特権を要求したり、あまりにも破壊的であったりします。 ロードマップセクションでは、デバイス障害の処理に関する特定の改善について詳しく説明します。

故障モード: コンテナコードの障害

コンテナコードが障害を起こしたり、メモリ不足などの問題が発生したりした場合、Kubernetesはそれらのケースに対処する方法を知っています。 コンテナを再起動するか、PodにrestartPolicy: Neverが設定されている場合はPodをクラッシュさせ、別のノードにスケジュールします。 Kubernetesは、何が障害であるか(たとえば、ゼロ以外の終了コードやliveness probeの失敗)と、そのような障害にどのように対応するか(たいてい常に再起動するか、すぐにPodを失敗させる)について表現力が限られています。

このレベルの表現力は、複雑なAI/MLワークロードにはしばしば不十分です。 AI/ML Podは、イメージを取得する時間とデバイス割り当てを節約できるため、ローカルで再スケジュールするか、その場で再スケジュールする方が適しています。 AI/ML Podはしばしば相互接続されており、一緒に再起動する必要があります。 これにより複雑さがさらに増しますが、これを最適化することで、AI/MLワークロードの実行コストを大幅に削減できる場合が多いです。

Pod障害のオーケストレーションを処理するための様々なDIYソリューションがあります。 最も典型的なものは、オーケストレーターによってコンテナ内のメイン実行可能ファイルをラップすることです。 このオーケストレーターは、他のPodで障害が起こったためにジョブを再起動する必要がある場合に、メイン実行可能ファイルを再起動できるようになります。

このようなソリューションは非常に脆弱で複雑です。 大規模なトレーニングジョブで使用する場合、通常のJobSetの削除/再作成サイクルと比較して、コスト削減の価値がある場合が多いです。 Kubernetesに新しいフックと拡張ポイントを開発することで、これらのソリューションの脆弱性を低減し効率化すれば、より小さなジョブにも簡単に適用でき、すべての人に利益をもたらします。

故障モード: デバイスの劣化

すべてのデバイス障害が、ワークロード全体やバッチジョブにとって致命的であるとは限りません。 ハードウェアスタックがますます複雑になるにつれて、ハードウェアスタックレイヤーのいずれかの設定ミスやドライバーの障害により、機能しているもののパフォーマンスが低下しているデバイスが生じる可能性があります。 遅くなっている1つのデバイスが、トレーニングジョブ全体を遅くする可能性があります。

このようなケースの報告はますます増えています。 Kubernetesには今日、このタイプの障害を表現する方法がなくこれが最新のタイプの故障モードであるため、ハードウェアベンダーから検出に関するベストプラクティスやこれらの状況の修復に関するサードパーティツールがほとんど提供されていません。

通常、これらの障害は、観測されたワークロード特性に基づいて検出されます。たとえば、特定のハードウェアでのAI/MLトレーニングステップの期待速度などです。 これらの問題の修復は、ワークロードのニーズに大きく依存します。

ロードマップ

上のセクションで概説したように、Kubernetesは多くの拡張ポイントを提供しており、それらを使用して様々なDIYソリューションを実装できます。 AI/MLの分野は、要件や使用パターンの変化に伴い、非常に急速に発展しています。 SIG Nodeは、特定のシナリオをサポートするための新しいセマンティクスの導入よりも、ワークロード固有のシナリオを実装するための拡張ポイントを増やすという慎重なアプローチを採用しています。 これは、一部のワークロードにしか適さない可能性のある障害に対する自動修復の実装よりも、障害に関する情報を容易に利用できるようにすることを優先するということです。

このアプローチによりワークロード処理に劇的な変更が加えられることがなくなり、既存の円滑なDIYソリューションや従来のワークロードの体験が損なわれることはありません。

今日使用されている多くのエラーハンドリング技術はAI/MLで機能しますが、非常に高コストです。 SIG Nodeは、AI/MLのコスト削減が重要であるという理解の下で、これらをより安価にするための拡張ポイントに投資します。

以下は、さまざまな故障モードに対して私たちが想定している具体的な投資事項です。

故障モードのロードマップ: K8sインフラストラクチャ

Kubernetesインフラストラクチャの領域は理解しやすく、デバイスプラグインからDRAへの今後の移行を正しく行うために非常に重要です。 SIG Nodeはこの領域で多くの作業項目を追跡しており、特に以下のものがあります:

基本的に、Kubernetesコンポーネントのすべての相互作用は、kubeletの改善またはプラグイン開発とデプロイメントのベストプラクティスを介して信頼性が確保される必要があります。

故障モードのロードマップ: デバイス故障

デバイス障害については、Kubernetesがサポートできる共通のシナリオでいくつかのパターンが既に現れています。 しかし、最初のステップは、故障したデバイスに関する情報をより簡単に利用できるようにすることです。 ここでの最初のステップは、KEP 4680(Add Resource Health Status to the Pod Status for Device Plugin and DRA)での作業です。

テストされる長期的なアイデアには以下が含まれます:

  • デバイス障害をPod失敗ポリシーに統合する。
  • ノードローカルのリトライポリシー、restartPolicy=OnFailureのPodに対してPod失敗ポリシーを有効にし、さらにそれ以外のケースにも対応可能にする。
  • restartPolicy: Alwaysも対象とした、Podの スケジュール解除 機能。これにより、Podに新しいデバイスを割り当てることができる。
  • DRAでデバイスを表すために使用されるResourceSliceから、健全でないデバイスを単に削除するのではなく、ResourceSliceにデバイスの健全性情報を追加する。

故障モードのロードマップ: コンテナコードの障害

AI/MLワークロードのコンテナコード障害への対応における主な改善点は、すべて低コストなエラー処理とリカバリを目的としています。 低コスト化の主な要因は、事前に割り当てられたリソースを可能な限り再利用することにあります。 コンテナをその場で再起動することによるPodの再利用から、可能な限り再スケジューリングの代わりにノードローカルでのコンテナ再起動、スナップショットサポート、イメージ取得を節約するために同じノードを優先する再スケジューリングまでです。

次のシナリオを考えてみましょう: 512個のPodが必要な大きなトレーニングジョブがあります。 そして、そのうちの1つが故障しました。 これは、すべてのPodを中断し、故障したステップを再起動するために同期する必要があることを意味します。 これを達成する最も効率的な方法は、一般に、可能な限り多くのPodをその場で再起動することで再利用しながら、エラーをクリアするために問題のあったPodを置き換えることです。 以下に図を示します:

この図は512個のPodを示しており、そのほとんどが緑色で、再利用できることを示すリサイクル記号が隣にあります。1つのPodが赤で描かれ、新しい緑色の置き換えPodがその隣にあり、置き換えが必要であることを示しています。

このシナリオを実装することは可能ですが、Kubernetesに特定の拡張ポイントが不足しているため、これを実装するすべてのソリューションは脆弱です。 このシナリオを実装するための拡張ポイントの追加は、Kubernetesのロードマップに組み込まれています。

故障モードのロードマップ: デバイスの劣化

この領域ではほとんど何も行われていません - 明確な検出シグナルがなく、トラブルシューティングツールが非常に限られており、Kubernetesで「劣化した」デバイスを表現する組み込みセマンティクスがありません。 DRAでデバイスを表現するために使用されるResourceSliceにデバイスのパフォーマンスや劣化に関するデータを追加することについての議論がありますが、まだ明確に定義されていません。 また、node-healthcheck-operatorのようなプロジェクトもあり、一部のシナリオで使用できます。

この領域では、ハードウェアベンダーとクラウドプロバイダーからの開発が期待されており、近い将来はDIYソリューションが主流になると予想しています。 AI/MLワークロードを利用するユーザーが増えるにつれて、この分野ではここで使用されているパターンに関するフィードバックが必要になります。

会話に参加する

Kubernetesコミュニティは、デバイス障害処理の未来を形作るためのフィードバックと参加を歓迎しています。 SIG Nodeに参加して、進行中の議論に貢献してください!

この記事では、Kubernetesにおけるデバイス障害管理の課題と今後の方向性について概説しました。 これらの課題に対処することで、KubernetesはAI/MLワークロードの主要プラットフォームとしての地位を確固たるものにし、特殊なハードウェアに依存するアプリケーションの耐障害性と信頼性を確保することができます。