🚨

SentinlからPraeco(ElastAlert2)へ! Elasticsearch v7のログ監視&アラートを無料で実現する

2024/12/08に公開

技術記事執筆には不慣れですが、(ElastAlert2はともかく)Praecoに関する日本語記事はほとんど見つからなかったため、初投稿してみます。

TL;DR

  • Elasticsearch(ES), Kibanaが稼働するサーバがEOLを迎え、リニューアルに伴いこれらをv6からv7.17へアップグレードした。
  • 従来の構成では、Kibanaへの直接統合が可能なSentinlでログ監視&アラートを実現していたが、Sentinlは現状Kibana v7以降に対応していない。
  • OSSとして利用しやすい代替ソリューションは実質ElastAlert2のみであったが、naiveなElastAlert2はルール設定が煩雑なため、GUIを提供してくれるPraecoを採用。
  • 「各Praecoインスタンスがローカルファイルシステムにアラート設定を保持する」という仕組み上、Praecoを複数サーバ上に冗長化して運用すると設定の不整合が予想されるので、外部ストレージをs3fsで各サーバの該当ディレクトリにマウントし、single-source-of-truthとした。

Asis

リニューアル前のログ監視アーキテクチャ
リニューアル前のログ監視アーキテクチャ

Tobe

新規ログ監視アーキテクチャ
新規ログ監視アーキテクチャ

取り組み

1:ログ監視&アラート発火の代替ソリューション検討

私のチームでは、アプリケーションレベルのログ監視用にES/Kibana/fluentdを利用しており、動作状況の分析や不具合の検知といったシンプルなユースケースが主です。
なので概ねスムーズにアップグレードを行えると想定していたのですが、ほぼ唯一にして最大の課題は、これまでログ監視&アラートソリューションとして活用していたSentinlがKibanaのv6.xまでにしか対応していないということでした。
(2024/12/07現在、残念ながらこちらのIssueでメンテの停止が宣言されています)
https://github.com/sentinl/sentinl/issues/814#issuecomment-2076947948

私たちのログ監視基盤はfree版のES/Kibanaに依拠していたため、新規構成のアラート機能においてもフリーで運用可能なソリューションが求められます。
求められる機能は、「ES上のindexへのqueryをもとに、PagerDutyのAPIを叩いてアラートを発火できる」ことです。
以下のような比較検討[1]の末、Praecoを導入することになりました。

  • Kibana alerting
    • ❌PagerDutyなどの3rd party connectorと連携するためにはPratinum以上のライセンスが必要
  • Watcher
    • ❌導入にはPratinum以上のライセンスが必要
  • fluentd/LogstashなどからPagerDutyを直で叩く
    • ❌一定以上複雑な条件に基づくアラート発火が難しい
    • ❌クライアントアプリ側に設定が散逸して管理困難
  • Praeco
    • ElastAlert Serverと協働して、GUIからElastAlert2を利用してアラート設定ができる
      Praecoのアーキテクチャ
      Praecoのアーキテクチャ
    • メンテが現状アクティブなGPLv3のOSSで、ES v7.xに対応している

2:Praecoのインストール

上記Tobe図のように、ESクラスタのData nodesを参照する形で、独立したサーバ上に起動します。
起動手順自体はPraecoレポジトリのQuickstartに従うだけです。

git clone https://github.com/johnsusek/praeco.git
cd praeco
# アラート設定が保持されるディレクトリ
mkdir -p rules rule_templates
chmod -R 777 rules rule_templates
# ElastAlertの通知先の設定。SlackのWebhook URLについてはすでに出力ファイル内にfieldが存在するようなので、直接編集してもOKか
# echo "slack_webhook_url: ''"  | sudo tee -a rules/BaseRule.config >/dev/null
export PRAECO_ELASTICSEARCH=<ip of LB for es-data-nodes>
docker compose up

VIPを設定し、http://<VIP>:8080をブラウザで開くと、PraecoのUIが表示されました!
ローカルで試す場合はlocalhost:8080でOKです。

Praecoでは"Rules" -> "Add rule"から新規アラートルールの作成が行えます。
PagerDutyと連携するためには、PagerDuty上で"Service Directory"からアラートを紐づけたいServiceを開き、"Integrations"タブから"Events API V2"の設定を追加して、"Integration key"を発行しておきましょう。
アラート作成ページ下部の"Destination"でPagerDutyを選択し、"Service key"に上記keyを入力すればOKです!
アラート設定
アラートをPagerDutyに通知する設定
アラート作成ページ最下部の"Test"から、指定した条件でlogがヒットするか否か&アラートが(Destinationへの通知まで含めて)正しく発火するか否かをテストすることができます。
テストアラート
アラートのテスト送信

3:Praecoの冗長化と設定一貫性の担保

素朴に冗長化する場合の課題

