第6章 トラブルシューティング・監視・最適化 / 想定学習時間:30〜40分 / 最終確認:2026年8月

6-4. クラスタ起動失敗・ライブラリ競合・メモリ不足(OOM)の診断

🎯 この節の学習目標

1. クラスタ起動失敗:コードが動く前の問題

この節で扱うのは、6-2 のような「実行中の性能問題」ではなく、そもそも実行環境が立ち上がらない・壊れているタイプの問題です。ジョブのステータスが Pending のまま進まない、クラスタが「起動失敗(terminated)」になる、という症状はここに分類されます。診断の起点はクラスタのイベントログ(Event log)で、より詳細な情報が必要ならドライバーログを確認します。

原因症状・ログでの現れ方対策
クラウド側のインスタンス不足
(capacity 不足)
イベントログに「要求したインスタンスタイプを確保できない」旨のクラウドプロバイダ由来のエラー。特定リージョン・特定タイプで発生別のインスタンスタイプ・アベイラビリティゾーンを試す。スポットからオンデマンドへ切り替える。インスタンスプールで事前確保する
クォータ(上限)超過イベントログにクラウドアカウントの vCPU 数などのクォータ超過エラー。大きなクラスタや同時起動が増えた時期に発生クラウドプロバイダにクォータの引き上げを申請する。不要クラスタの自動終了(auto termination)を徹底する
権限の不足
(インスタンスプロファイル等)
起動時の認可エラー。指定したインスタンスプロファイル/サービス資格情報でインスタンス作成やストレージアクセスが拒否されるクラウド側の IAM 設定(ロール・ポリシー)を確認・修正する。ワークスペースに登録された資格情報の設定を見直す
init script の失敗インスタンス自体は確保できたのに、初期化スクリプトが非ゼロ終了して起動が中断。イベントログに init script failure、詳細はinit script のログ・ドライバーログスクリプトのエラー(参照先URLの死活、依存パッケージ、実行権限)を修正する。まず init script なしで起動して切り分ける

📝 試験のポイント

「クラスタが起動しない。まずどこを確認するか」→ クラスタのイベントログが第一の答えです。イベントログにはインスタンス確保・起動・終了・リサイズなどのライフサイクルイベントと失敗理由が時系列で残ります。「コードのエラー→ドライバーログ/ノートブック出力」「起動の失敗→イベントログ」という対応付けを覚えておきましょう。

2. ライブラリ競合:バージョンの衝突を層で理解する

Databricks のクラスタでは、Python ライブラリが次の3つの層で存在し、同じライブラリの異なるバージョンが層の間で衝突することがあります。

インストール方法適用範囲
Databricks Runtime 同梱ランタイムにあらかじめ含まれる(pandas、pyarrow など)クラスタ全体(基盤)
クラスタライブラリクラスタ設定画面や API でインストールそのクラスタで動くすべてのノートブック・ジョブ
notebook-scoped ライブラリノートブック内で %pip installそのノートブックのセッションのみ。他のノートブックには影響しない

症状:ImportError / AttributeError(存在しないはずの属性)、「昨日まで動いていたノートブックが今日から壊れた」、同じクラスタの別ノートブックだけ動かない、など。
確認箇所:ノートブックで実際に読み込まれているバージョンを確認します(pip listライブラリ.__version__)。クラスタ設定のライブラリ一覧、ノートブック内の %pip 行、使用中の Runtime バージョンの同梱ライブラリ一覧を突き合わせます。
原因:典型パターンは次の3つです。

対策:

💡 具体例:「別のチームがクラスタライブラリを更新したら壊れた」

共有の汎用クラスタで、あるチームが自分たちのノートブックのためにクラスタライブラリとして機械学習ライブラリの新バージョンをインストールしたところ、同じクラスタを使う別チームの既存ノートブックが AttributeError で動かなくなりました。クラスタライブラリはそのクラスタの全ユーザーに影響するためです。恒久対策は、チーム固有の要求バージョンを notebook-scoped(%pip install ライブラリ==X.Y.Z)へ移すか、ジョブごとに専用のジョブクラスタを使って環境を分離することです。

3. メモリ不足(OOM):ドライバーとエグゼキュータを切り分ける

OOM(Out Of Memory)の診断で最初にすべきことは、「どこでメモリが尽きたのか」の切り分けです。Spark ではドライバーとエグゼキュータの役割が異なるため、原因も対策も別物になります。

3-1. ドライバー OOM:データを1台に集めてしまった

症状:ノートブック全体が応答しなくなる、カーネルの再起動、「Driver is up but unresponsive」系のメッセージ。クラスタ上のすべての処理が巻き添えになります。
確認箇所:ドライバーログにヒープ不足・GC 多発の記録。直前に実行したコードに collect()・大きな DataFrame の toPandas()・巨大な結果の display がないか。
原因:分散処理の結果をドライバー1台のメモリに集約する操作collect() と大規模データの toPandas() が2大要因です。
対策:集約系操作を避け、結果はテーブルやファイルへ分散のまま書き出す。確認用には limit()display の件数制限を使う。pandas 的な処理が必要なら pandas API on Spark 等の分散実装を検討する。

3-2. エグゼキュータ OOM:1タスクに載るデータが大きすぎる

症状:特定のタスク・ステージが失敗と再試行を繰り返した末にジョブが失敗する。ノートブック自体は応答している。
確認箇所:失敗したステージを Spark UI で開き、失敗タスクのメトリクスを確認。特定タスクだけ入力・shuffle read が突出していればスキュー、全タスク一様に大きければパーティション過大。エグゼキュータのログにヒープ不足の記録。
原因:データスキューによる特定タスクへの集中、パーティションサイズの過大、メモリ設定に対して重すぎる処理(巨大な結合・爆発的な explode など)。
対策:スキューなら 6-2 の対策(AQE の skew join 処理確認・ブロードキャスト結合・salting)。パーティション過大ならパーティション数を増やす(spark.sql.shuffle.partitions・repartition)。それでも不足するならメモリ最適化インスタンスへの変更を検討します。

