背景
去年,モニタリングサービスを Zabbix から Mackerel に移行したときに,ファイルの変更検知(例えば /etc/passwd
など)を Mackerel でうまく実現できなくて,諦めてしまっていた経緯があった.もしかしたら公式機能であるのかも...?
Zabbix だと
Zabbix から公式に提供されている「Template OS Linux」の中に /etc/passwd
の変更検知をする設定がある.ちなみに,今回は Zabbix 2系を前提にしている.
- アイテム
- 名前 :
Checksum of /etc/passwd
- キー :
vfs.file.cksum[/etc/passwd]
- 名前 :
- トリガー
- 名前 :
/etc/passwd has been changed on {HOST.NAME}
- 条件式 :
{Template OS Linux:vfs.file.cksum[/etc/passwd].diff(0)}>0
- 名前 :
仕組みをザックリと説明すると,Zabbix で vfs.file.cksum
を使うとファイルのチェックサム(例えば 1938292000
のような数値)を取得できるため,その値をメトリクスとして保持している.さらに Zabbix のトリガー条件式では .diff
という「前回のメトリクスと違った場合」を検知する関数があるので,チェックサムが変更された場合にアラートを鳴らすことができる.逆に言うと「変更されたことを検知できる」だけであって「どのように変更されたか?は検知できない」ことに注意する.
メルカリの事例
最近開催されていた Mackerel DAY の資料を見ていたら,メルカリでは diff-detector という独自ツールを使って /etc/passwd
の変更検知を Mackerel で実現しているとのことで,さっそく試してみようと思った.diff-detector 以外でも,メルカリの Mackerel 活用事例が圧倒的で非常に勉強になった!スゴすぎ...!
diff-detector を読んだ
まずは diff-detector 単体の機能を把握するために,実装を読んでみた.Go と Perl 版があるけど,今回は Go を選んだ.実装としては,少し書き捨てっぽい印象も受けたけど(go fmt
と goimports
を流すと結構変更点が出た...w),必要十分な機能は揃っていた.
- 特徴
- ファイルの変更検知ではなく「標準出力の変更検知」ができる
- 「標準出力の変更検知」ができるので,検知の対象としてコマンドを指定する(例えば
cat /etc/hosts
など) - 一次ディレクトリに新旧の標準出力を含めたファイルを保持しているため「どのように変更されたか?」の具体的な変更点も確認できる
- 初回実行と変更なしの場合は
0
が返り,変更ありの場合は1
が返る
- 実装
- コマンドオプションの終点を意味する
--
をパースするためにflags.NewParser(opts, flags.PassDoubleDash)
を使っている - 標準出力(旧)は
os.TempDir()
で取得している/tmp/500-diff-detector-c9f995bb55ec9fc62e0ca720b3ebfbad
のような絶対パスになる
- 標準出力(新)は
ioutil.TempFile()
で取得している/tmp/temp766915122
のような絶対パスになる
- 一次ディレクトリに保持するファイル名に使うハッシュにソルト値を含めたい場合は
--identifier
オプションが使える - 変更検知は
diff -U 1
を使っている-U
は-u
と同じで,差分の前後の行数を指定することができる
- コマンドオプションの終点を意味する
具体的には以下のように実行する.
# 初回実行 $ diff-detector -- cat /etc/passwd Notice: first time execution command: 'cat /etc/passwd' # 変更なし $ diff-detector -- cat /etc/passwd OK: no difference: ```root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:...``` # 変更あり $ diff-detector -- cat /etc/passwd NG: detect difference: ```@@ -31 +31,2 @@ jenkins:x:502:502::/home/jenkins:/bin/bash +kakakakakku:x:503:503::/home/kakakakakku:/bin/bash```
Mackerel と diff-detector を組み合わせる
ここからやっと本題で,Mackerel と diff-detector を組み合わせる.基本的には diff-detector をチェックプラグインとして使えるようにするだけで良かった.オプションなどは公式ドキュメントを見てカスタマイズすると良さそう(例えば /etc/passwd
のインターバルをもう少し長くするなど).
設定は簡単で /etc/mackerel-agent/mackerel-agent.conf
に以下を追加した.
[plugin.checks.diff_etc_passwd]
command = "/usr/local/bin/diff-detector -- cat /etc/passwd"
この状態で変更検知を起こすと,以下のようにアラートが Slack に通知された.Zabbix のときには実現できていなかった「変更点」も確認できるので,非常に便利だった.
関連する公式チェックプラグイン
id:Soudai さんに教えて頂いたファイル関連の公式チェックプラグインも紹介しておこうと思う.今回の変更検知の要件には合わなかったが,知っておくといざ必要になったときに良さそう.
- check-file-age
- go-check-plugins/check-file-age at master · mackerelio/go-check-plugins · GitHub
- 指定したファイルのサイズと経過秒数(○秒以上,経過したか?)を監視できる
- check-file-size
- go-check-plugins/check-file-size at master · mackerelio/go-check-plugins · GitHub
- 指定したディレクトリ直下にあるファイルの総サイズを監視できる
--depth
オプションで,深さも指定できる
まとめ
- Mackerel でファイルの変更検知を実現するために diff-detector を試してみた
- 「変更されたこと」だけではなく「どのように変更されたか?」も検知できるので,非常に便利だった
- diff-detector のような汎用的なチェックプラグインが Mackerel 公式であっても良さそう 🙏
- Mackerel の監視設定は現在「閾値」しか設定できないので,Zabbix の
.diff
のような「前回のメトリクスと違った場合」を設定できると,監視設定の幅が広がりそう 🙏
関連記事
メルカリの Mackerel 活用事例を詳細に解説されている.すごく参考になった!