この記事の内容(端的に)
Elastic StackのMachine Learning - Anomaly Detection機能の異常検知データにES|QLクエリーでアクセスするための方法を紹介します。異常検知データはElasticsearchのシステムインデックス(隠れインデックス)に保存されており、公式ドキュメントなどでアクセス方法は明記されていません。本記事は、KibanaのAnomaly Explorer画面で見えるのと同じデータをES|QLで取得できる方法を調べたものです。
本記事は、2026/1/6時点のElastic Cloud Serverless (実質Elatic Stack v9.2相当)で検証しています。
本記事はElasticのML異常検知を使ったことがあるユーザーを対象にしています。ElasticのMachine Learning機能はElastic v5.x の2017年ごろに登場している機能です。これに関するブログなどの記事については既に多くあり、私も過去に以下のブログなどを書いています。
背景 (なぜES|QLでアクセスしたいか?)
Elastic StackのMachine Learning - Anomaly Detection機能は、オブザーバビリティあるいはセキュリティ用途でElasticsearchに収集したログ、メトリック、トレースに対しての異常検知ができる強力な機能です(有償のPlatinum サブスクリプション以上が必要)。
教師なし学習のタイプのMLなので、事前のモデル学習は必要なく、取り込んだデータに対して随時学習し異常を検出していきます。よって、設定作業だけで手軽に使うことができます。
検出された異常データは通常はKibanaのWeb UIから確認したり、一定値以上の異常スコアの場合にアラート通知して運用したりします。しかし、データが多くなると、これらに対して実際に対応が必要かどうかの判断の手間が増えてしまうのが課題の一つでした。
現在は色々ところでAIエージェントが登場しており、今後はこのような確認作業をエージェントにさせることで、この確認と判断の作業を任せられるようになる日も近いと考えられます。Elasticも2025年にElastic Agent Builderという機能を発表し、Elasticsearchのデータを活用するためのAIエージェントが手軽に作成できます。
そういうわけで、この世界観を実現するためにはAPI経由でElasticの異常検知データにアクセスすることが必要になってくるわけです。
異常検知データが含まれるData Viewをまず作成
KibanaのDiscover画面でデータを見たいので、Data Viewを作成します。.ml-anomalies-xxxといった名前の隠れインデックスにデータが含まれています。以下のような設定でData Viewを作成します。

Anomaly Explorer - View by Job ID画面のデータをES|QLで取得
以下は特定の異常検知ジョブ単位での異常スコアを確認する画面です。この場合、k8s_pod_cpu_usageというジョブのを表示しています。

Discoverで表示するにはこのようにします。ジョブ単位の異常検知データはresult_type: bucketでフィルターしてあげるのがポイントです。

FROM .ml-anomalies-*
| WHERE job_id == "k8s_pod_cpu_usage" AND result_type == "bucket"
| KEEP @timestamp, job_id, result_type, anomaly_score
| SORT @timestamp ASC
| LIMIT 10000
Anomaly Explorer - View by (influencer) 画面のデータをES|QLで取得
ジョブの設定でパーティションやInfluencer設定を追加している場合、以下の画面のように個別のエンティティ毎の異常を検知できるようなっています。

Discoverでこのデータ相当にアクセスするには、result_type: influencerにするのがポイントです。

FROM .ml-anomalies-*
| WHERE job_id == "k8s_pod_cpu_usage" AND result_type == "influencer"
AND influencer_field_name == "service.name" AND service.name == "fluentbit-gke"
| KEEP @timestamp, job_id, result_type, anomaly_score, influencer_field_name, influencer_score
| SORT @timestamp ASC
| LIMIT 10000
Anomaly Explorer - Top influencersのデータをES|QLで取得
この赤枠の部分は、さきほどのInfluencer単位のアノマリースコアの最大値を表示してランキングしています。

以下のようにES|QLでMAX関数を使えば簡単に同じデータになります。

FROM .ml-anomalies-*
| WHERE job_id == "k8s_pod_cpu_usage" AND result_type == "influencer" AND influencer_field_name == "service.name"
| STATS max_anomaly_score = MAX(influencer_score) by service.name
| KEEP service.name, max_anomaly_score
| SORT max_anomaly_score DESC
分析対象データの時系列データをES|QLで取得
Anomaly Explorerで、セル(赤とか黄色の色の部分)をクリックすると、監視対象のデータがどのような挙動だったかを確認できるチャートが表示されます。
例えば以下のような形で、データにスパイクがあるようなことがわかります。これを見て、この異常が運用として対応すべきものかどうか人が判断します。例えば以下の例は、最初の投入データだけなぜか高く、あとは低く推移しているので、問題ないと判断できます。

Discoverでこのデータ相当を表示するには、result_type: recordを指定するのがポイントです。

ES|QLではこのように実現できます。
descriptionという名のカラムで通常時(typical)よりも何倍今回の値(actual)が高いかを表現することもできます。

FROM .ml-anomalies-*
| WHERE result_type == "record"
| WHERE job_id == "k8s_pod_cpu_usage" AND field_name == "k8s.pod.cpu.usage" AND partition_field_value == "kafka"
| EVAL description = CONCAT(TO_STRING(ROUND(actual / typical, 1)) , "倍 通常よりCPUの使用率が高い")
| KEEP @timestamp, job_id, actual, typical, description, field_name, function, partition_field_name, partition_field_value, record_score, k8s.pod.name
Elastic Agent Builderを使いAIエージェントからアクセス
上記のES|QLクエリーを使って簡単にAIエージェントから分析する例を最後のご紹介します。
Elastic Agent Builderについては以下のブログなどをご参照ください。
新しく出たElasticのAIエージェント作成機能: Elastic Agent Builderを試す
Elastic Agent Builderは現在まだテックプレビューですが、今後Enterpriseサブスクリプション機能として今後GAになると予想されます。
新たにエージェント:anomaly_detection_analyzerと名付けたエージェントを作成。Custom Instructionsに指示を与えます。注目ポイントとして異常スコアや通常よりどれくらい高いものに着目して欲しいかを指示してみました。

上記エージェントに装備するToolを以下のように設定して作成しました。今回の記事で使った同様のES|QLを設定しています。対象の期間やサービス名は変数にして、チャット時にAIに入れてもらうようにしています。

では早速チャットしてみましょう。期間とサービス名を指示に含めます。

結果:エージェントのシステムプロンプトに入れた通り、異常スコアが50以上のものや通常より5倍以上のデータをピックアップして報告してくれました。

おわり
AIエージェントがElasticのMachine Learningのデータを活用するための基礎となるデータアクセス方法についてご紹介しました。オブザーバビリティ、セキュリティの分析をAIエージェントに任せるための一つの方法として参考になれば幸いです。

