[v8.14]最新のElastic Agent自身のモニタリング方法

# この記事はなに？
Elastic Stackバージョン8.xを使って、オブザーバビリティやSIEM用途でログやメトリクスを収集するなら、Elastic AgentとIntegrationsを使うのが一番です。それにより色々なソフトウェアのログやメトリクスを簡単に集めることができます。
本記事では、そのElastic Agent自身の監視や状態確認を行うための方法について紹介します。

この記事はElastic Stack バージョン8.14を元の執筆しています。

# Elastic Agentのインストール
まずはElastic AgentとIntegrationのセットアップから。
IntegrationsからElastic Agentで使うデータ収集方法を選択します。今回はCustom Logsを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/88d79ed9-6b77-a77a-b480-510f86ec0041.png)

今回は/tmp/test.logに書き込まれるログを集めるように設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/68386c5b-e6c3-ec88-c50d-ff03aeea623f.png)

表示されるインストールコマンドのURLとトークンをコピーして..
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/363dbb56-b8b0-79af-7db7-0ebb3002cee0.png)

今回はElastic Agentをコンテナ上で起動させるので、docker-compose.ymlが読み込む.envにインストールのパラメータを貼り付けします。
```.env
# Version of Elastic products
STACK_VERSION=8.14.0
PROJECT=elastic-agent-fleet
FLEET_URL=<設定してください>
FLEET_ENROLLMENT_TOKEN=<設定してください>
```

```docker-compose.yml
version: "3.0"

services:
 elastic-agent:
    hostname: ${PROJECT}-elastic-agent
    image: docker.elastic.co/beats/elastic-agent:${STACK_VERSION}
    restart: always
    environment:
      - FLEET_ENROLL=1
      - FLEET_URL=${FLEET_URL}
      - FLEET_ENROLLMENT_TOKEN=${FLEET_ENROLLMENT_TOKEN}
```

コンテナを起動して、以下のようにエンロールが成功したら疎通できています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/a91948ea-a97d-8a5b-d086-c78fc1b2c0e5.png)

# Elastic Agentのステータスを監視しましょう
Fleet画面のAgent一覧で接続できたエージェントを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/7492e1a1-ee60-c9eb-58bc-27f95363c5a2.png)

ここの各Status値については、[ドキュメント](https://www.elastic.co/guide/en/fleet/8.14/monitor-elastic-agent.html#view-agent-status)に記載がありますが、運用時の監視という観点では以下2つのステータスに気をつけます。

- **Unhealthy** ... [このドキュメント](https://www.elastic.co/guide/en/fleet/8.14/agent-health-status.html#agent-health-status-other-components)には、Elastic Agentが内部で起動する子プロセスのFilebeatやMetricbeatからの応答がないときはUnhealthyとなるとあります。
- **Offline** ... Elastic Agentを停止したり、Elastic Agentからのネットワークを遮断したりすると、Offlineになります。

また、個別のエージェントのリンクをクリックすると、Integrationの設定に問題があったかを確認できるようになっています。（下のサンプルは[View details for an agent
](https://www.elastic.co/guide/en/fleet/8.14/monitor-elastic-agent.html#view-agent-details)より）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/9528cffb-4678-0f5e-15ff-4b2490f395df.png)


## Offlineに対する監視アラートの設定

以下のドキュメントに書かれている方法で、Elastic Agentのステータスに応じてアラートをあげるようにすることができます。
Offline監視アラート通知設定方法
https://www.elastic.co/guide/en/fleet/8.14/monitor-elastic-agent.html#fleet-alerting-example
こちら簡単に説明すると、metricsにfleet.agents.offlineというフィールドにOfflineのエージェントのカウントがあるので、そのカウントを監視しましょうという話です。

その前に、下の画像のようにOfflineで放置されている、もう使っていないElastic Agentのデータが残っていたら、先にこれらをUnenrollしましょう。そうしないと、これらが引っかかってアラートが上がってしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/58c24856-36a5-a774-38de-d71d598fe038.png)

### 監視アラートのテスト
では、実際にElastic Agentのホストのネットワークを遮断してみました。この時の時刻は14:35でした。

アラートが上がったのは、約8分後でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/df629b81-47ef-c781-c2ce-eeed060248fb.png)

Discoverで監視対象のメトリクスを確認するとこのように1分おきでステータスがログされていますが、Offlineかどうかの検知は即座ではないようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/36336043-1fd7-1183-3fb2-37a85f730f0d.png)