症状ログ・UIで見る場所原因の典型対策
クラスタが起動しない/Pending が長いクラスタのイベントログ(詳細はドライバーログ・init script ログ)インスタンス不足・クォータ・権限・init script 失敗タイプ/AZ 変更、クォータ申請、IAM 修正、スクリプト修正
ImportError/AttributeError、昨日まで動いたコードが壊れたノートブックの pip list、クラスタのライブラリ設定、Runtime 同梱一覧ライブラリのバージョン競合Runtime 更新、バージョン固定、notebook-scoped/ジョブ単位で分離
ノートブック全体が無応答・ドライバー再起動ドライバーログ、直前のコードドライバー OOM(collect / 大きな toPandas)collect 回避、limit、分散のまま書き出す
特定ステージのタスクが失敗・再試行を繰り返すSpark UI の失敗ステージ、エグゼキュータログエグゼキュータ OOM(スキュー・パーティション過大)スキュー対策、パーティション数増、メモリ最適化インスタンス

4. 復習:ワークロードに合ったコンピュートを選んでいるか

症状への対処と同じくらい重要なのが、そもそもワークロードに合ったコンピュートを選ぶことです(2章の内容の復習です)。合わないコンピュートは、遅延・OOM・コスト超過という形で「症状」を生み続けます。

✅ この節のまとめ

練習問題

問1. ジョブクラスタが起動に失敗し、ジョブが実行できない。失敗の理由を特定するために最初に確認すべき場所はどれか。

  1. Spark UI の Stages タブ
  2. クラスタのイベントログ
  3. ジョブの実行履歴の duration グラフ
  4. Unity Catalog の監査ログ
解答と解説を見る

正解:B

イベントログにはクラスタのライフサイクル(インスタンス確保・起動・終了)と失敗理由が時系列で記録されており、インスタンス不足・クォータ超過・権限エラー・init script 失敗のいずれかをここで切り分けられます。Aの Spark UI はクラスタが起動して処理が動いた後の診断手段であり、起動前の失敗には使えません。Cは性能トレンドの確認用です(6-1)。Dはデータアクセスの監査が目的で、クラスタ起動の失敗理由は記録されません。

問2. 共有の汎用クラスタで、あるノートブックだけが特定バージョンのライブラリを必要としている。他のユーザーのノートブックに影響を与えずにこれを満たす方法として最も適切なのはどれか。

  1. クラスタライブラリとして該当バージョンをインストールする
  2. そのノートブック内で %pip install ライブラリ==X.Y.Z を実行する(notebook-scoped)
  3. Databricks Runtime を最も古いバージョンに変更する
  4. クラスタの init script で全ノード共通にインストールする
解答と解説を見る

正解:B

notebook-scoped ライブラリ(%pip)は、そのノートブックのセッションにのみ適用され、同じクラスタの他ノートブックへ影響しません。バージョン固定(==X.Y.Z)も再現性の観点から適切です。AとDはどちらもクラスタ全体に適用されるため、他ユーザーの環境を変えてしまい競合の火種になります。Cはランタイムの変更でクラスタ全体の同梱ライブラリがすべて変わるうえ、古いランタイムへ下げる合理性もありません。

問3. 大きなテーブルを DataFrame に読み込んで toPandas() を呼んだところ、ノートブック全体が応答しなくなり、しばらくしてドライバーが再起動した。原因と対策として最も適切なのはどれか。

  1. エグゼキュータ OOM が原因。ワーカーノードを増やす
  2. ドライバー OOM が原因。全件をドライバーに集約する操作を避け、結果はテーブルへ分散のまま書き出すか limit で件数を絞る
  3. ネットワーク障害が原因。クラスタを再起動すれば解決する
  4. ライブラリ競合が原因。pandas を最新版に更新する
解答と解説を見る

正解:B

toPandas() は分散していたデータ全件をドライバー1台のメモリ上の pandas DataFrame に変換する操作で、大きなテーブルではドライバー OOM の代表的な原因です。「ノートブック全体が無応答→ドライバー再起動」という症状もドライバー側の障害を示しています。Aはワーカーを増やしてもドライバーに集まるデータ量は変わらないため無効です。Cは再起動しても同じコードで再発します。Dはバージョン違いのエラー(ImportError 等)として現れる問題で、この症状とは異なります。

問4. 数百人のアナリストが日中、BIダッシュボードやアドホックなSQLクエリを断続的に実行する。同時実行が多く、応答の速さが求められる。最も適切なコンピュートはどれか。

  1. 大型の汎用(All-Purpose)クラスタを1つ用意し、全員で共有する
  2. アナリストごとにジョブクラスタを作成する
  3. サーバーレス SQL ウェアハウスを使用する
  4. シングルノードクラスタを使用する
解答と解説を見る

正解:C

多数ユーザーの同時アドホック SQL という要件には、SQL に最適化され、即時起動と自動スケーリングで高い同時実行性を提供するサーバーレス SQL ウェアハウスが適合します。Aは同時実行の増減に追従しにくく、ピーク時は詰まり、閑散時は無駄なコストが出ます。Bのジョブクラスタは自動化されたパイプライン向けで、対話的なアドホック分析には不向きです(人数分のクラスタはコストも管理も非現実的です)。Dのシングルノードは軽量な開発・実験用で、数百人の同時利用を支えられません。