上記の手順で無事にPraecoを立ち上げられました。
シングルインスタンスはこれでOKなのですが、社内のポリシー等を考慮すると、ログ監視基盤の各Componentは可能な限り冗長化しておきたいです。
(内部のDeveloperが利用するアラート管理ツールが高負荷でダウンするようなケースは考えにくいですが、念には念をというやつです)

冗長化するだけであれば、追加でPraecoインスタンスを別サーバ上に起動してVIPのリクエスト転送対象に追加するだけでOKなのですが、ここで一つ課題がありました。
Praecoはホスト上のrules, rule_templatesなどをコンテナへバインドマウントして動作し、GUI上のユーザのアラートルール操作はこれらのディレクトリへ反映されます。

Praecoのdocker-compose.yml
services:
  elastalert:
    image: 'praecoapp/elastalert-server'
    ...
    volumes:
      ...
      - ./rules:/opt/elastalert/rules
      - ./rule_templates:/opt/elastalert/rule_templates

これは、各インスタンスで作成されたアラートルールが、各々のホスト上に独立して永続化されることを意味します。
よって、VIP経由でアクセスを提供する今回の構成の場合、何も対策しないと以下のリスクに繋がります。冗長化の末に保守性・機能性を残っては本末転倒ですね。

  • リクエストが転送されるインスタンスに応じてユーザから見えるアラートルールが異なり、アプリケーション群の運用しやすさを損なう
  • インスタンスがダウンした場合、ダウンした側が保持していたルールに基づくアラートが検知できなくなる

アラート設定を一元化する

ぱっと考えついたのが以下の対処法でした。

  • NFS(Network File System)を各サーバのrules, rule_templatesにマウントする。
  • rsyncでサーバ間のアラートルールファイル群を同期する。
  • S3互換のオブジェクトストレージを用意し、s3fsで各サーバのrules, rule_templatesにマウントする。

NFS利用には社内プラットフォーム部への申請が必要でありリードタイムがかかってしまうこと、rsyncは双方向同期に向かないことなどから、最終的にs3fsのオプションを選びました。

ストレージをマウントする手順も基本的にs3fs公式のREADMEに従えばOKですが、今回のユースケースにおいては権限周りで少しだけ注意点があります。
というのも、s3fsを実行すると、デフォルトではマウントポイント以下のownerはroot、権限は700になり、Praecoの各コンテナから利用できません。よって、以下の対応が必要です。

  • /etc/fuse.confでuser_allow_othersをenableする。
    • 下記オプション付与の前提として必要。
  • s3fs実行時に-o allow_others,umask=0000を付与する。
    • allow_others: root以外のユーザからマウントポイントへのアクセスを許可する。
    • umask=****: マウントポイント内のumask値を設定する。

これにより、Praecoのコンテナが外部ストレージ上のbucketをアラート設定用ディレクトリとして利用できるようになります。
上記を踏まえてアレンジした手順がこちらです。

インストール
# install - Ubuntuの場合
sudo apt install s3fs
# install - RHE系の場合
sudo yum install epel-release
sudo yum install s3fs-fuse
# ストレージアクセス用credentialの定義
echo ${ACCESS_KEY_ID}:${SECRET_ACCESS_KEY} > ${HOME}/.passwd-s3fs
chmod 600 ${HOME}/.passwd-s3fs
# /etc/fuse.confを修正
sudo vim /etc/fuse.conf
> "user_allow_others"のコメントアウトを外す
# マウント実行
s3fs <bucket1> rules -o passwd_file=${HOME}/.passwd-s3fs -o allow_other,umask=0000,use_path_request_style -o url=<URL of Storage>
s3fs <bucket2> rule_templates -o passwd_file=${HOME}/.passwd-s3fs -o allow_other,umask=0000,use_path_request_style -o url=<URL of Storage>

これを各サーバで実行することで、冗長化されたPraecoインスタンス群が外部ストレージを介してアラートルールを共有できるようになりました![2]

まとめ

レガシーなElastic Stackからの移行においてSentinlを置き換える手段として、Praecoはいい代替案になりうるのではないかなと思います。
アプリケーションログ監視については開発者が直接設定する現場も少なくないでしょうから、親切なGUIがあるのも推せるポイントですね。

s3fsについても、Linuxサーバ管理に不慣れな自分でも簡単に利用出来て驚きました。
自分と全く同様のニーズを抱える人は多くはないでしょうが、(書き込み速度を重視しないのであれば)シンプルに共有ディレクトリを構成する手段として引き出しに入れておいてもいいのかなと思います。

この記事がどなたかの参考になれば幸いです。

参考

https://qiita.com/rururu_kenken/items/6207ab68378b70f408bb
https://designetwork.daichi703n.com/entry/2019/03/24/Praeco-ElastAlert-GUI
https://tech.classi.jp/entry/2022/12/07/150330

脚注
  1. 2024/11月時点での調査なので、今後状況が変わる可能性はあります ↩︎

  2. rule設定の際にrealert(deault 60s)等を活用することで、各インスタンスが同じlog queryについて重複してアラートを発火することを予防できます。 ↩︎

Discussion