もう一つテストとして、Elastic Agentのシャットダウンをしました。時間は14:48です。アラートが上がったのは、14:54でした。

[補足]
コンテナ上で動いているElastic Agentは、揮発性ボリュームの上でシャットダウン後に新たなコンテナで起動すると、別のAgentとして認識され、Offlineは残ってしまいます。コンテナでElastic Agentを動かす際はそのインストールボリュームが永続するようにしておく必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/56b2ed04-928b-4960-a60d-48c47ecd5001.png)

# Elastic Agentのメトリクスを使って細かく状態確認してみましょう

先ほどはAgentの状態監視でしたが、別の問題として集めるべきデータを全て集められているのか？というのも気になるところです。
それにはElastic Agentが発する稼働メトリクスを見て、データ収集状況を評価していくことになりますので、そちらを紹介します。

Fleetから特定のElastic Agentを選択して、下の画面の`View more agent metrics`でこのエージェントの稼働情報を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/7276ad76-dea2-7c4b-0bdd-1bf2587746d5.png)

このように色々な情報が確認できますね。どれを見るべきかは後ほど...
![CleanShot 2024-08-07 at 15.55.02@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/47de67d7-7826-8dc5-0d67-50f0689c716c.png)

ここで、Elastic Agentが動いているコンテナに入り、ログをファイルに書き込みます。今回のElastic Agentはこのログを収集するように設定されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/9ca61a71-9eec-2fea-3e97-2f8f86b097d1.png)

このようにDiscoverではログが取れているのが見えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/22103249-8a77-845c-9688-1475b89229e4.png)

次に、無限ループでログ書き込みさせます。2件のログの書き込みと1秒のスリープをループして実行するようにしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/e237a650-0a9b-8dc0-601d-f49a183ac744.png)

Elastic AgentはAgentの稼働情報など、今回着目しているログの収集以外にも色々なデータを集めているため、フィルタリングしないと単一の収集の状況を可視化しづらいです。今回はcomponent.idでIntegrationの情報による絞り込みでフィルタかけました。これで今回のCustom Logsのログ収集状況だけ見ることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/d6c737e5-4bf3-67c1-f423-97d36f619c0d.png)

このようにCustom Logsインテグレーションで集めているログに関する稼働情報が出ました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/fe6cdd03-27fa-d5bd-0ff8-3d53f48b0e32.png)
* [Elastic Agent] Total events rate/s ... Elasticsearchへのログの送信件数。2件/秒が検知されています。今回のログ書き込みのタイミングと一致しています。
* [Elastic Agent] Events acknowledged rate/s ... 送信されたログのうち、Elasticsearchが正常に受け取っている数。こちらも2件/秒。
* [Elastic Agent] Output write batches ... ログの送信はいくつかのイベントをまとめたバッチ毎に送信されるので、そのバッチの件数。0.1/秒ということで、10秒に1回のペースでログはElasticsearchにバッチ送信されています。[queue.mem.flush.timeout](https://www.elastic.co/guide/en/fleet/current/es-output-settings.html)の値がデフォルト10sなので、仕様通りの送信間隔です。

この辺りのパラメータの詳細は以下のドキュメントで確認できます。
https://www.elastic.co/guide/en/beats/filebeat/current/understand-filebeat-logs.html
https://www.elastic.co/guide/en/beats/metricbeat/current/exported-fields-beat.html

# テスト： Elasticsearch側のイベント受信を停止してみる

Elastic CloudのElasticsearch側イベントの受信を停止してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/84da96db-fcd8-3436-5010-dc4f68358c69.png)

