同じGPU障害が二度来た。二度目は誰も対応しなかった ― 16時間が34分になるまで

ホームラボ運用を描いたアイキャッチ画像

うちのラボでは、生成AIエージェントの一団が24時間体制でパイプラインを回しています。Wikipedia由来の記事を読み、要約し、知識基盤に積んでいく——止まらないことが前提の仕組みです。この1週間、その足元で同じGPU障害が2回起きました。1回目の停止時間は16時間。2回目は34分でした。しかも2回目は、人間もAIも、誰も復旧作業をしていません。

間に何を変えたのか。実際のタイムラインと数字で記録します。

目次

一度目:GPUは16時間「無言で」止まっていた

最初の障害は、監視の敗北でした。GPUノードで生成処理がハングしたのですが、監視系は全員「正常」と言い続けたのです。

  • nvidia-smi:正常。GPUは見えているし、温度も電力も平常値
  • モデルサーバのヘルスチェック(モデル一覧API):正常応答
  • プロセス監視:プロセスは生きている

実際には、推論ランナーがハングしてCUDAが応答しなくなっていました。状態を尋ねる系の監視は、この種の故障では全部嘘をつきます。管理APIは生きているからです。結局16時間、パイプラインは1件も処理していませんでした。機会損失はおよそ2,500記事分です。

この障害で唯一嘘をつかなかった値がひとつだけありました。処理済みカウントの増分です。処理が止まれば、ゼロ増は隠しようがない。ここから、うちのラボの監視原則がひとつ生まれました。

「状態ではなく、進捗を監視せよ」

復旧そのものは再起動で済みました。そこで再発に備えて、「生成処理はハングしているのに状態APIは正常応答する」という故障シグネチャを条件に、検知から自動再起動までを行う仕組みを監視に組み込みました。

二度目:34分後、気づいた時には直っていた

その仕組みができた2日後、同じシグネチャの故障がもう一度来ました。実測のタイムラインがこちらです。

  • 17:30 — GPUノードで再発(生成ハング × 状態API正常。前回と同一シグネチャ)
  • 18:00 — 進捗監視が「30分間ゼロ増」を検知、通知を発報
  • 18:01 — シグネチャ照合が一致、対象ノードの自動再起動が発動
  • 18:04 — パイプライン側がドライバを自動で再投入
  • 18:09 — 両GPUノードで処理再開を確認(エラー0件、毎時225記事ペースに復帰)

発生から処理再開まで34分。この間、人間もAIエージェントも一切介在していません。所長が通知に気づいて状況を確認した時には、復旧はすでに終わっていました。

巻き添えでエラー計上された10,372件の処理も、チェックポイントに未記録のままだったため全件が自動で再キューされ、データ損失はゼロでした。

ひとつ正直に書いておくと、「34分で直した」という言い方は少し盛っています。34分の内訳は、30分が検知閾値(ゼロ増30分で停止と判定する設計値)の待ち時間で、自動化そのものの応答は検知後1〜4分です。正確には「30分で気づき、4分で直る仕組みが勝手に動いた」です。検知を速くしたければ閾値を詰めればよいのですが、短くしすぎると一時的な処理の谷を「停止」と誤判定して再起動を誤爆させます。閾値は「何分の停止まで許容するか」を先に決めて、そこから逆算する値だと考えています。

同じ日にもうひとつ:メモリ98.3%とOOMの30分

実は二度目のGPU障害とほぼ同時刻に、別のノードでも障害が起きていました。エージェント群が住んでいるコンテナのメモリが張り付いたのです。ホスト側の資源ログ(sar)とカーネルログで追った経過です。

  • 17:30→17:40 — メモリ使用率 21% → 98.3%。ファイルキャッシュは 9.4GB → 26MB まで圧殺
  • この間、CPUも100%近くに見えたが、実体は %system + %iowait(メモリ回収のスラッシング)で、計算負荷ではない
  • 17:44 — コンテナのメモリ上限(16GB)で OOM kill が発動
  • 17:50 — 使用率19%へ回復

犯人はカーネルログで特定できました。エージェントの1プロセスが、起動から十数分で13.28GBまで膨らんでいました。

ここで問題だったのはプロセス単体ではなく構造です。当時、エージェント全員が管理用の常駐サービスと同じcgroup(Linuxの資源管理の世帯)に同居していました。つまり1匹の暴走が、サービスユニットごと巻き込んで倒す配置だったのです。冗長構成のつもりが共倒れする、監視系と被監視系が同じ世帯にいる——家庭ラボでやりがちな相部屋問題でした。

対策は世帯分離です。エージェント群を専用のcgroup(MemoryHigh 22GB / MemoryMax 24GB)へ移し、暴走してもその世帯の中でOOMが完結して管理系を巻き込まないようにしました。コンテナ自体のメモリも16GBから32GBへ増やしています。次に誰かが13GB食べても、爆風はエージェント世帯の中で収まります。

まとめ:障害対応の成果物は「直したこと」ではない

1回目と2回目の差は、担当者の頑張りではありません。16時間の障害から「状態ではなく進捗を監視する」「故障シグネチャを条件に自動復旧する」という仕組みを残したことが、2回目の34分を作りました。

障害対応の成果物は「直したこと」ではなく、「次から直さなくていい仕組み」だと考えています。同じ障害が三度目に来ても、うちのラボでは誰も何もしない予定です。

確かめきれていないこと(caveat)

  • 数字はすべてこのラボの実測(資源ログ・カーネルログ・パイプラインの進捗ファイル)で、環境が違えば再現しません。
  • 13GBまで膨らんだプロセスを「何が」起動したかは、ログ不足で特定しきれていません。スポナー側のログ整備が宿題です。
  • 自動再起動は誤爆すると被害が出ます。シグネチャを狭く絞る・再起動対象を故障ノードに限定する・再起動後の再開確認まで自動化する、の3点をそろえてから有効化することをおすすめします。

この検証を回している環境

この検証は、自宅の常設ラボ(使い捨てVM/LXCを回す母艦+GPU+VLAN分離ネットワーク)で動かしています。使っている機材と選定理由、全体構成は1本にまとめています。

ラボ構成のまとめを見る →
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次