ラベル Kibana の投稿を表示しています。 すべての投稿を表示
ラベル Kibana の投稿を表示しています。 すべての投稿を表示

2025年9月21日日曜日

ElastAlert2 を使ってみる

ElastAlert2 を使ってみる

概要

前回ES9をdockerで構築しました
今回は ElastAlert2 を組み合わせて特定のログがES9に格納されたらアラートされる仕組みを作成してみます

環境

  • macOS 15.6.1
  • docker 28.4.0
    • ElasticSearch 9.0.7
    • Kibana 9.0.7
    • fluentd 1.19-1
    • ElastAlert 2.26.0

elastalert.yaml

EalstAlert2 共通の設定を作成します
接続する ElasticSearch9 の設定やルールを管理するディレクトリを指定します

  • vim elastalert.yaml
rules_folder: /opt/elastalert/rules

run_every:
  seconds: 10

buffer_time:
  minutes: 15

es_host: 192.168.1.152
es_port: 9200
use_ssl: true
verify_certs: false
es_username: elastic
es_password: xxx

writeback_index: elastalert_status

alert_time_limit:
  days: 2

rules/test_alert.yaml

とりあえずテスト用のアラートファイルを作成します
今回は必ずアラートが上がるように @timestmp フィールドを監視し5分間の間に2回レコードが格納された場合にアラートが上がるようにします

  • mkdir rules
  • rules/test_alert.yaml
name: "test_alert"
type: "frequency"
index: "fluentd*"
is_enabled: true
num_events: 2
realert:
  minutes: 5
terms_size: 50
timeframe:
  minutes: 5
timestamp_field: "@timestamp"
timestamp_type: "iso"
use_strftime_index: false
alert_subject: "Test {} 123 aa☃"
alert_subject_args:
  - "log"
alert_text: "Test {}  123 bb☃"
alert_text_args:
  - "source"
filter:
  - query:
      query_string:
        query: "@timestamp:*"
alert:
  - "slack"
slack_webhook_url: 'https://hooks.slack.com/services/xxx'
slack_channel_override: "#private"
slack_emoji_override: ":kissing_cat:"
slack_msg_color: "warning"
slack_parse_override: "none"
slack_username_override: "elastalert"

各種項目の説明

ルールの基本

name: "test_alert"
ルールの名前。Slack 通知などに出てくる。

type: "frequency"
「一定時間内に指定した件数以上のイベントがあるとアラートを出す」というタイプ。

index: "fluentd"
監視対象の Elasticsearch インデックス名。

is_enabled: true
このルールが有効になっている。

発火条件

num_events: 2
  イベント件数のしきい値。

timeframe: minutes: 5
  評価対象の時間範囲。
  → 「5分間に2件以上あればアラート」

realert: minutes: 5
  一度アラートが出た後、同じ条件で再度アラートを出すまでのクールダウン時間。
  → 5分間は抑止する。

terms_size: 50
  集計クエリのサイズ。frequency ルールでは多くの場合デフォルトでOK。

タイムスタンプ関連

timestamp_field: "@timestamp"
  イベントの時刻として使う Elasticsearch のフィールド。

timestamp_type: "iso"
  日時フォーマットの種類。ISO 8601 形式。

use_strftime_index: false
  インデックス名に日付を埋め込まない(例: fluentd-%Y.%m.%d ではなく fluentd 固定)。

通知メッセージ

alert_subject: "Test {} 123 aa☃"
  Slack の件名やタイトル部分に使うテンプレート。
  {} に alert_subject_args のフィールドが入る。

alert_subject_args: "log"
  → log フィールドの値が {} に挿入。

alert_text: "Test {} 123 bb☃"
  本文テンプレート。
  {} に alert_text_args のフィールドが入る。

alert_text_args: "log"
  → log フィールドの値が {} に挿入。

検索条件

filter:
  単純に @timestamp フィールドが存在する全ログを対象にする。
  実質「全件」になる。

