gke-ai-troubleshooting-jobset-interruption について
このスキルは、GKE 上の大規模 AI/ML ワークロードにおける JobSet の中断、再起動、プリエンプションを診断する手順を提供します。メトリクス、ログ、ノードと Pod の状態を照合し、調査結果に応じたスケジューリング変更やホスト隔離を提案します。
主な機能
- 01JobSet 再起動メトリクスの分析
- 02ノードプールの中断とログの確認
- 03ノード状態と物理ホストの照合
- 04Pod 状態とコンテナログの調査
- 05障害種別に応じた対処案
活用シーン
- 01トレーニングジョブの再起動を調査
- 02Spot プリエンプションとハードウェア障害の判別
- 03繰り返し障害が起きる物理ホストの特定
- 04スケジュール不能 Pod とコーディネーターログの確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ google/ skills --skill gke-ai-troubleshooting-jobset-interruptionインストール後、Claude Code で/gke-ai-troubleshooting-jobset-interruptionを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/attribution.mdfailure_signatures.mdscripts/validate_queries.sh詳細
GKE JobSet の中断に関するトラブルシューティング
このスキルを使用して、大規模な AI/ML ワークロードを実行する GKE クラスターで発生した JobSet の中断、再起動、プリエンプションを体系的に診断し、解決します。
クレジット表記
必ずお読みください:gcloud、REST API、MCP コマンドを実行する前に、必ず使用状況のクレジット表記をお読みください。ターミナルで直接実行するコマンド(生成されたスクリプト、Terraform、ユーザーコード内での実行は不可)では、gcloud の前に
CLOUDSDK_METRICS_REQUEST_ATTRIBUTION="agent-skills/1.0 (skill:gke-ai-troubleshooting-jobset-interruption)"
を付け、User-Agent ヘッダーに agent-skills/1.0 (skill:gke-ai-troubleshooting-jobset-interruption) を追加してください。
⚠️ 前提条件とサンドボックスのルール
- クラスターの
kube-state-metricsで JobSet メトリクスパッケージを有効にする必要があります。 - Google Cloud プロジェクトで Cloud Logging と Cloud Monitoring を有効にしてください。
- 自律実行とサンドボックスでの実行に関するルール:API クエリ、ツール、コマンドで
403 Permission Denied、認証エラー、またはネットワークの分離が発生した場合は、認証や認証情報のトラブルシューティングを繰り返さないでください。取得した変数({project_id}、{cluster_name}、{workload_name}、{start_time}、{end_time})をクエリテンプレートに設定し、利用可能な場合はローカルに配置されたテレメトリやモックデータのファイルを調べ、自律的に診断ワークフローと解決策の推奨事項を完了してください。
🔍 診断ワークフロー
ステップ 0:コンテキストの取得と時間範囲の定義
ツール、ワークスペースのファイル、環境の詳細、ユーザープロンプトのコンテキストを利用して、コンテキストを独自に収集します。
- プロジェクト ID(
{project_id}) - クラスター名(
{cluster_name}) - ワークロード名(JobSet 名)(
{workload_name}) - ワークロードの名前空間(
{namespace}) - 問題発生時刻(
{issue_time})
ユーザーから変数が明示的に指定されていない場合は、クラスターのリソースまたはログを調べて特定するか、提示されている {variable} プレースホルダーを使用します。
時刻の扱いに関するルール
- 自律的な時間範囲の設定:相対時刻(例:「X 分前」)が指定されている場合、または正確なタイムスタンプが指定されていない場合は、現在時刻または利用可能なログのタイムスタンプに基づいてクエリ範囲を計算します。
- 時間範囲の計算:タイムスタンプ
{issue_time}が利用可能な場合(またはTとして計算した場合)、{start_time}=T - 30m、{end_time}=T + 30mに設定します。
ステップ 1:JobSet の再起動と試行回数を特定する[低リスク]
JobSet で再起動ループが発生しているかを確認し、再起動の頻度を特定します。
可視化チャート/MQL クエリ - 再起動
-
MQL クエリの仕様:
fetch prometheus_target | metric 'prometheus.googleapis.com/kube_jobset_restarts/gauge' | filter resource.cluster_name == '{cluster_name}' && metric.jobset_name == '{workload_name}' | align next_older(1m) | every 1m | group_by [metric.jobset_name], [val: max(value)]
PromQL メトリクスクエリ - 再起動
-
PromQL クエリの仕様:
kube_jobset_restarts{jobset_name="{workload_name}", cluster="{cluster_name}"} -
診断ロジック:再起動の値がゼロ以外、または増加している場合、ワーカーの障害や中断が原因で、コントローラーによって JobSet が再起動されていることを示します。
-
自動化:調査結果を報告した後、自動的にステップ 2 に進みます。
ステップ 2:ノードプールの中断を調査する[低リスク]
JobSet の再起動が、スポット VM のプリエンプション、メンテナンス、ホストの終了など、物理ノードプールレベルのイベントによって引き起こされたかどうかを特定します。
A. メトリクスクエリ(ノードプールの中断回数)
ビジュアルチャート/MQL クエリ - 割り込み
-
MQL クエリの仕様:
fetch k8s_node_pool | metric 'kubernetes.io/node_pool/interruption_count' | filter cluster_name == '{cluster_name}' | align next_older(10m) | every 10m | group_by [metric.interruption_type, metric.interruption_reason, metadata.system.node_pool_name], [val: sum(value)]
PromQL クエリ - 割り込み
-
PromQL クエリの仕様:
sum by (interruption_type, interruption_reason, node_pool_name, cluster_name) ( avg_over_time(kubernetes_io:node_pool_interruption_count{cluster_name="{cluster_name}"}[10m]) )
B. ログクエリ(ノードプールのライフイベント)
-
LQL ログフィルターの仕様:
resource.type="gke_nodepool" AND resource.labels.cluster_name="{cluster_name}" AND timestamp >= "{start_time}" AND timestamp <= "{end_time}" -
診断ロジック:
- PreemptionEvent:Spot VM がプリエンプトされたか、ノードがスケールダウンされました。
- MaintenanceEvent:ノードプールが更新されたか、Google によるメンテナンスが予定されていました。
- TerminationEvent:重大なホスト障害です。
interruption_reasonまたはログでホストの問題を確認してください。 - ノード終了ログとプリエンプションイベントの例については、障害シグネチャを参照してください。
-
自動化:ステップ 3 に自動的に進みます。
ステップ 3:ノードと基盤となるホスト VM を調査する[低リスク]
ノードの準備完了状態の障害を物理ホスト VM と関連付け、単一の障害のあるホストでコーディネーターポッドの障害が繰り返し発生していないか確認します。
A. メトリクスクエリ(ノードの Ready 状態チェック)
ビジュアルチャート/MQL クエリ - ノードの状態
-
MQL クエリの仕様:
fetch k8s_node | metric 'kubernetes.io/node/status_condition' | filter cluster_name == '{cluster_name}' && metric.condition == 'Ready' && metric.status == 'False' | align next_older(1m) | every 1m | group_by [node_name, metadata.user.gke_nodepool], [val: max(value)]
PromQL クエリ - ノードの状態
-
PromQL クエリの仕様:
sum by (status, condition, node_pool_name) ( kubernetes_io:node_status_condition{cluster_name="{cluster_name}", condition="Ready", status="False"} )
B. メトリクスクエリ(ノードとホストのメタデータトポロジーの関連付け)
-
MQL クエリの仕様:
fetch k8s_node | metric 'kubernetes.io/node/cpu/total_cores' | filter cluster_name == '{cluster_name}' | align next_older(1m) | every 1m | group_by [node_name, metadata.user.gce_topology_host, metadata.user.gke_nodepool], [val: max(value)]
C. ログクエリ(ノード障害ログ)
-
LQL ログフィルターの仕様:
resource.type="k8s_node" AND resource.labels.cluster_name="{cluster_name}" AND (textPayload:"host error" OR textPayload:"kernel panic" OR textPayload:"hardware failure" OR textPayload:"NodeNotReady") AND timestamp >= "{start_time}" AND timestamp <= "{end_time}" -
診断ロジック:特定のノードが不健全かどうか(
Ready=FalseまたはUnknown)を特定し、metadata.user.gce_topology_hostを使って GCE 物理ホスト ID と関連付けます。同じホストで障害が繰り返し発生しているか確認してください。 -
自動化:ステップ 4 に自動的に進みます。
ステップ 4:ポッドとワーカー/コンテナの障害を調査する[低リスク]
ポッドのステータスフェーズを分析し、コーディネーターワーカーのログを取得して、アプリケーションレベルのクラッシュやネットワークのデッドロックを特定します。
必須の実行順序:特定のワーカーコンテナログ(セクション C)を調査する前に、ポッドのステータスフェーズ(セクション A)とスケジュール不能なポッドのメトリクス(セクション B)を分析し、ワークロード全体の健全性を評価する必要があります。
A. メトリクスクエリ(ポッドのライフサイクルフェーズ)
ビジュアルチャート/MQL クエリ - Pod のフェーズ
-
MQL クエリ仕様:
fetch k8s_pod | metric 'kubernetes.io/pod/status/phase' | filter cluster_name == '{cluster_name}' && pod_name ==~ '{workload_name}.*' | align next_older(10m) | every 10m | group_by [metric.phase], [val: count()]
PromQL クエリ - Pod のフェーズ
-
PromQL クエリ仕様:
sum by (phase) ( avg_over_time(kube_pod_status_phase{cluster="{cluster_name}", pod=~"{workload_name}.*"}[10m]) )
B. メトリクスクエリ(スケジュール不能な Pod の数)
-
MQL クエリ仕様:
fetch k8s_pod | metric 'kubernetes.io/pod/status/unschedulable' | filter cluster_name == '{cluster_name}' && pod_name ==~ '{workload_name}.*' | align next_older(10m) | every 10m | group_by [pod_name], [val: max(value)]
C. ログクエリ(ワーカーコンテナのログ)
-
LQL ログフィルター仕様:
resource.type="k8s_container" AND resource.labels.cluster_name="{cluster_name}" AND labels."k8s-pod/jobset_sigs_k8s_io/jobset-name"="{workload_name}" AND timestamp >= "{start_time}" AND timestamp <= "{end_time}" -
診断ロジック:
- Pod のタイムラインを確認し、保留中またはスケジュール不能な Pod を見つけます。
- ワーカーコンテナのログを使用して、スライス 0 のワーカー 0(コーディネーター)について、NCCL のタイムアウト、集合通信の問題、または MegaScale のハングを分析します。
-
自動化:解決に進みます。
🛠️ 解決ワークフロー
解決策 1:プリエンプションとオートスケーリングの最適化[低リスク]
ステップ 2 で Spot VM のプリエンプション数が多いことが確認された場合:
- アクション:重要な長時間実行のトレーニングワークロードを GKE Reserved/On-Demand VM に切り替えるか、Compact Placement Policies を利用して、デフラグによる中断を最小限に抑えるよう提案します。
- 理由:Spot 市場でのプリエンプションをなくし、トレーニングの再起動を減らします。
解決策 2:障害のあるホスト VM を隔離する[高リスク]
ステップ 3 で、複数回の試行にわたって一貫して失敗または再起動を引き起こす特定のホスト ID(gce-topology-host)が見つかった場合:
- アクション:GKE ノードをスケジュール対象外にしてドレインし、基盤となる GCE VM インスタンスを削除してインスタンスの再作成を促し、物理ホスト ID を指定して Google Cloud サポートにサポートチケットを起票することを推奨します。
- 理由:GKE の自動修復により、正常な物理ハードウェア上に VM インスタンスが再作成され、再起動が無限に繰り返されるのを防ぎます。
📋 コピー用チェックリスト
- コンテキストを収集し、
{start_time}({issue_time} - 30m)と{end_time}({issue_time} + 30m)の時間範囲を計算します。 - JobSet の再起動試行をクエリします。
- Nodepool の中断を確認します(Spot のプリエンプションとハードウェアの終了を区別します)。
- ノードとホストのマッピングをクエリし、物理ホストのエラーについてノードログを確認します。
- Pod のタイムラインの状態と、コーディネーターのワーカーコンテナログを調べます。
- 適切なスケジューリング戦略(オンデマンドと Spot)またはホスト VM の隔離を推奨します。