あきろぐ

いろいろめもするよ

RubyでZabbixアラートをSlackに通知する

概要

Rubyの勉強をかねて、今までシェルスクリプトでZabbixのアラート通知をしていたものをRubyで書き換えてみました。
設定方法とつまずいたところをまとめたいと思います。

環境

  • CentOS7.6
  • zabbix4.0
  • Ruby2.4

設定方法

slackのWebhook URLを取得する

通知したいチャンネルのWebhook URLをまず取得します。
対象のワークスペースの対象チャンネルにIncoming Webhookインテグレーションを追加します。
f:id:akngo22:20191030161303j:plain
表示されたWebhook URLをコピーし、スクリプト内でURLを指定します。

zabbixアラート用スクリプトを作成する

今回は、"zabbix_notify_to_slack.rb"というスクリプトを作成しました。
作成したスクリプトは、githubに置いています。
github.com

zabbixアラート通知用ディレクトリにスクリプトを移動する

zabbixでは、アラートがあがったときに対象のディレクトリにスクリプトを配置しておくと自動的に実行されるので、対象ディレクトリを調べて移動させます。
Zabbixアラート用ディレクトリは、以下のように設定ファイルに書かれているので確認します。

# zabbixアラート用ディレクトリパスを確認
$ sudo cat /etc/zabbix/zabbix_server.conf | grep alertscripts
# AlertScriptsPath=${datadir}/zabbix/alertscripts
AlertScriptsPath=/usr/lib/zabbix/alertscripts
# 対象ディレクトリに移動
$ mv zabbix_notify_to_slack.rb /usr/lib/zabbix/alertscripts
# 忘れずにスクリプトに実行権限をつける
$ chmod +x /usr/lib/zabbix/alertscripts/zabbix_notify_to_slack.rb

zabbixで対象スクリプトが実行されるように設定する

Zabbixにログイン後、[Administration]>[Media Types]>[Create media type]をクリックし、以下のように、対象スクリプトスクリプトのパラメータを設定します。
f:id:akngo22:20191030145940j:plain

スクリプトパラメータに設定しているのは、Zabbixがサポートしているマクロです。今回は、{ALERT.SENDTO}、{ALERT.SUBJECT}、{ALERT.MESSAGE}の3つを使います。これらは、スクリプトを実行する際に使用するコマンドライン引数になります。
Zabbixのマクロ一覧は下記から確認することができます。
www.zabbix.com

続いて、[Administration]>[Users]>[Admin]をクリックし、メディアを追加します。[Add]をクリックします。
f:id:akngo22:20191030151654j:plain

Typeに登録したメディアタイプを選択し、Send toにはSlackのチャンネル名、アラートを通知したい深刻度にチェックを入れます。今回は、深刻度が[Warning]以上のものをSlackに通知させたいと思います。
f:id:akngo22:20191030151729j:plain

最後にアクションの設定をします。[Configuration]>[Actions]>[Create action]をクリックします。
[Operations]の[Operations]>[New]から
f:id:akngo22:20191030152736j:plain

"Send to User"に先ほどメディアを追加したユーザーを選択し、今回はSlackにのみ通知したいので"Send only to"でslackのメディアを選択しました。
f:id:akngo22:20191030153012j:plain
これで設定完了です!

意図的にZabbixアラートを発生させる

今回、ZabbixのトリガーでCPU使用率が80%超えたらアラートを出すようにテストアラートを設定したので、意図的にCPUの負荷を上げます。yesコマンドでサーバーのCPU負荷が80%超えるようにします。

# CPU負荷を上げる(今回はyesコマンドをバックグラウンドで5回実行することで負荷が80%を超えました)
$ yes > /dev/null &
$ yes > /dev/null &
$ yes > /dev/null &
$ yes > /dev/null &
$ yes > /dev/null &
# cpu使用率を確認する
$ top
# アラートが発生し、slackに通知が飛ぶことを確認したらkillコマンドでジョブを止める
$ kill %1 %2 %3 %4 %5
[1]   Terminated              yes > /dev/null
[2]   Terminated              yes > /dev/null
[3]   Terminated              yes > /dev/null
[4]-  Terminated              yes > /dev/null
[5]+  Terminated              yes > /dev/null
# ジョブが止まっていることを確認する
$ jobs
[1]   Terminated              yes > /dev/null  (wd: /usr/lib/zabbix/alertscripts)
[2]   Terminated              yes > /dev/null  (wd: /usr/lib/zabbix/alertscripts)
[3]   Terminated              yes > /dev/null  (wd: /usr/lib/zabbix/alertscripts)
[4]-  Terminated              yes > /dev/null  (wd: /usr/lib/zabbix/alertscripts)
[5]+  Terminated              yes > /dev/null  (wd: /usr/lib/zabbix/alertscripts)

slackにアラートが飛んでいるか確認する

対象チャンネルに通知が来ているか確認します。ちゃんとアラートが飛んできていればOK!
f:id:akngo22:20191030155122j:plain

つまづいたところ

ちょっとしたミスが多いですが、つまずいたところです。

zabbixにアラートが上がったのに通知が飛ばない

Zabbixで設定したアクションが有効になっているか確認してみましょう。ステータスが"Disabled"だと通知飛ばないのでご注意。
f:id:akngo22:20191030160110j:plain

アクションが実行されているが、失敗している

エラーメッセージを確認したところ、"permission denied"が発生していました。
対象スクリプトの最初に"#!/home/akina/.rbenv/shims/ruby"とインタプリタを指定していますが、Zabbixユーザーだとパーミッションがないよ!と怒られていました。なので、Zabbixユーザーでも実行できるようにパーミッションを変更します。
今回は、/home/akinaパーミッションに実行権限を付与しました。

$ chmod +x /home/akina/

rubyコマンドライン引数を取得する方法を間違えた

今までシェルスクリプトばっかり書いていたので、rubyでも同様に"$1"とか"$2"とか書いていたんですけど、間違いでした。。。rubyでは以下のように記載するんですね。勉強になりました・・・!

# argv[引数番号]でコマンドライン引数を取得できる
notify_channel=ARGV[0]
alert_subject=ARGV[1]
alert_message=ARGV[2]

おしまい!