ElastAlert2 コンテナの起動

ではコンテナを起動します
ホスト側に作成した各種設定ファイルがちゃんとコンテナにマウントされるようにしましょう

  • docker run -d --name elastalert --restart=always -v $(pwd)/elastalert.yaml:/opt/elastalert/config.yaml -v $(pwd)/rules:/opt/elastalert/rules jertel/elastalert2 --verbose

ログを見ると

Background alerts thread 0 pending alerts sent at 2025-09-17 23:35 UTCINFO:elastalert:1 rules loaded

でルールが有効になっていることが確認できます
また以下のログがあれば Slack に通知できているログになります

INFO:elastalert:Ran test_alert from 2025-09-17 23:54 UTC to 2025-09-17 23:55 UTC: 2 query hits (0 already seen), 1 matches, 1 alerts sent

動作確認

5分間待って Slack に通知が来ることを確認しましょう

以下のように変数部分が <MISSING VALUE> になる場合は ES9 上に指定のフィールドが存在するか確認してください

おまけ: 事前にルールファイルの確認をする

  • docker run --entrypoint "" --rm -v $(pwd)/elastalert.yaml:/opt/elastalert/config.yaml -v $(pwd)/rules:/opt/elastalert/rules jertel/elastalert2 elastalert-test-rule /opt/elastalert/rules/test_alert.yaml

最後に

ES9 と ElastAlert2 を連携させて特定のログが出た場合に Slack に通知する仕組みを試してみました
基本的には filter や timeframe などの監視条件をいろいろ変更してログ監視ルールを作成していく感じになります

また今回の構成だと rules ディレクトリにルールファイルをどんどん追加していく感じになりますが追加したルールファイルが1つでも壊れている(YAML構文エラーや必須のディレクティブが定義されていないなどがある)と ElastAlert2 自体が起動しないので注意してください

今回紹介した機能以外にもたくさんの機能があるので興味があれば参考サイトから公式のドキュメントを参照してみてください

参考サイト

2025年9月20日土曜日

docker で ElasticSearch9 を試す

docker で ElasticSearch9 を試す

概要

過去にES8を試しました
ES9が出たので久しぶりに試してみました

環境

  • macOS 15.6.1
  • docker 28.4.0
    • ElasticSearch 9.0.7
    • Kibana 9.0.7
    • fluentd 1.19-1

ElasticSearch の起動

  • docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" --name es docker.elastic.co/elasticsearch/elasticsearch:9.0.7

パスワードなどの確認や CA 証明書の取得などは同じ流れでした

  • docker exec -it es /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic -a
  • docker cp es:/usr/share/elasticsearch/config/certs/http_ca.crt .
  • curl --cacert http_ca.crt -u elastic https://localhost:9200
Enter host password for user 'elastic':
{
  "name" : "528f80bd51ca",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "pBMuWf9vTBuFEj1PHoZiFA",
  "version" : {
    "number" : "9.0.7",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "c6d8fb31b39450a223671e79141dd1c4b2759b5f",
    "build_date" : "2025-09-10T22:06:39.784049935Z",
    "build_snapshot" : false,
    "lucene_version" : "10.1.0",
    "minimum_wire_compatibility_version" : "8.18.0",
    "minimum_index_compatibility_version" : "8.0.0"
  },
  "tagline" : "You Know, for Search"
}

エンロールメントトークンも取得しておきます

  • docker exec -it es /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s kibana --url "https://localhost:9200"

Kibana 起動

  • docker run -d -p 5601:5601 --name kibana docker.elastic.co/kibana/kibana:9.0.7

Kibana ログイン時に認証コードが必要なので取得しておきます

  • docker exec kibana bin/kibana-verification-code

ログ送信

fluentd コンテナを使って送信します

  • vim Dockerfile
FROM fluent/fluentd:v1.19-1

