kibana-anomaly-detection について
kibana-anomaly-detectionは、Elastic MLの異常検知を調査・運用するためのスキルです。インシデントの原因特定、スコアの解釈、トラブルシューティング、ジョブ管理を支援し、Elasticsearch操作にはelastic CLIを使用します。
主な機能
- 01複数ジョブを関連付け異常エンティティを特定
- 02スコア、モデル動作、再正規化を説明
- 03ジョブ、データフィード、ライフサイクルの診断
- 04ジョブの作成と異常結果の取得
活用シーン
- 01複数の検知ジョブにまたがるインシデント調査
- 02異常スコアの上昇や低下の原因分析
- 03ドキュメント欠落や停止したデータフィードの診断
- 04異常検知ジョブの設定と結果確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ elastic/ agent-skills --skill kibana-anomaly-detectionインストール後、Claude Code で/kibana-anomaly-detectionを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/agent-builder-companion.mdanomaly-detection-functions.mdinvestigation-queries.mdjob-creation-recipes.mdobservability-anomaly-expert.mdREADME.mdscore-reference.mdsecurity-anomaly-expert.mdtroubleshooting-reference.mdworked-example.mdreferences/protocols/investigation.md詳細
Elastic ML 異常検知
ML 異常検知のエキスパート向けプロセス:インシデントをエンティティに帰属させ、スコアとモデルの動作を説明し、ジョブのライフサイクル障害を診断して、ジョブを管理します。異常の結果は POST /.ml-anomalies-*/_search(Serverless 対応)から、ジョブ/データフィードの状態は ML REST API から読み取ります。ユーザーがプロンプトにフィクスチャの証拠(インフルエンサーの行、ジョブ統計など)を埋め込んでいる場合は、以下の判断をそのまま適用してください。すでに提示されているフィールドを再取得しないでください。
環境設定
このスキルは elastic CLI を通じて Elasticsearch を操作します。
elastic CLI がインストールされていない場合は、何に必要なのかをユーザーに伝えてください。認証情報を推測したり、HTTP API を直接呼び出したり、ほかの回避策を試したりしないでください。
このスキルでは、HTTP の省略記法(例:GET /、GET /_cat/indices、GET /{index}/_mapping、GET /{index}/_settings/index.mode、POST /_query)で操作を記載しています。このドキュメント末尾の操作表で、各省略記法に対応する elastic CLI コマンドを確認できます。HTTP API を直接呼び出すのではなく、必ず CLI を使用してください。
モードの選択
| ユーザーの意図 | モード |
|---|---|
| 「何が壊れましたか?」/RCA/ジョブ横断/影響範囲/インフルエンサー/ログカテゴリー | Investigate |
| 「スコアが高い/低いのはなぜですか?」/再正規化/モデルの境界値/予測 | Explain |
| ドキュメント欠落/メモリ制限/データフィード停止/ライフサイクル/カレンダー | Troubleshoot |
| ジョブの作成/データフィードの設定/分析の開始/結果の取得 | Manage |
| セキュリティの観点(攻撃チェーン、MITRE、データ窃取) | Investigate + references/security-anomaly-expert.md |
| オブザーバビリティ/SRE の観点(劣化、キャパシティ、デプロイ回帰) | Investigate + references/observability-anomaly-expert.md |
質問が複数のモードにまたがる場合:Investigate → Explain → Troubleshoot。ロジックを組み合わせる前に、各モードを完了してください。
Serverless に関する注意: レガシーの
/_ml/anomaly_detectors/{job_id}/results/*エンドポイントは Serverless では HTTP 410 を返します。result_typeフィルターを指定してPOST /.ml-anomalies-*/_search経由で.ml-anomalies-*を必ずクエリしてください。
スコアのクイックリファレンス
record_scoreの範囲:>75 重大 · 50–75 警告 · 25–50 軽微 · <25 情報multi_bucket_impact ≥ 3→ 持続的なシフト(突発的なスパイクではありません)initial_record_score >> record_score→ 再正規化(モデルが後にさらに深刻な異常を検知)actual << typicalにcount/low_count/low_meanが伴う場合 → 単なる低値ではなく、欠落/停止です- 1つのジョブの高スコアより、多数のジョブにわたる低スコアのほうが重要です。ジョブ横断の複合シグナルは、単一の検出器の重大度を上回ることがよくあります
スコアの定義、再正規化の仕組み、
anomaly_score_explanationの構成要素について詳しくは、 references/score-reference.md を参照してください。
基本概念
検索クエリの result_type を使って、.ml-anomalies-* を階層化された結果タイプとして扱います。
result_type | 対象 | 主なフィールド |
|---|---|---|
bucket | 時間ウィンドウ | anomaly_score、initial_anomaly_score、timestamp |
record | 検知器の行 | record_score、initial_record_score、actual、typical、anomaly_score_explanation |
influencer | エンティティ × バケット | influencer_field_name、influencer_field_value、influencer_score |
model_plot | 境界 | model_lower、model_upper、actual |
category_definition | ログパターン | category_id、terms、regex、examples |
スコアは次のように読み取ります。
anomaly_score/record_score= 現在の正規化済みの値(モデルが新たな極端値を検知すると変動します)。initial_anomaly_score/initial_record_score= 検知時点の不変のスナップショット。influencer_scoreはバケット内でのエンティティの要因度を順位付けします — 最高スコアのエンティティが主な原因候補であり、バケットレベルのanomaly_scoreだけでは判断できません。partition_field_value/by_field_value/over_field_valueでエンティティを特定します。multi_bucket_impact(-5 ~ +5)を読み取り、単一バケットの急増と継続的な傾向を区別します。
モード:調査 — RCA
用途: 「何が壊れたのか?」「どのエンティティが原因なのか?」、ジョブ間の相関、影響範囲、攻撃/連鎖の経路。
プロセス
-
ジョブを特定します。 ジョブ ID が不明な場合は、
GET /_ml/anomaly_detectorsを呼び出します。 ソースインデックス、エンティティフィールド(by_field_name、over_field_name、partition_field_name)、およびbucket_spanを確認するには、GET /_ml/anomaly_detectors/{job_id}とGET /_ml/datafeeds/datafeed-{job_id}を呼び出します。判断基準:関連するジョブグループを特定します。同じデータフィードインデックスまたはエンティティフィールドを共有するジョブは、同じシステムを異なる角度から監視しています。 -
インシデントの時間範囲を絞り込みます。 時間範囲と任意の最小
anomaly_scoreを指定し、result_type: bucketを使ってPOST /.ml-anomalies-*/_searchを呼び出します。判断基準:インシデントの開始時刻と終了時刻を確定し、その時間範囲内に同時に異常を検知したジョブ数を数えます。多くのジョブで同時にスコアが低い場合、根本原因がシステム全体に及んでいる可能性があります。 -
エンティティに原因を帰属させます(RCA で重要です)。 異常バケットのタイムスタンプについて、
result_type: influencer、ジョブ ID、およびバケットの時間範囲を指定してPOST /.ml-anomalies-*/_searchを呼び出します。influencer_scoreの降順で並べ替えます。判断基準:最も高いinfluencer_scoreのエンティティを、原因の可能性が高いものとして特定します。このスコアは、そのバケット内で各エンティティがどれほど異常かを順位付けします。原因を帰属させずに、バケットのanomaly_scoreだけを言い換えてはいけません。次に、そのエンティティのレコードを詳しく調べることを推奨します。 -
複数ジョブで確認します。 同じエンティティ値と時間範囲を対象に、関連するジョブ ID 全体でインフルエンサー(またはバケットレコード)を再検索します。2 つ以上のジョブで異常が見られるエンティティは有力な容疑対象です(リソース障害またはシステム全体の障害)。単一ジョブだけのエンティティは、多くの場合、下流側の被害です。 references/protocols/investigation.md を参照してください。
-
レコードを詳しく調べます。 正確なジョブ ID、エンティティフィルター(
partition_field_value、by_field_value)、および低い最小record_score(25 以下)を指定し、result_type: recordを使ってPOST /.ml-anomalies-*/_searchを呼び出します。multi_bucket_impact ≥ 3は、持続的な動作の変化として読み取ります。障害の種類(急増か、欠如/停止か)は、actualとtypicalを比較して判断します。 -
ソースの証拠で確認します。 疑わしいエンティティと時間範囲を対象に、データフィードのソースインデックスで
POST /{index}/_searchを呼び出します。ソースの生ドキュメントが確かな根拠です。これらを確認せずに RCA を完了してはいけません。 -
結果をまとめます。 根本原因のエンティティ · 影響を受けたジョブ · 時系列の推移 · 障害の種類 · 深刻度 · 推奨アクションを報告します。手順を追った例:references/worked-example.md。クエリのテンプレート:references/investigation-queries.md。
ルール
- 「どのエンティティか?」を特定する際は、
anomaly_scoreではなくinfluencer_scoreで順位付けします。 バケットスコアは集計値であり、インフルエンサースコアは原因を帰属させます。 - 複数ジョブで異常が見られるエンティティは有力な容疑対象であり、単一ジョブだけのエンティティは通常、被害側です。
- 最も早い異常タイムスタンプを優先します。 ジョブをまたいだレコードのタイムスタンプから時系列を再構成します。
multi_bucket_impact ≥ 3は持続的な動作の変化を示します。 一時的な急増より重く評価します。- インフルエンサー/レコードのクエリでは、スコアのしきい値を低く(25 以下)設定します。 しきい値が高いと、相関するエンティティを見逃します。
- データフィードのインデックスからソースの証拠を得ずに、RCA を完了してはいけません。
モード:説明 — スコア/モデルの動作
対象となる質問:「スコアが 30/90 なのはなぜですか?」「一晩でスコアが下がった」「再正規化とは何ですか?」「なぜ検出されなかったのですか?」。
プロセス
-
取得するか、解釈するかを判断します。 ユーザーが
record_score、initial_record_score、actual、typicalを含むレコードを提供している場合は、そのまま解釈します。それ以外の場合は、GET /_ml/anomaly_detectors/{job_id}で設定を読み込み、POST /.ml-anomalies-*/_search(result_type: record)でレコードを取得します。 -
initial_record_scoreとrecord_scoreの両方を必ず表示します。 この差が、再正規化の経緯を示します。正のドリフトが大きい場合(initial_record_score >> record_score)、後からより極端な異常が発生して、このレコードのスコアが下方に再スケーリングされたことを意味します。これは正常な動作であり、モデルの故障ではありません。 -
推測する前に、パターンを分類します。
パターン 解釈 initial_record_score >> record_score再正規化 — 設定変更を提案する前に説明します actual << typicalとlow_count/count/low_mean欠如/停止の異常 — スコア調整ではなく、停止の原因を調査します anomaly_score_explanation内のhigh_variance_penalty: trueノイズの多いメトリック — 広い範囲にスパイクが吸収されています incomplete_bucket_penalty: trueデータ取り込みの遅延、または疎なバケット — スコアは妥当に低下しています レコードに存在する
anomaly_score_explanationの要因のみを挙げます。 -
再正規化を定量化します(任意)。
timestampでソートしたレコードを再取得し、score_drift = initial_record_score - record_scoreを計算して、大きなドリフトにフラグを付けます。 -
必要に応じて、視覚的なコンテキストを追加します。
model_plot_config.enabledの場合、result_type: model_plotをクエリして、actualとmodel_lower/model_upperを比較します。カテゴリ化ジョブの場合は、result_type: category_definitionをクエリします。 -
スコアが継続的におかしい場合は、ジョブの健全性を確認します。
GET /_ml/anomaly_detectors/{job_id}/_statsを呼び出します —model_size_stats.memory_statusがhard_limitの場合、学習が破損し、スコアが無効になる可能性があります。トラブルシューティングモードに切り替えます。
anomaly_score_explanation の構成要素
| 構成要素 | 効果 | 意味 |
|---|---|---|
anomaly_length | ↑ スコア | 連続して異常となったバケットの数が多い |
single_bucket_impact | ↑ スコア | 確率が低いほど、影響が大きい |
multi_bucket_impact | ↑ スコア | 継続的なパターンによる寄与 |
anomaly_characteristics_impact | ↑ スコア | 平均値の変化と分散の変化 |
high_variance_penalty | ↓ スコア | データにノイズが多い → 範囲が広い → 異常性が低い |
incomplete_bucket_penalty | ↓ スコア | バケットのデータが予想より少ない(データ取り込みの遅延、データの疎さ) |
ルール
- 設定を診断する前に、再正規化を説明します — スコアドリフトは、「スコアが低下した」原因として最もよくあります。
actual << typicalと count/low_count の組み合わせは欠如の異常です — 値の急増と停止を区別します。- 週次の季節性には、3 週間以上の学習データが必要です — ジョブの開始から日が浅いことを原因として指摘します。
- 検出器関数の方向が重要です — references/anomaly-detection-functions.md を参照してください。
モード:トラブルシューティング — ジョブのライフサイクル
対象: 「ドキュメントが見つからない」、「データフィードが停止した」、hard_limit、「結果がおかしい」、ライフサイクルの変更。
プロセス
-
ジョブとデータフィードの状態を読み込みます。
GET /_ml/anomaly_detectors/{job_id}/_statsとGET /_ml/datafeeds/datafeed-{job_id}/_statsを呼び出します。state、data_counts、model_size_stats、およびデータフィードのstateを確認します。ユーザーが統計情報の JSON を埋め込んでいる場合は、memory_statusとデータフィードの状態から直接診断します。 -
最初にメモリの状態を診断します(重要)。
model_size_statsを確認します。フィールド 意味 memory_statusok/soft_limit(プルーニング)/hard_limit(重大)model_bytes現在使用中のメモリ量 model_bytes_memory_limit設定された model_memory_limitmemory_statusがhard_limitで、model_bytesがmodel_bytes_memory_limitと等しい場合、モデルはメモリ上限に達しており、新しいエンティティの学習が止まり、結果が劣化するか、出力されなくなります。停止したデータフィードは、多くの場合、根本原因ではなく症状です。データフィードの再起動だけを推奨しないでください。それだけではhard_limitは解消されません。 -
hard_limitを解消します。 対処方法は、model_memory_limitを引き上げる(ジョブの更新で実施)、および/またはカーディナリティを下げてモデルサイズを縮小する(partition/by/over のフィールド値を減らす、複数のジョブに分割する)ことです。上限を引き上げるには、以下のライフサイクル手順(データフィードを停止 → ジョブを閉じる → 更新 → 開く → 開始)に従う必要があります。必要に応じて、POST /_ml/anomaly_detectors/_estimate_model_memoryを呼び出し、ソースのカーディナリティから新しい上限を見積もります。 -
ドキュメントの欠落/クエリのタイミングを診断します。 メモリの状態が正常になったら、
GET /_ml/datafeeds/datafeed-{job_id}でデータフィードのquery_delayとdelayed_data_check_configを確認します。.ml-annotations-*を検索し、遅延データのイベントを調べます。query_delayは、P95 の取り込みレイテンシにバッファーを加えた値に設定します(デフォルトは60s~120s)。 -
ジョブのメッセージを読み込みます。 エラーの原因が不明な場合は、
.ml-notifications-*をジョブ ID で検索します。 -
破損したモデル状態を復旧します。
hard_limitの発生中にモデルが破損した場合は、POST /_ml/anomaly_detectors/{job_id}/model_snapshots/{snapshot_id}/_revertを呼び出して、正常な既知のスナップショットに戻します。
設定変更時のライフサイクル(メモリ上限、query_delay)
順番に適用してください。手順を省略すると、更新が拒否されます。
POST /_ml/datafeeds/datafeed-{job_id}/_stopPOST /_ml/anomaly_detectors/{job_id}/_closePOST /_ml/anomaly_detectors/{job_id}/_update(メモリ上限)および/またはPOST /_ml/datafeeds/datafeed-{job_id}/_update(query_delay)POST /_ml/anomaly_detectors/{job_id}/_openPOST /_ml/datafeeds/datafeed-{job_id}/_start
再起動する前に、POST /_ml/datafeeds/datafeed-{job_id}/_preview で変更をプレビューします。
hard_limitはモデルの状態を破損させ、下流でドキュメントが欠落したという誤警報を引き起こします。query_delayを修正する前に、メモリを修正してください。 トラブルシューティングの詳細: references/troubleshooting-reference.md。
ルール
- ライフサイクルの診断は
memory_statusに基づいて行います。「再起動してください」といった一般的なアドバイスに頼らないでください。 query_delayより先にメモリを修正します。hard_limitがあると、その後の診断は無効になります。- メモリまたはデータフィードの設定を変更する場合は、データフィードを停止 → ジョブを閉じる → 更新 → 開く → 開始の順で実行します。
hard_limitの最初の対処としてジョブを削除しないでください。上限を引き上げる、および/またはカーディナリティを下げてください。
モード:管理 — ジョブの作成/設定
該当する場合:「ジョブを設定する」「ML 検出器を作成する」「X を継続的に監視する」。
作成/オープン/開始の全ライフサイクルについては、elasticsearch-anomaly-detection スキルを優先してください。このモードでは、手順と検出器の選び方を要約します。
- 対象インデックスを確認します。
GET /{index}/_mappingを呼び出し、時刻フィールドと検出器フィールドが存在することを確認します。 - ジョブを作成します。
analysis_config(検出器、bucket_span、インフルエンサー)とdata_description.time_fieldを指定して、PUT /_ml/anomaly_detectors/{job_id}を呼び出します。 - データフィードを作成します。
indices、query、query_delayを指定して、PUT /_ml/datafeeds/datafeed-{job_id}を呼び出します。 - オープンして開始します。
POST /_ml/anomaly_detectors/{job_id}/_openを呼び出し、続けてPOST /_ml/datafeeds/datafeed-{job_id}/_startを呼び出します。 - 確認します。
GET /_ml/anomaly_detectors/{job_id}/_statsとGET /_ml/datafeeds/datafeed-{job_id}/_statsを呼び出します。
ユーザーの意図に応じて検出器の関数を選択してください。詳しくは references/anomaly-detection-functions.md を参照してください。JSON の設定例: references/job-creation-recipes.md。
ルール
- データフィードより先にジョブを作成します。 データフィードを開始する前にジョブをオープンします。
query_delay= P95 の取り込みレイテンシ + バッファー(安全なデフォルト値は 60s~120s)。by_field_nameとover_field_name:byはエンティティをその履歴と比較し、overはピアグループと比較します。- 予測には非母集団ジョブが必要です —
over_field_nameを持つジョブは予測できません。
例
RCA:「何かが原因でチェックアウトのレイテンシが急増しました。どのエンティティですか?」→ 該当バケットのインフルエンサーをクエリします → web-07 の influencer_score が 91.5 と最も高く、22.0 と 8.4 を上回っています → web-07 を原因候補として示します → そのレコードを詳しく調べるよう提案します — バケットの anomaly_score 88 だけで回答してはいけません。
スコアの低下:「スコアが 90 から 55 になりました。モデルが変わったのでしょうか?」→ initial_record_score と record_score を比較します →
乖離が大きい場合は、再正規化について説明します。
メモリー制限:「ジョブに hard_limit が表示され、データフィードが停止しました。」→
model_size_stats.memory_status = hard_limit と診断します → ジョブをクローズ/更新/オープンするライフサイクルで model_memory_limit を引き上げる、またはカーディナリティを下げます — 「データフィードを再起動するだけ」ではありません。
新しいジョブ:「ホストごとに異常なエラー率を検出する。」→ by_field_name: host.keyword を指定した high_count を使います →
作成/オープン/開始の手順を実行します。
ガイドライン
- 最初にモードを選びます。 RCA のロジックとスコア説明のロジックを、1 つの回答に混在させないでください。
- 「どのエンティティか?」には、バケットの
anomaly_scoreではなくinfluencer_scoreの順位を使います。 - ライフサイクルの失敗では、データフィードの再起動を勧める前に
memory_statusを確認します。 initial_record_scoreとrecord_scoreを並べて示します — その差から再正規化の状況が分かります。query_delayの前にメモリーを修正します。hard_limitがあると、その後の診断は無効になります。- データフィードのインデックスにあるソースの証拠で RCA を確認します。
オペレーション
| HTTP API (shorthand) | elastic CLI command |
|---|---|
GET /{index}/_mapping | elastic es indices get-mapping --index '<index>' |
POST /{index}/_search | elastic es search --index '<index>' --input-file '<search-body.json>' |
GET /_ml/anomaly_detectors | elastic es ml get-jobs |
GET /_ml/anomaly_detectors/{job_id} | elastic es ml get-jobs --job-id '<job_id>' |
GET /_ml/anomaly_detectors/{job_id}/_stats | elastic es ml get-job-stats --job-id '<job_id>' |
GET /_ml/datafeeds/datafeed-{job_id} | elastic es ml get-datafeeds --datafeed-id 'datafeed-<job_id>' |
GET /_ml/datafeeds/datafeed-{job_id}/_stats | elastic es ml get-datafeed-stats --datafeed-id 'datafeed-<job_id>' |
POST /.ml-anomalies-*/_search | elastic es search --index '.ml-anomalies-*' --input-file '<search-body.json>' |
POST /.ml-annotations-*/_search | elastic es search --index '.ml-annotations-*' --input-file '<search-body.json>' |
POST /.ml-notifications-*/_search | elastic es search --index '.ml-notifications-*' --input-file '<search-body.json>' |
POST /_ml/anomaly_detectors/_estimate_model_memory | elastic es ml estimate-model-memory --analysis-config '<json>' |
PUT /_ml/anomaly_detectors/{job_id} | elastic es ml put-job --job-id '<job_id>' --input-file '<job-body.json>' |
PUT /_ml/datafeeds/datafeed-{job_id} | elastic es ml put-datafeed --datafeed-id 'datafeed-<job_id>' --input-file '<datafeed-body.json>' |
POST /_ml/anomaly_detectors/{job_id}/_open | elastic es ml open-job --job-id '<job_id>' |
POST /_ml/anomaly_detectors/{job_id}/_close | elastic es ml close-job --job-id '<job_id>' |
POST /_ml/anomaly_detectors/{job_id}/_update | elastic es ml update-job --job-id '<job_id>' --analysis-limits '<json>' |
POST /_ml/datafeeds/datafeed-{job_id}/_update | elastic es ml update-datafeed --datafeed-id 'datafeed-<job_id>' --input-file '<update-body.json>' |
POST /_ml/datafeeds/datafeed-{job_id}/_start | elastic es ml start-datafeed --datafeed-id 'datafeed-<job_id>' |
POST /_ml/datafeeds/datafeed-{job_id}/_stop | elastic es ml stop-datafeed --datafeed-id 'datafeed-<job_id>' |
POST /_ml/datafeeds/datafeed-{job_id}/_preview | elastic es ml preview-datafeed --datafeed-id 'datafeed-<job_id>' |
POST /_ml/anomaly_detectors/{job_id}/model_snapshots/{snapshot_id}/_revert | elastic es ml revert-model-snapshot --job-id '<job_id>' --snapshot-id '<snapshot_id>' |
各 result_type の検索本文形式とトラブルシューティングのクエリは、
references/investigation-queries.md と
references/troubleshooting-reference.md に記載されています。