結果、受信停止期間はイベントの送信もゼロと出ています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/1ec15033-2ce3-2892-472a-c7ecaebfe3df.png)

別途Integrationsのダッシュボード画面で、[Elastic Agent] Events per Integrationというのがありました。こちらはElasticsearchの受信停止期間中は凹んでいませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/989cb536-402d-f193-9cdf-1c75055858d3.png)

Discoverでこのデータの詳細を詳しく見ると、先どのデータの時間の元となる@timestampの値はログがファイルに書き込まれた時間を表しています。event.ingestedはElasticsearchがログを受信した時間で、Elasticsearchの受信を再開後に受信していることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/54c587ca-9ee9-ec79-f582-7bea225fd273.png)

16:45にElasticsearchの受信を再開したところで、エージェント側で溜まっていたログを一気に受信したスパイクが見えますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/1e47443e-0af9-de19-2bab-43399ce0916e.png)

# テスト： Elasticsearchでインジェスト時にエラーさせた場合
logs-generic@customという名前でIngest Pipelineを作ると、今回のCustom
 Logインテグレーションに対するログの加工処理をElasticsearch側で定義できます。ここで、わざとエラーを起こす処理を入れてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/f9389d25-fafd-51db-54f8-b90db7f20a26.png)

結果、この時のデータです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/1ad9fba8-1437-731c-9f8a-80de9ea9804e.png)
* [Elastic Agent] Events failed rate/s ... Elasticsearchが受信でエラーを返していることがわかります。
* [Elastic Agent] Total events rate/sとOutput write batches ... エラー期間中も、エージェントからの送信が起こり続け、リトライの分、通常より送信も多いことがわかります。
* [Elastic Agent] Events acknowledged rate/s ... Elasticsearchが受信を正常に処理できた数です。エラー期間中はこの値がゼロになります。また、エラーからの復旧直後はエージェントからリトライされ続けていたイベントが受信されたため、スパイクがあるのがわかります。

# Elastic AgentがOfflineになった時のメトリクス状況

Offlineのアラート監視を仕掛けた時はアラート検知までに数分のラグが出ていましたが、メトリクスを確認すると正確にいつからログデータが上がって来なくなっていたかを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/eaba15ec-be3b-ae5d-b843-a4047763b000.png)


# Appendix
Input Metricsのダッシュボードでは、Input毎の数値というのが確認できますが、ここのFilestream Inputsは、今回のCustom Logsインテグレーションが使うInputのタイプとは違うので、この数値は使えません。では、何に使っているのかというと、Elastic Agent自身のログの収集に使われているため、1が立っています。いずれCustom Logsインテグレーションも内部で使用されるInputタイプがLog InputからFilestream Inputに移行されるはずなので、その時になったらここの数値も使えるはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/893b3d82-6170-db4c-2985-ef8884a84f53.png)

Input MetricsだとInput毎の稼働情報がこのように見やすいので助かるのですが。
![CleanShot 2024-08-07 at 15.56.57@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/641841fa-e129-dcca-5b04-7e4d1853c253.png)

Input ID毎の絞り込みも簡単にできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/0cc77b99-06e9-42d2-5302-ec60d8c301bb.png)

# おわり
ご紹介したようにElastic Agentの監視は、監視したい観点によっては、どのメトリクスをどう評価するかは様々な状況があり、一筋縄ではいきません。
まずはElatic Agentのステータスに対する監視を仕掛け、次のより細かい監視は一定期間の状態を確認してから、精度の良い監視ルールが作れそうかを見極めて設定していきましょう。
また、大前提として、本番クラスタは開発・検証クラスタとは別にしておき、ゴミデータのないクリーンな状態を保持することも重要です。