USER root
RUN gem install fluent-plugin-elasticsearch
  • docker build -t my_fluentd .

fluent.conf を作成します
ES9 に接続するには認証情報などが必要になります
ssl_verify=false を設定しないと fluentd -> es で SSL のエラーが発生しました

  • vim fluent.conf
<source>
  @type forward
  port 24224
  bind 0.0.0.0
</source>

<match docker.**>
  @type copy
  <store>
    @type stdout
  </store>
  <store>
    @type elasticsearch
    user elastic
    password xxx
    ca_file /fluentd/etc/http_ca.crt
    ssl_verify false
    scheme https
    host 192.168.1.152
    port 9200

    logstash_format true
    logstash_prefix fluentd
  </store>
</match>

@timestamp フィールドを使うので logstash_format: true を設定しています

  • docker run --name fluentd -d -p 24224:24224 -p 24224:24224/udp -v $(pwd):/fluentd/etc -e FLUENTD_CONF=fluent.conf my_fluentd

あとは fluentd にログを投げるコンテナを起動すれば OK です

  • docker run --rm --log-driver=fluentd --log-opt fluentd-address=host.docker.internal:24224 --log-opt tag="docker.{{.Name}}" alpine /bin/sh -c "while :;do date; sleep 3; done;"

動作確認

Kibana を確認して fluentd インデックスにログがあることを確認します
Discover で棒グラフが表示されない場合は

最後に

ElasticSearch9 を docker で動かしてみました
認証方法などはほぼ ES8 と変わってませんでした

fluentd からログを送信する際にも認証情報は必要になるので注意しましょう

参考サイト

2022年5月9日月曜日

ElasticSearch8 を docker で起動する

ElasticSearch8 を docker で起動する

概要

いろいろと起動方法が変わっていたので試してみました

環境

  • Ubuntu 18.04
  • docker 20.10.7
  • ElasticSearch 8.1.3
  • Kibana 8.1.3

max_map_count 変更

ERROR: [1] bootstrap checks failed. You must address the points described in the following [1] lines before starting Elasticsearch. というエラーが発生して ElasticSearch が起動しないので事前に変更します

  • sudo sysctl -w vm.max_map_count=262144

ElasticSearch 起動

シングルノードで起動します

  • docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" --name es docker.elastic.co/elasticsearch/elasticsearch:8.1.3

elastic ユーザのパスワードリセット

ElasticSearch にアクセスする elastic ユーザのパスワードを作成します
ターミナルに表示されたパスワードをメモしておきましょう

  • docker exec -it es /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic -a

ここで ElasticSearch にアクセスできるか確認

一旦アクセスできるか確認します
自動で生成されるクライアント証明書は localhost アクセス用のなので注意してください

  • docker cp es:/usr/share/elasticsearch/config/certs/http_ca.crt .
  • curl --cacert http_ca.crt -u elastic https://localhost:9200

Enrollment token の作成

Kibana が ElasticSearch にアクセスするためのトークンを生成します
ターミナルに表示される eyxxx という文字列をコピーしておきます

  • docker exec -it es /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s kibana --url "https://localhost:9200"

Kibana の起動

  • docker run -d -p 5601:5601 --name kibana docker.elastic.co/kibana/kibana:8.1.3

動作確認

アクセスする URL は以下で確認できます

  • docker logs kibana

URL の後ろに code が含まれている URL にアクセスしましょう

http://192.168.100.10:5601/?code=xxxx

事前に取得した Enrollment token を入力します
Kibana -> ElasticSearch のアクセス経路は docker 内のネットワークを使用しているようなので ElasticSearch と Kibana は必ず同じネットワークに所属させるようにしてください (今回は default ネットワークを使っています)

設定が完了してログイン画面が表示されれば OK です

elastic ユーザでログインできることを確認しましょう

最後に

セキュリティ面がだいぶ強化されログインや Kibana からの接続時に証明書や認証が含まれるようになっていました

