huawei-cloud-dws-io-diag について
Huawei Cloud DWS クラスターの I/O 過負荷を診断するスキルです。アラートやディスク負荷の異常を調べる運用担当者向けに、3段階の判断ツリーでメトリクスを分析し、標準形式のレポートを作成します。
主な機能
- 01クラスターのメトリクス収集と分析
- 02顧客側とシステム側の原因を判別
- 03基準に沿った高負荷ノードの特定
- 04標準形式の診断レポート作成
活用シーン
- 01DWS の I/O 使用率アラートの調査
- 02ディスク I/O 負荷異常の分析
- 03依頼を受けた I/O 診断への対応
MCP 対応
dws_autopilot MCP サーバーを通じて、クラスター、ホスト、メトリクスのデータを取得できます。KooCLI(hcloud)を優先し、ネットワークエラー時は MCP に切り替える手順です。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ huaweicloud/ huaweicloud-skills --skill huawei-cloud-dws-io-diagインストール後、Claude Code で/huawei-cloud-dws-io-diagを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/cli-installation-guide.mddiagnosis-json-format.mddws-mcp-installation-guide.mdiam-policies.mdIO_DIAGNOSIS_REF.mdio-background.mdmetric-reference.mdoutput-format.md詳細
Huawei Cloud DWS I/O 過負荷診断スキル
概要
このスキルは、DWS クラスターの I/O 過負荷の根本原因を診断するためのものです。クラスターで I/O 使用率が高すぎるアラームが発生すると、メトリクスデータを自動的に収集し、3 段階の決定木を通じて根本原因(顧客側/システム側)を分析し、標準化された診断レポートを出力します。
アーキテクチャ:KooCLI (hcloud) → DWS Autopilot API → クラスター監視メトリクス;MCP Server (dws_autopilot) → 同じ API へのフォールバック経路
適用シナリオ:
- DWS クラスターの I/O 使用率が高すぎるアラーム
- ディスク I/O 負荷の異常調査
- ユーザー主導の I/O 診断リクエスト
一般的なユースケース:
- 「DWS クラスターの I/O 使用率が非常に高いので、診断してください」
- 「I/O アラームを受信しました。クラスター ID は xxx です。原因を分析してください」
- 「DWS クラスターのディスク使用率が最大になっています。原因を確認してください」
重要なルール:診断結果はすべて、実際のツールの戻り値に基づく必要があります。値を捏造したり、推測したりすることは禁止されています。出力には診断レポートのみを含めます。修復の提案の追加、SQL 最適化ステートメントの出力、絵文字の使用は禁止されています。
背景知識:RAID アーキテクチャ、I/O の主要メトリクスのしきい値、3 つの主要な I/O シナリオにおける指標の特徴、重要な原則については、I/O 背景知識に記載されています。診断の前に必ずお読みください。
前提条件
1. CLI の要件
- KooCLI (hcloud) >= 3.2.0
- インストールの確認:
hcloud version - 未インストールまたはバージョンが古い場合は、CLI インストールガイドを参照してください
2. MCP Server の設定(フォールバック)
- KooCLI が利用できない場合は、代替として MCP Server を使用します
- MCP インストールガイドを参照してください
3. 認証の設定
- 有効な Huawei Cloud 認証情報(AK/SK モードまたは IAM Token)
- セキュリティルール:
- 会話やコマンドで AK/SK の値を決して公開しないでください
- 会話で AK/SK を直接入力するようユーザーに求めないでください
- 認証情報の状態を確認する場合は、
hcloud configure listのみを使用してください
4. IAM 権限の要件
- dws:clusters:get、dws:clusters:list
- dws:metricData:get、dws:hostOverview:get
- IAM ポリシーを参照してください
KooCLI コマンド形式の標準
コマンド形式
# Query metric data
hcloud DWS ListMetricsData --cli-region=<region> --cluster_id=<id> --metric_name=<name> --project_id=<pid> --offset=0 --limit=200 --from=<from_ts> --to=<to_ts>
# Query host information
hcloud DWS ListHostOverview --cli-region=<region> --project_id=<pid> --offset=0 --limit=200
ツール選択戦略
KooCLI と MCP Server のどちらかを選択します。KooCLI を優先してください。ステップ 0 で hcloud が利用可能か確認します:
- hcloud が利用可能(バージョン >= 3.2.0)→ 以降のステップでは KooCLI コマンドライン呼び出しを使用します
- hcloud が利用不可(未インストールまたはバージョン < 3.2.0)→ 以降のステップでは MCP Server のツール呼び出しを使用します
フォールバックと終了の戦略:
- hcloud を選択した後、最初の呼び出しが
NETWORK_ERROR(接続タイムアウト、ネットワーク到達不可など)を返した場合は、自動的に MCP Server にフォールバックし、以降のすべてのステップで MCP モードを使用します - hcloud が NETWORK_ERROR を返し、MCP Server も利用できない場合(未設定、または認証/接続エラーを返す場合)は、このスキルを終了し、次の内容を出力します:
KooCLI network unavailable and MCP Server connection failed. Please check KooCLI network configuration or DWS Autopilot MCP Server configuration and retry - MCP Server を選択した後、最初の呼び出しが認証エラー(401 Unauthorized など)を返した場合は、hcloud にフォールバックしないでください。このスキルを直接終了し、次の内容を出力します:
MCP Server authentication failed. Please check DWS Autopilot MCP Server authentication configuration and retry - NETWORK_ERROR 以外の hcloud 呼び出しの失敗(パラメーターエラー、権限不足など)ではフォールバックを行わず、既存の再試行ロジックに従います
ツールを選択した後は、NETWORK_ERROR によるフォールバックを除き、切り替えずに最後まで同じツールを使用してください。呼び出しに失敗した場合は 1 回再試行します(最大 2 回)。それでも失敗する場合は、そのメトリクスを「利用不可」として記録し、次のステップに進みます。すべてのメトリクスのクエリに失敗した場合は、診断レポートを直接生成します。
パラメーターのマッピング
| 一般的なパラメーター | hcloud パラメーター | MCP パラメーター |
|---|---|---|
| リージョン | --cli-region | (MCP 接続に組み込み) |
| プロジェクト ID | --project_id | project_id |
| クラスター ID | --cluster_id | cluster_id |
| メトリクス名 | --metric_name | metric_name |
| 開始時刻 | --from | from_ts |
| 終了時刻 | --to | to_ts |
| ページネーションのオフセット | --offset | offset |
| ページネーションの上限 | --limit | limit |
| ソートフィールド | (未対応) | order_by |
| ソート順 | (未対応) | sort_by |
MCP ツール
| ツール名 | 用途 | 主なパラメーター |
|---|---|---|
dws_autopilot_get_clusters | クラスターリストを照会 | project_id, cluster_id, limit, offset |
dws_autopilot_get_hosts | ホスト情報を照会 | project_id, cluster_id, limit, offset |
dws_autopilot_get_metric | メトリクスデータを照会 | project_id, cluster_id, metric_name, from_ts, to_ts, limit, offset, order_by, sort_by |
metric_data パラメーターに関する注意:metric_data は instance_name によるフィルタリングに対応していません(該当するパラメーターはありません)。クエリはクラスター全体のデータを返すため、対象インスタンスを絞り込むには inst_name フィールドでフィルタリングする必要があります。metric_data は period パラメーターに対応していません(サンプリング期間はプラットフォームによって自動的に決定されます)。
使用可能な metric_name:IOStat、CpuStat、cpu_io_diagnose_detail、business_concurrency、business_query_monitor、business_thread_wait、bussiness_conflict_lock
時刻の仕様:from_ts/to_ts には Unix のミリ秒タイムスタンプを使用する必要があります。すべての時刻は UTC タイムゾーンです。推奨する時間範囲は、アラーム時刻の 5 分前からアラーム時刻までです(from_ts = first_alarm_time - 300000)。
戻り値の形式:成功時は {"code": 0, "data": [...]}、失敗時は {"code": -1, "message": "error description"} です。失敗した場合は 1 回再試行し、それでも失敗する場合は縮退パスを使用し、レポートで「利用不可」と記載してください。
メトリクスごとの主なフィールド:
- IOStat:ctime, host_id, disk_name, io_data{util, await, r_await, w_await, r_s, w_s, read_iops, write_iops, rMB_s, wMB_s, read_throughput, write_throughput, avgrq_sz, avgqu_sz} → I/O の主要なメトリクス
- CpuStat:ctime, host_id, cpu_data{usr, sys, idle, iowait} → iowait > 30% は大きな I/O 負荷を示します
- cpu_io_diagnose_detail:ctime, host_id, active_queries[{query, query_id, userName, cpu_rate, state, inst_name, duration_ms}], io_stats{read_iops, write_iops, read_throughput, write_throughput} → I/O 診断の詳細と実行中のクエリ
- business_concurrency:ctime, concurrency_value, active_connections → ビジネスの同時実行数
- business_query_monitor:ctime, query, query_id, username, duration_ms, host_id → 過去のリアルタイムクエリ
- business_thread_wait:ctime, wait_event, count, username, host_id → 待機イベント(wait wal sync、WALWriteLock など)
- bussiness_conflict_lock:ctime, lock_type, blocker, waiter, username, host_id → ロック競合
手順ごとのクエリの違いについては、メトリクスリファレンスを参照してください。
ページネーションの仕様
すべてのツール呼び出し(MCP と hcloud)では、単一の応答が大きくなりすぎてトークン制限を超えないよう、ページネーションを使用してクエリを実行する必要があります。
ページネーションのルール:
- 一律に
limit=200を使用します(800 やその他の大きな値は使用しないでください) - 1 ページ目は
offset=0とします。返されたデータ件数が 200 件の場合は、offset+=200としてクエリを続けます - 返されたデータ件数が 200 件未満になるまで繰り返し、すべてのページのデータを結合します
- 結合時は、すべてのページのデータ配列を連結して完全なデータセットを作成します
MCP 呼び出し例(IOStat を使用):
Page 1: dws_autopilot_get_metric(project_id, cluster_id, metric_name="IOStat", from_ts, to_ts, limit=200, offset=0)
If returned data length = 200:
Page 2: dws_autopilot_get_metric(project_id, cluster_id, metric_name="IOStat", from_ts, to_ts, limit=200, offset=200)
If returned data length < 200: Stop pagination, merge page 1 + page 2 data
hcloud 呼び出し例(IOStat を使用):
Page 1: hcloud DWS ListMetricsData --cli-region=<region> --cluster_id=<id> --metric_name=IOStat --project_id=<pid> --offset=0 --limit=200 --from=<from_ts> --to=<to_ts>
If returned data count = 200:
Page 2: hcloud DWS ListMetricsData --cli-region=<region> --cluster_id=<id> --metric_name=IOStat --project_id=<pid> --offset=200 --limit=200 --from=<from_ts> --to=<to_ts>
If returned data count < 200: Stop pagination, merge data
ワークフロー
診断の前に、ステップ 0~7 に基づいて実行計画を作成し、その後順番に実行してください。ツールの選択戦略については、「KooCLI コマンド形式の標準」セクションを参照してください。以降のステップでは、この説明を繰り返しません。すべての MCP ツール呼び出しでは、「ページネーションの仕様」セクションに従ってください。以降のステップでは、ページネーションの詳細を繰り返しません。
ステップ 0:環境の検出とパラメーターの解決
パラメーターの解決:ユーザーから project_id または region_id が指定されていない場合は、MCP サーバーの設定ファイル conf/dws_config.yaml から読み取ります。
project_idが指定されていない場合:python -c "import yaml; c=yaml.safe_load(open('conf/dws_config.yaml')); print(c.get('project_id',''))"を実行して取得しますregion_idが指定されていない場合:python -c "import yaml; c=yaml.safe_load(open('conf/dws_config.yaml')); print(c.get('region_id',''))"を実行して取得します- 設定ファイル内の該当フィールドも空の場合は、ユーザーにパラメーターの入力を求めます
hcloud version を実行します。バージョンが 3.2.0 以上の場合は tool_mode=hcloud、それ以外の場合は tool_mode=mcp とします。
hcloud のネットワーク接続確認:tool_mode=hcloud の場合、軽量な API 呼び出し(例:hcloud DWS ListClusters --cli-region=<region> --project_id=<project_id> --offset=0 --limit=1)を実行してネットワーク接続を確認します。
- 正常な応答、または業務エラー(例:権限不足、パラメーターエラー)が返された場合 → ネットワークは利用可能です。tool_mode=hcloud を維持します
- NETWORK_ERROR が返された場合 → ネットワークは利用できません。tool_mode=mcp に切り替えます
- 切り替え後も MCP が利用できない場合 → 実行を終了し、KooCLI のネットワーク設定または MCP サーバーの設定を確認するようユーザーに求めます
ステップ 1:IOStat のクエリ
metric_name="IOStat" でメトリクスクエリを呼び出します。時間範囲は from_ts=first_alarm_time - 300000、to_ts=first_alarm_time とします。MCP モードでは limit=200 でページネーション付きクエリを使用します。
Autopilot が利用できない場合の判定:50201/RDS.9999 エラーが返された場合は、ステップ 1~6 をスキップし、すべてのメトリクスを「利用不可」として、ステップ 7 に直接進みます。
解析:host_id と disk_name でグループ化し、各ノードの各ディスクについて最新の I/O データを特定します。各ディスクから util、await、r_await、w_await、r_s、w_s、read_iops、write_iops、rMB_s、wMB_s、read_throughput、write_throughput、avgrq_sz、avgqu_sz を抽出します。
I/O 過負荷の判定:いずれかのディスクで util > 90%、await > 100、またはスループット/IOPS が上限に達しているかを判定します。
I/O の偏りの判定:ノード間の util または await の偏差が 20% を超えているかを判定します。
TOP ノードのフィルタリング:I/O 負荷が最も高い 2 つのノードを特定します。
現象の分布の判定:あるノードで単一ディスクの I/O が高いのか、すべてのディスクの I/O が高いのかを判定します(ステップ 4 のシナリオ振り分けに使用)。
I/O 高負荷時点:IOStat の時系列データから、上位 2 つの I/O ノードでいずれかのディスクの util > 90% となっているすべての ctime 時点を特定します。これらの ctime 値をミリ秒単位のタイムスタンプのリストとして high_io_ctimes に収集します。また、util が最も高い ctime を peak_io_ctime として記録します。util > 90% となる ctime がない場合、high_io_ctimes は空にし、util 値が最も高い ctime を peak_io_ctime とします。
出力:io_by_host_disk、io_by_host、max_io_hosts、problem_host_id、problem_host_util、problem_host_await、problem_host_avgrq_sz、problem_host_avgqu_sz、cluster_avg_util、is_imbalanced、io_deviation、high_io_nodes、single_disk_high_nodes、all_disk_high_nodes、high_io_ctimes、peak_io_ctime
ステップ 2:ホスト名の取得
ホスト情報クエリを呼び出し(MCP モードでは limit=200 でページネーションを使用)、host_id → {host_name, ip} のマッピングテーブルを作成します。ステップ 1 の出力にある max_io_hosts に含まれるノードについてのみ、ホスト情報をクエリします。
出力:host_id_to_info_map、problem_host_ip、node_name
ステップ 3:CpuStat のクエリ
metric_name="CpuStat" でメトリクスクエリを呼び出します。MCP モードでは limit=200 でページネーション付きクエリを使用します。
解析:各ノードの iowait を抽出します。iowait > 30% は、顕著な I/O 負荷を示します。iowait が高く、CPU 使用率が低い場合は、典型的な I/O ボトルネックです。
出力:cpu_by_host、high_iowait_nodes
ステップ 4:3 段階の判定ツリーによる I/O シナリオの特定
ステップ 1 の IOStat データとステップ 3 の CpuStat データに基づき、3 段階の判定ツリーで I/O シナリオを特定します。
前提条件:await が継続的に 100 を超え、avgqu_sz も継続的に 100 を超えていますか?
- いいえ → await/avgqu_sz の一時的なスパイクは正常です。シナリオの特定は不要で、正常としてマークします
- はい → 3 段階の判定に進みます
第 1 段階:明確な I/O 異常 — IOPS とスループットが最小仕様を大幅に下回っていますか?
- SSD:rMB/s+wMB_s << 900MB/s かつ r/s+w/s << 8000/s
- HDD:rMB/s+wMB_s << 250MB/s かつ r/s+w/s << 1000/s
- はい → I/O 異常を確定(ハードウェアの問題が明らか)
第 2 段階:明確な I/O 過負荷 — IOPS またはスループットが最大仕様を超えていますか?
- SSD:rMB/s+wMB_s > 3500MB/s または r/s+w/s > 20000/s
- HDD:rMB/s+wMB_s > 800MB/s または r/s+w/s > 2000/s
- はい → I/O 過負荷を確定(スループット過負荷/IOPS 過負荷/両方の過負荷を区別)
- スループットのみが最大値を超過 → I/O スループット過負荷
- IOPS のみが最大値を超過 → IOPS 過負荷
- 両方が最大値を超過 → 両方の過負荷
第 3 段階:グレーゾーン — I/O が最小仕様に近いか、最小仕様を超えているものの最大仕様を下回っていますか?
- 1 台のディスクのパフォーマンスが低く(await/avgqu_sz が高い)、他のディスクは正常 → I/O 異常と判定
- 1 台のディスクの I/O 量が多く(スループット/IOPS が高い)、他のディスクは正常 → I/O 過負荷と判定
- すべてのディスクのパフォーマンスが一貫している → 他のノードの I/O と比較
- 他のノードに I/O 負荷があるが、I/O 待ちがない → このノードのI/O 異常と判定
- 他のノードに I/O 負荷と待ちがある/他のノードに I/O 負荷も待ちもない → 明確な判定はできません。I/O 過負荷と I/O 異常の両方について、完全な調査方法を提示する必要があります
- 他のノードのデータを取得できない → 比較用に他のノードの iostat を提示するようユーザーに提案し、両方の完全な調査方法も提示する必要があります
現象の分布の判定(ステップ 1 の IOStat データに基づき、host_id と disk_name のディメンションで分析):
- 単一ノード+単一ディスクの I/O が高い:1 つのノードにある 1 台のディスクのみで I/O 異常が発生し、そのノードの他のディスクは正常または低負荷 → データ偏り/ディスク故障
- 単一ノード+すべてのディスクの I/O が高い(過負荷タイプ):1 つのノードのすべてのディスクでスループット/IOPS が上限を超過 → ノードレベルの異常を優先的に疑います(RAID カードの読み書き戦略の劣化/RAID カードの CC 検証/RAID カードの故障)。DWS のデータ分散はディスク単位であり、すべてのディスクが同時に過負荷になることはないためです。可能性 B として I/O 過負荷の調査方法も提示します
- 単一ノード+すべてのディスクの I/O が高い(異常タイプ):1 つのノードのすべてのディスクでスループット/IOPS が上限を下回っているものの、await が極端に高い → I/O 異常(単一ノード+すべてのディスク)に振り分けます
- 複数ノード/すべてのノードで、すべての DN データディスクの I/O が高い → ビジネスレイヤーの過負荷(全表スキャン、バッチインポートなど)
- システムディスクの I/O が高い → pg_log ログ/pg_audit 監査ログ/システムレベルのタスク
I/O タイプの判定(過負荷シナリオの振り分け用):
- wMB/s >> rMB/s → 書き込み I/O が優勢
- rMB/s >> wMB/s → 読み取り I/O が優勢
出力:io_scenario、io_type、phenomenon_distribution、is_gray_zone、gray_zone_result
ステップ 5:ビジネスの同時実行数と I/O 診断の詳細を照会
5a:ビジネスの同時実行数を照会
metric_name="business_concurrency" を指定してメトリックを照会します。MCP モードでは、limit=200 を指定してページネーションによる照会を行います。
出力:max_concurrency、avg_concurrency、is_high_concurrency
5b:上位 2 ノードの I/O 診断の詳細を照会
dws_service_autopilot_metric_data を呼び出します。パラメーターはステップ 3 と同じですが、metric_name を "cpu_io_diagnose_detail" に変更します。注:metric_data では host_id によるフィルタリングはサポートされていません。クラスター全体のデータを照会した後、上位 2 つの I/O ノードの host_id で絞り込みます。
ページネーション付きクエリ:このメトリクスのデータ量は最も多く(複数ノード × 複数インスタンス × 複数時点 × 複数クエリ)、1 ページあたり 800 件では足りない可能性があります。最初のページでは offset=0、limit=800 を指定します。返されたデータ件数が 800 件の場合は、offset+=800 としてクエリを続けます。返されたデータが 800 件未満になったら、ページネーションで取得したすべてのデータを結合します。
IO 負荷が高い時間帯によるフィルタリング:返されたデータから、ctime ∈ {{steps.iostat_metrics.output.high_io_ctimes}} に該当するサンプリングポイントのみを残し、通常の時間帯の無関係なクエリを除外します。high_io_ctimes が空(IO 負荷が高い時点がない)の場合は、util が最も高い時点のデータを取得し、「IO が継続的にしきい値を超えていません。以下は IO 負荷が最も高かった時点のクエリの参考情報です」と注記します。
返されたデータを解析し、各ノードについて以下を抽出します。
- 実行中のクエリ文の一覧(SQL)
- 実行ユーザー(userName)
- クエリの実行時間(duration_ms)
- SQL ごとの IO 消費量(pidstat -t -d で収集した io_read、io_write)
- IO 統計(io_stats: read_iops、write_iops、read_throughput、write_throughput)
- ロック待機の状態
ディスクへのスピル判定ルール:実行中の文の特徴に基づいて推定し、以下のいずれかの条件を満たす場合は spill_detected=true とします。
- SQL 文に複数テーブルの JOIN とソート(ORDER BY)/集計(GROUP BY/DISTINCT)処理が含まれ、書き込み IO が読み取り IO を大幅に上回る場合(io_data_available=true のとき、io_write >> io_read、または io_stats.write_throughput が異常に高い)
- business_thread_wait に
wait file write待機イベントが含まれる - 該当する SQL を
full_scan_queriesに記録します(このフィールドを再利用してスピル SQL を記録)。spill_info には、最初に検出されたスピル SQL の詳細を記録します。
フルテーブルスキャン判定ルール:実行中の文の特徴に基づいて推定し、以下の条件を満たす場合は full_scan_detected=true とします。
- SQL 文が大規模テーブルに対する SELECT /COUNT()/MAX/MIN などの集計クエリであり、WHERE 条件による絞り込みが不十分な場合(WHERE 句がない、または非等価条件のみ)
- 該当する SQL を
full_scan_queriesに記録します
データ偏りの推定ルール:IOStat のノード間 IO 偏差に基づく、確定的ではない判定です。
- IOStat で、あるノードの util が他のノードより大幅に高く(偏差 > 20%)、そのノードの実行中クエリが少数のテーブルに集中している場合は、
is_data_skewed=trueとします - skew_info には、偏差が最も大きい 2 つのノードと偏差の割合を記録します。説明には「ノード間 IO 偏差から推定されたデータ偏りの可能性があります。テーブルの分散列を確認することを推奨します」と注記します IO 貢献度 TopN 統計ルール(時間ウィンドウ集計。DMS の監視項目ロジックに準拠):
- データ利用可否の判定:すべての active_queries の io_read/io_write フィールドを確認し、すべてが 0、またはフィールドが存在しない場合は、
io_data_available=falseとします。注:io_data_available=true となるケースはまれです(クラスターノードに pidstat 収集プラグインがデプロイされ、正常に収集できている場合に限り、io_read/io_write に 0 以外の値が入ります。ほとんどの場合、このフィールドは 0 です)。そのため、通常は io_data_available=false です - フィルターしきい値(DMS プラグインのフィルターロジックに準拠。io_read/io_write の単位は kB/s):
cpu_rate < 20%ANDio_read < 1024ANDio_write < 1024の場合に限り、その行を除外します(AND 条件です。3 つすべてがしきい値未満の場合に除外し、いずれか 1 つでもしきい値を超えていれば残します)。残った行を TopN 統計に使用します - Ruby ユーザーのフィルタリング:userName が "Ruby" の行は TopN の並べ替えに含めません(DMS の監視項目ロジックに準拠)。Ruby の IO 消費量は、システム側の根本原因の説明に反映されます
- サンプリングポイントをまたぐ集計:query_id ごとにグループ化し、IO 高負荷時間帯の複数のサンプリングポイントを集計します(io_read/io_write はレート値 kB/s です):
- IO 合計:Σ(io_read + io_write)。時間ウィンドウ内の累積 IO 貢献度を表します
- CPU 合計:Σ(cpu_rate)。時間ウィンドウ内の累積 CPU 負荷を表します
- 出現頻度:この SQL が出現したサンプリングポイント数 / IO 高負荷時間帯の総サンプリングポイント数(例:3/3)。継続性を表します
- TopN SQL IO 貢献度:
- io_data_available=true の場合:SQL ごとに集計した行(lwtid が空でなく、userName が "Ruby" ではないもの)から、IO 合計の降順で上位 3 件を選び、出現頻度の降順で二次ソートします。query_preview、query_id、userName、total_io_read、total_io_write、frequency、cpu_rate、io_characteristic を抽出します
- io_data_available=false の場合:SQL ごとに集計した行(lwtid が空でなく、userName が "Ruby" ではないもの)から、CPU 合計の降順で上位 3 件を選び、出現頻度の降順で二次ソートします。query_preview、query_id、userName、total_cpu_rate、frequency、cpu_rate、io_characteristic を抽出します。「IO 消費データが利用できないため、参考値として CPU 使用率順で並べ替え」と注記します
- TopN ユーザー IO 貢献度:
- io_data_available=true の場合:ユーザーごとに集計した行(lwtid が空で、userName が空でなく、かつ "Ruby" ではないもの)から、IO 合計の降順で上位 3 件を選び、出現頻度の降順で二次ソートします。userName、total_io_read、total_io_write、frequency を抽出します
- io_data_available=false の場合:ユーザーごとに集計した行(lwtid が空で、userName が空でなく、かつ "Ruby" ではないもの)から、CPU 合計の降順で上位 3 件を選び、出現頻度の降順で二次ソートします。userName、total_cpu_rate、frequency を抽出します。「IO 消費データが利用できないため、参考値として CPU 使用率順で並べ替え」と注記します
時刻の注記ルール:cpu_io_diagnose_detail が返す ctime は Autopilot の収集スナップショット時刻であり、SQL の実際の開始時刻ではありません。active_queries に duration_ms フィールドがある場合、SQL 開始時刻 = ctime - duration_ms とし、「開始時刻」と注記します。duration_ms が利用できない場合は ctime をそのまま使い、「収集時刻」と注記します(収集時刻を「開始時刻」と注記しないでください)。
アクティブユーザー統計ルール:state=active のユーザーと接続のみをカウントし、idle 状態はカウントしません。userName ごとにグループ化してアクティブなクエリ数を数え、上位ユーザーを特定します。
出力(steps.top_node_io_diagnose.output):
io_query_details: # Node IO query details [{host_id, queries, io_stats}]
spill_detected: # Whether spill to disk is detected (boolean)
spill_info: # Spill information {query, query_id, username, host_id, io_write_rate}
full_scan_detected: # Whether full table scan is detected (boolean)
full_scan_queries: # Full table scan query list [{query, query_id, username, host_id, duration_ms}]
is_data_skewed: # Whether data skew is possible (inferred from IOStat inter-node deviation, non-confirmatory) (boolean)
skew_info: # Skew inference information {max_deviation_node, min_deviation_node, deviation_pct, description} (inferred from IOStat inter-node IO deviation, marked when deviation > 20%, cannot confirm specific table names)
topn_sql_io: # Top3 SQL IO contribution (time window aggregation) [{query_preview, query_id, user_name, total_io_read, total_io_write, frequency, cpu_rate, io_characteristic}]
topn_user_io: # Top3 User IO contribution (time window aggregation) [{user_name, total_io_read, total_io_write, frequency}]
io_data_available: # Whether io_read/io_write data is available (boolean)
peak_io_ctime: # Highest util time point ctime in high IO time period
5c:クエリ待機イベントとロック競合
metric_name="business_thread_wait" および metric_name="bussiness_conflict_lock" を指定してメトリッククエリを実行します。MCP モードでは、limit=200 を指定してページネーション付きのクエリを使用します。
解析:I/O 関連の待機イベント(例:wait wal sync、WALWriteLock、I/O wait)を特定します。I/O 異常の原因となるロック競合を特定します。
出力:wait_events、io_wait_detected、lock_conflicts、lock_conflict_detected
ステップ 6:診断結果の分析
ステップ 1~5 で収集したデータに、ステップ 4 の 3 段階判定ツリーの結果と現象分布を組み合わせ、該当するシナリオに振り分けて、調査方針の全項目を分析します。
時刻の形式:すべての Unix ミリ秒タイムスタンプ(first_alarm_time、ctime など)は UTC タイムゾーンです。レポートでは、北京時間(UTC+8)の文字列 YYYY-MM-DD HH:MM:SS に変換する必要があります。python -c "from datetime import datetime,timezone,timedelta; print(datetime.fromtimestamp({ms}/1000,tz=timezone(timedelta(hours=8))).strftime('%Y-%m-%d %H:%M:%S'))" を使用できます。タイムスタンプの値を暗算しないでください。
ユーザーの判定(データベースユーザーに基づきます。つまり、cpu_io_diagnose_detail の username です):
- データベースユーザーが「omm」または「Ruby」→ システム側の原因
- データベースユーザーが「omm」でも「Ruby」でもない → 顧客側の原因
シナリオの振り分けと調査方針の全項目
ステップ 4 の io_scenario と phenomenon_distribution に基づいて該当するシナリオに振り分け、調査を実施します。完全なシナリオ振り分け表、調査方針の一覧、顧客側/システム側の原因の説明、出力例については、必ず IO_DIAGNOSIS_REF.md を読んでください。以下のシナリオ概要だけに基づいて分析してはいけません。
シナリオ概要:
- シナリオ 1:I/O スループット過負荷 → 読み取り I/O/書き込み I/O に基づいて振り分け、サブシナリオは現象分布に基づいて振り分けます
- シナリオ 2:IOPS 過負荷 → 読み取り I/O/書き込み I/O に基づいて振り分け、断片化 I/O を調査します(avgrq_sz<30)。サブシナリオは現象分布に基づいて振り分けます
- シナリオ 3:I/O 異常 → ハードウェア層を調査します(RAID カード/I/O スケジューラー)。アクティブなステートメントには依存しません
- シナリオ 4:二重過負荷 → シナリオ 1 とシナリオ 2 の調査方針を統合し、重複する方針を取り除きます
- グレーゾーン → I/O 過負荷と I/O 異常の調査方針を、どちらもすべて出力します
総合判定ルール:
| 条件 | 判定項目 |
|---|---|
| problem_host_util > 90% | ディスク使用率が高すぎる |
| problem_host_await > 100 | I/O 応答時間が長すぎる |
| io_deviation > 20% | クラスターの I/O 負荷が不均衡で、データ偏在の可能性があります |
| is_high_concurrency = true and spill_detected = true | 高い同時実行性によるディスクへのスピルが I/O 高負荷を引き起こしています |
| full_scan_detected = true | 全表スキャンが I/O 高負荷を引き起こしており、該当するステートメントが特定されています |
| io_wait_detected = true | I/O 関連の待機イベントが検出されています |
| lock_conflict_detected = true | ロック競合が I/O パフォーマンスに影響しています |
| 統計および集計要件: |
- io_data_available=true の場合:Step 5b の時間範囲集計結果を使用します(高 I/O 負荷期間のサンプリングポイントを query_id ごとに集計し、第一ソートキーは Σ(io_read+io_write) の降順、第二ソートキーは出現頻度の降順)。Top3 の SQL と Top3 のユーザー別 I/O 寄与をそれぞれ取得します。フィルターのしきい値(AND 条件):cpu_rate<20% かつ io_read<1024kB/s かつ io_write<1024kB/s の場合に限り、その行を除外します。Ruby ユーザーは TopN のソート対象に含めません。その I/O 消費量はシステム側の根本原因の説明に反映します(例:「システムユーザー Ruby の autovacuum タスクにより I/O が高負荷」)。レポートに【I/O 寄与 Top3 SQL】と【I/O 寄与 Top3 ユーザー】を出力し、合計 I/O(kB。レポートでは MB に換算)と出現頻度を含めます。TopN の SQL 項目には I/O の特性(スピル/全表スキャン/高い I/O 待機などの定性的な説明)を含め、同じ SQL が重複して表示されないよう、独立した【I/O 関連の異常クエリ】セクションは設けません。
- io_data_available=false の場合(io_read/io_write がすべて 0、または存在しない場合):Step 5b の時間範囲集計結果を使用しますが、合計 I/O ではなく Σ(cpu_rate) の降順でソートし、Top3 の SQL と Top3 のユーザー別寄与を取得します。フィルターのしきい値:cpu_rate<20% の場合に限り、その行を除外します。Ruby ユーザーは TopN のソート対象に含めません。レポートに【I/O 寄与 Top3 SQL】と【I/O 寄与 Top3 ユーザー】を出力し、「I/O 消耗データを利用できないため、参考情報として CPU 使用率順にソート」と注記します。TopN の SQL 項目には query_preview、query_id、userName、total_cpu_rate、frequency、cpu_rate、io_characteristic を含めます。TopN のユーザー項目には userName、total_cpu_rate、frequency を含めます。さらに、検出された I/O 関連の現象を調査の方向性として説明します。これらは I/O 消費量の定量的な証拠ではなく、可能性に基づく推測であるため、「調査の方向性」と注記します。
- gaussdb プロセスの I/O オーバーヘッドは、独立した項目として列挙せず、対応する根本原因の説明に統合します。
異常なしの判定:Step 4 の 3 段階の判定ツリーにより I/O シナリオが正常と判定された場合(つまり、シナリオ判定が不要で、util が 90% を大幅に下回り、await が 100ms を大幅に下回り、iowait が 30% を大幅に下回る場合)、io_scenario=normal とし、シナリオの振り分けは不要です。診断結果は「診断で異常は検出されませんでした」とします。この場合:
root_cause_category= "normal"、io_scenario= "normal"、その他すべてのフラグ(spill_detected、full_scan_detected、io_wait_detected、lock_conflict_detected、is_data_skewed)= falseio_investigation_info= 空topn_sql_ioとtopn_user_ioは Step 5b の TopN 統計ルールに従って引き続き計算しますが、根本原因の証拠ではなく参考情報として注記します。- レポートの「問題ノードの I/O 概要」テーブルは、しきい値を超えるノードがないため、空(行なし)にします。
- 「I/O 関連の異常クエリおよび調査情報」セクションには、調査の方向性ではなく、現在アクティブなクエリの参考情報を表示し、「I/O に異常は検出されませんでした。以下は現在アクティブなクエリの参考情報です」と注記します。
- 「I/O 寄与 Top3 SQL」および「I/O 寄与 Top3 ユーザー」セクションには、異常シナリオと同じ io_data_available=true/false の表示ルールに従って、現在アクティブなクエリ/ユーザーの参考情報を表示します。ただし、根本原因の証拠ではなく参考情報として注記します。
出力:root_cause_category、io_scenario、phenomenon_distribution、io_type、summary、specific_sql、is_data_skewed、spill_detected、full_scan_detected、io_wait_detected、lock_conflict_detected、io_investigation_info、topn_sql_io、topn_user_io、io_data_available
ステップ 7:診断レポートの生成
「出力形式」セクションのテンプレートに従って HTML レポートを生成します。レポートを生成した後、HTML ファイルを現在の作業ディレクトリ(ワークスペースのルートフォルダー)に保存してください。ファイル名は dws_io_diagnosis_report_{timestamp}.html とし、{timestamp} は現在のマシンのローカル時刻を yyyyMMdd_HHmmss 形式で指定します(例:dws_io_diagnosis_report_20260623_150421.html)。
HTML レポートに加えて、{{diagnosis_json}} データ構造も出力します。完全なデータ構造、content フィールドの形式ルール(io_data_available=true/false)、システム側/異常なしの例、および Ruby ユーザーの制約については、diagnosis_json 形式リファレンスを必ず確認してください。
異常がない場合のレポートセクション記入ルール:
io_scenario=normal(診断結果が「異常は検出されませんでした」の場合):diagnosis_summary:<div class="conclusion-item normal">诊断暂未发现异常</div><div class="conclusion-item normal">诊断时间范围: {from_time} ~ {to_time}</div>を出力します- 問題ノード I/O 概要テーブル:ヘッダー行のみ出力し、データ行は出力しません(しきい値を超えるノードがないため)
io_investigation_content:現在アクティブなクエリの参照情報を表示し、「IO未发现异常,以下为当前活跃查询参考信息」と注記します。異常シナリオと同じ io_data_available=true/false の表示ルールに従いますが、「IO排查方向」を「IO参考信息」に置き換え、調査の方向性ではなく参考情報として注記しますtopn_sql_io_contentとtopn_user_io_content:異常シナリオと同じ io_data_available=true/false の表示ルールに従いますが、根本原因の証拠ではなく参考情報として注記しますdiagnosis_json:content ="诊断暂未发现异常"、addition.advice ="暂无"
io_scenarioが normal ではない場合(異常が検出された場合):- 問題ノード I/O 概要テーブル:I/O がしきい値を超えるノードのみを記載し、正常なノードは記載しません
io_investigation_content:io_data_available=true/false のルールに従って記入します
主なコマンド
クラスター一覧の照会
# hcloud
hcloud DWS ListClusters --cli-region=<region> --project_id=<pid> --offset=0 --limit=200
# MCP
dws_autopilot_get_clusters(project_id=<pid>)
ホスト情報の照会
# hcloud
hcloud DWS ListHostOverview --cli-region=<region> --project_id=<pid> --offset=0 --limit=200
# MCP
dws_autopilot_get_hosts(project_id=<pid>, cluster_id=<cid>, limit=200, offset=0)
メトリクスデータの照会(一般形式)
# hcloud
hcloud DWS ListMetricsData --cli-region=<region> --cluster_id=<cid> --metric_name=<name> --project_id=<pid> --offset=0 --limit=200 --from=<from_ts> --to=<to_ts>
# MCP
dws_autopilot_get_metric(project_id=<pid>, cluster_id=<cid>, metric_name=<name>, from_ts=<from>, to_ts=<to>, limit=200, offset=0, order_by="ctime", sort_by="desc")
パラメーターの確認
| パラメーター | 必須/任意 | 説明 | デフォルト |
|---|---|---|---|
| alarm_serial_number | 必須 | アラームのシリアル番号 | N/A |
| cluster_id | 必須 | クラスター ID | N/A |
| first_alarm_time | 必須 | 初回アラーム時刻(ミリ秒単位のタイムスタンプ) | N/A |
| alarm_name | 必須 | アラーム名 | N/A |
| project_id | 任意 | プロジェクト ID | MCP Server の設定ファイル(conf/dws_config.yaml)の project_id フィールドから読み取ります |
| region_id | 任意 | リージョン識別子 | MCP Server の設定ファイル(conf/dws_config.yaml)の region_id フィールドから読み取ります |
| node_name | 任意 | アラート対象ノード名 | 空(クラスター単位のアラーム) |
| cluster_name | 任意 | クラスター名 | cluster_id を使用します |
| alarm_severity | 任意 | アラームの重大度 | N/A |
パラメーター解決ルール:ユーザーから project_id または region_id が指定されていない場合は、MCP Server の設定ファイル conf/dws_config.yaml から読み取ります。
project_id:conf/dws_config.yamlのproject_idフィールドを読み取りますregion_id:conf/dws_config.yamlのregion_idフィールドを読み取ります- 読み取り方法:project_id には
python -c "import yaml; c=yaml.safe_load(open('conf/dws_config.yaml')); print(c.get('project_id',''))"を、region_id にはpython -c "import yaml; c=yaml.safe_load(open('conf/dws_config.yaml')); print(c.get('region_id',''))"を使用します
出力形式
出力形式 のテンプレートに厳密に従って出力し、返してください。テンプレートの内容を分析または要約したり、一部を省略したり、テンプレートの構造を変更したりしないでください。出力はテンプレートと一致している必要があります。
ベストプラクティス
- タイムスタンプの処理:first_alarm_time はすでにミリ秒単位のタイムスタンプです。ツールのパラメーターにはそのまま使用してください。最初に時刻文字列へ変換してからタイムスタンプへ戻すことは避けてください(8時間のずれを防ぐため)。
- ツールの選択:KooCLI と MCP のどちらかを選択し、KooCLI を優先してください。選択後は、その方法を一貫して使用してください。
- ページネーション付きクエリ:すべてのツール呼び出しでは、取得件数が 200 未満になるまで limit=200 でページネーションを行い、すべてのページのデータを統合してください。例外として、cpu_io_diagnose_detail では、取得件数が 800 未満になるまで limit=800 でページネーションを行い、すべてのページのデータを統合してください(データ量が最も多いため)。
- レポート時刻:すべてのタイムスタンプを北京時間(UTC+8)に変換してください。次のコマンドを使用できます:
python -c "from datetime import datetime,timezone,timedelta; print(datetime.fromtimestamp({ms}/1000,tz=timezone(timedelta(hours=8))).strftime('%Y-%m-%d %H:%M:%S'))" - SQL の表示:I/O 関連の異常クエリでは、具体的な SQL を最大 1024 文字まで表示し、超える場合は「...」で省略してください。diagnosis_summary の SQL 要約は最大 50 文字です。
- I/O 閾値の判定:I/O 閾値は RAID グループの仕様に基づきます。iostat の各 sdX デバイスは 1 つの RAID グループに対応します。閾値は RAID グループ全体の性能仕様として設定されているため、ディスク数を掛けずに直接比較してください。
- スループットと IOPS の独立した判定:両方が同時に過負荷になる場合があります。それぞれを独立して判定してください。スループットが過負荷でなく、IOPS が過負荷の場合は、IOPS の過負荷のみであり、両方が過負荷ではありません。
- 異常の特徴:スループットと IOPS が一時的に最大値に達していても、await が継続的に高い場合は、過負荷よりも I/O 異常の判定を優先してください。
参考資料
| ドキュメント | 説明 |
|---|---|
| CLI インストールガイド | KooCLI のインストールと設定 |
| MCP インストールガイド | DWS Autopilot MCP サーバーのインストールと設定 |
| IAM ポリシー | 必要な権限とポリシー JSON |
| メトリクスリファレンス | メトリクスのキー項目とクエリの違い |
| I/O の基礎知識 | RAID アーキテクチャ、I/O 閾値、シナリオの特徴、重要な原則 |
| 出力形式 | HTML テンプレートと入力ルール |
| diagnosis_json 形式 | diagnosis_json のデータ構造、content フィールドの形式ルール、Ruby ユーザーの制約 |
| I/O 診断リファレンス | シナリオのルーティング表、調査の方向性、出力例 |
注意事項
- セキュリティ:AK/SK の値を会話やコマンドで公開しないでください。また、ユーザーに会話で AK/SK を直接入力するよう求めないでください
- 時刻プロトコル:from_ts/to_ts はミリ秒単位のタイムスタンプを使用する必要があります。レポートでは北京時間を表示します。北京時間をタイムスタンプに変換する場合は、タイムゾーンサフィックス +08:00 を必ず付けてください。タイムスタンプの値を暗算しないでください。既存のミリ秒単位のタイムスタンプを時刻文字列に変換してから、再変換しないでください
- 出力制約:「出力形式」セクションのテンプレートに従って診断レポートを厳密に出力してください。テンプレートの構造を変更せず、いかなる部分も省略せず、改善提案を追加せず、SQL の最適化文を出力せず、絵文字を使用せず、独自の書式タグを使用しないでください
- データの真正性:診断結果はすべて、実際のツールの戻り値に基づく必要があります。ツールの戻り値が空の場合、または呼び出しに失敗した場合は、「获取できません」と記載してください。値を捏造することは禁止されています
- 既知の制限事項:hcloud は --order_by および --sort_by パラメーターをサポートしていません。クエリ後、ローカルで ctime の降順に並べ替えてください。cpu_io_diagnose_detail は host_id によるフィルタリングをサポートしていません。クラスター全体をクエリしてから、ローカルでフィルタリングしてください。cpu_io_diagnose_detail はフラットな行構造(1 クエリにつき 1 行)を返し、ネストされた active_queries 配列は返しません。iostat では、シーケンシャル I/O とランダム I/O の比率を正確に区別できません。iostat の各 sdX デバイスは 1 つの RAID グループに対応し、しきい値は RAID グループ全体の性能仕様です。io_data_available=false が通常の状態です(pidstat 収集プラグインがデプロイされていない場合、io_read/io_write は 0 になります)。TopN の並べ替えが意味を持つのは、io_data_available=true の場合のみです
- RAID アーキテクチャ:システムディスクは 2 台のディスクによる RAID1(ミラーリング)で構成され、仕様は RAID グループ全体の性能を示します。データディスクは 4~6 台のディスクによる RAID5(パリティ)で構成され、仕様は RAID グループ全体の性能を示します。DWS のデータ分散はディスク単位です。データの偏りによって過負荷になるのは単一のディスクのみで、すべてのディスクが同時に過負荷になることはありません