各種 SDK を使っている場合もいろいろとその辺りの変更が入っているかなと思います

参考サイト

2019年10月4日金曜日

Kibana でフィールドを分割して新しいフィールドとして登録する方法

概要

普通にやろうとすれば td-agent 側の format を使ってフィールドに分割すると思います
何らかの理由で td-agent 側が操作できない場合は Kibana 側だけでも解決することができます
Kibana の Scripted field という機能を使います

環境

  • macOS 10.14.6
  • Kibana 7.4.0

Scripted field とは

簡単に言えば特定のフィールに対して Groovy を使って値を抽出する方法です
文字列を分割したり数値のフィールド同士を計算した結果を新しいフィールドとして登録することができます

fielddata=true にする

今回は Scripted field でテキストのフィールドを扱おうと思います
実は ElasticSearch はデフォルトだとテキストのフィールドに対して Scripted field を使うことができます
なので ElasticSearch のマッピングに fielddata=true フラグを設定する必要があります

例えば fluentd という名前のインデックスのマッピングで log というテキストフィールドがある場合にこのフィールドに対して fielddata=true を設定する場合は以下のようなクエリを ElasticSearch に対して投げます

curl -X PUT "localhost:9200/fluentd/_mapping?pretty" -H 'Content-Type: application/json' -d'
{
  "properties": {
    "log": { 
      "type":     "text",
      "fielddata": true
    }
  }
}
'

インデックス名やフィールド名を適宜変更して fielddata=true にしましょう

Scripted field の作成

まずは Kibana の Index Patterns にアクセスします
そして該当のインデックスを選択し「Scripted fields」タブを選択します
そして右側にある「Add scripted field」 を選択します

スクリプトで解析したあとの新しいフィールドの情報を登録します
以下のように登録しましょう

  • Name・・・status
  • Language・・・painless
  • Type・・・number
  • Format・・・Default
  • Popularity・・・0

今回は文字列からステータスコードを取得してみます
なので結果としては数値が返却されるスクリプトを作成します

スクリプトをコーディング

その下にスクリプトを登録するテキストフィールドがあるので登録します
今回は以下のようなスクリプトになります

def log = doc['log.keyword'].value;
if (log != null) {
    // Debug.explain(log);
    def splited = log.splitOnToken(' ');
    try {
        return Integer.parseInt(splited[8]);
    } catch (Exception e) {
    }
}
return 0;

スクリプトを実行できる環境も備わっておりコーディングしながらデバッグすることができます
「Get help with the syntax and preview the results of your script.」をクリックすると右ペインにスクリプトを実行する環境が表示されます
シンタックスエラーやコンパイルエラーの場合はその旨が右ペインに表示されます

エラーが出なければ「Create field」を選択して完了です

スクリプト解説

少し解説します
スクリプトは Kibana が独自で作成している painless という言語になりますがほぼ Groovy っぽく書けます
Groovy なので Java の API も使えます
また painless として独自で作成している関数などもあるようです (splitOnToken はおそらくそれ)
詳しくは参考サイトにもある API リファレンスを参照してください

既存のフィールドを参照するには doc['hoge'].value という感じで参照します
テキストフィールドの場合には .keyword を付与しないとテキスト情報を取得できないので注意してください

あとは状況に応じて数値の情報を return すれば OK です

注意事項

このページの一番下にもあるのですが Scripted field を追加した瞬間にすべてのデータに対してスクリプトが適用されるため負荷が高まる可能性があります
そのせいで ElasticSearch がダウンする可能性もあるので追加する場合は慎重に追加してください

最後に

Scripted field を使って既存のフィールドをパースして新たなフィールドを追加してみました
td-agent などのロガーサイドに手を加える必要がなく Kibana だけで完結できるのは嬉しい点かなと思います
フィールドを使う場合には最初に fielddata=true を投入する必要があるのでそこは注意が必要です

参考サイト