Zabbixにはディスカバリルールと呼ばれる、監視対象からの情報取得結果に応じて、自動的に監視するアイテムやトリガーを生成する機能がある。
WindowsやLinuxの標準テンプレートでは、ディスカバリルールが実装されており、例えばネットワークインターフェースが複数ある場合も自動認識がされるため、それぞれのネットワークで個別で監視設定を行うことなく、必要な監視設定が実施される。
今回、OSSのロードバランサーであるZEVENETを例に、実際にディスカバリルールを作成してみたので、その手順を記載する。先に伝えると、なかなかうまくいかずに難航したので、その内容も含め記載をさせていただく。
環境
Zabbixは5.0を使用し、ディスカバリルールによる監視対象として、OSSのロードバランサーであるZEVENETを使用する。ZEVENETに登録した負荷分散対象に状態変化があった際に、トリガーにて検知できるようディスカバリルールを作成する。
- Zabbix 5.0.10
- ZEVENET 5.11.0
ディスカバリルール作成手順
1. ディスカバリ用のデータ取得コマンドを検証
ディスカバリ時には、監視対象より必要な情報をJSON形式で取得する必要がある。以下にフォーマットを記載する。変数名を"{#変数名}の形式で定義し値を取得すると、取得した値の数だけアイテムやトリガーを自動で生成させることができる。
{
"data": [
{
"{#変数名1}": "値1"
},
{
"{#変数名2}": "値2"
},
~(繰り返し)~
{
"{#変数名X}": "値X"
}
]
}
ZEVENETの場合は、コマンドラインツールであるzcliを使うことで、JSON形式のデータを取得することができる。ただし、細かい箇所で記載が異なることから、sedを使って置換を行うことで対処する。
以下が、実際にZEVENETにて取得したデータとなる。変数名は{#FARMNAME}としており、それぞれに負荷分散対象グループの名前が入っている。
# /usr/bin/zcli -nc farm list -filter farmname | sed -e 's/params/data/g' -e 's/farmname/{#FARMNAME}/g'
{
"data": [
{
"{#FARMNAME}": "farm-chrony"
},
{
"{#FARMNAME}": "farm-postfix"
},
{
"{#FARMNAME}": "farm-squid"
},
{
"{#FARMNAME}": "farm-unbound"
}
]
}
2. テンプレートを作成
ディスカバリルールを作成する前に、テンプレートを作成する。
先ほど作成したJSON形式の情報取得コマンドは、監視対象に対してSSHによる実行を行うことから、マクロにてあらかじめSSHログイン用のパスワードを設定しておく。
3. ディスカバリルールを作成
作成したテンプレートの「ディスカバリルール」を選択し、ディスカバリルールを以下の通り作成する。
| 設定項目 | 設定値 | 説明 |
|---|---|---|
| 名前 | ZEVENET Farm discovery | 任意で設定。 |
| タイプ | SSHエージェント | zcliによるコマンド実行が必要となるため、SSHエージェントを選択する。 |
| キー | ssh.run[zcli] |
任意で設定。 |
| 認証方式 | パスワード | SSH接続時にパスワードによる認証を利用する。 |
| ユーザー名 | root | |
| パスワード | {$ZEVENET_PASS} |
マクロで設定したパスワードを指定。 |
| 実行するスクリプト | /usr/bin/zcli -nc farm list -filter farmname | sed -e 's/params/data/g' -e 's/farmname/{#FARMNAME}/g' |
事前に作成したJSON形式のデータを取得するコマンドを指定。 |
| 監視間隔 | 1h | 今回は1時間間隔で設定したが、要件に応じた間隔に設定する。頻繁に変更される内容ではない場合は、監視間隔を長くしても問題ないと想定。 |
| 存在しなくなったリソースの保持期間 | 3d | 一度ディスカバリした情報が削除された場合に |
4. ディスカバリのテスト
「ディスカバリルール」作成画面の「テスト」ボタンを押すことで、ディスカバリのテストを行うことができる。
取得対象のホストのIPアドレス、マクロで設定しているSSH接続用のパスワードを入力し、「値の取得とテスト」ボタンを押す。問題なく成功する場合は、結果欄にJSON形式のデータが表示される。
ただし、いくつか失敗するパターンも経験したので補足する。
Cannot read data from SSH serverのエラーで失敗する
テストをする際に以下のようにCannot read data from SSH serverのエラーが表示され、SSHの接続に失敗してしまう。この事象は毎回必ず発生するものではなく、数回に1回ランダムで発生する事象となる。
調査したところ、以下URLに原因が書いてあった。libsshのバグであり、バージョン0.9.0を使用している場合に発生するようだ。
- [ZBX-17756] SSH. Run will often report an error: “Cannot read data from SSH server” - ZABBIX SUPPORT
libsshのバージョンが0.9.5以降であれば確実に直っているようだが、私の環境では0.9.4にバージョンアップすることで事象が解消した。
※不要と思ったが、バージョンアップ後念のため再起動を実施した。
# rpm -qa | grep libssh
libssh-config-0.9.0-4.el8.noarch
libssh-0.9.0-4.el8.x86_64
# dnf update libssh.x86_64 -y
# reboot
# rpm -qa | grep libssh
libssh-config-0.9.4-2.el8.noarch
libssh-0.9.4-2.el8.x86_64
Invalid discovery rule valueのエラーで失敗する
Invalid discovery rule valueは、JSON形式のデータが正しく取得できていないことを表すエラーとなる。Zabbix上のエラーメッセージを見ると、確かに[38;5;188mといったおかしな情報が混入している。
Invalid discovery rule value: cannot parse as a valid JSON object: invalid object name at: '[38;5;188m"[0m[38;5;188mdata[0m[38;5;188m"[0m: [
{
[38;5;188m"[0m[38;5;188m{#FARMNAME}[0m[38;5;188m"[0m: [38;5;82m"[0m[38;5;82mfarm-chrony[0m[38;5;82m"[0m
しかし、実際にZEVENET上で直接コマンドを実行し取得した値は問題がないように見えるため、原因特定が難航した。
色々調べた結果、これは「ANSIエスケープシーケンス」呼ばれる制御文字列であり、ZEVENETが結果出力に色付けする際に利用しているものが、そのままZabbixに情報として連携されてしまうことが原因だった。
ちなみに、ANSIエスケープシーケンスでは[38;5;NmでNで指定した番号のカラーコードで色付けされ、[0mで設定がリセットされる。
ZEVENETの場合はzcliのオプションで-ncを付けることで、結果出力に色付けをしなくなる。このオプションを付けることで事象を解消することができた。
4. アイテムのプロトタイプを作成
ディスカバリされた情報をもとに作成されるアイテムのプロトタイプを作成さる。JSON形式で受け取るデータの変数名(今回の場合は{#FARMNAME})を名前やキーに使うことで、検出した対象ごとにアイテムを作成することができる。
「ディスカバリルール」→「アイテムのプロトタイプ」にて、以下の通りアイテムのプロトタイプを作成する。
| 設定項目 | 設定値 | 説明 |
|---|---|---|
| 名前 | ZEVENET Farm "{#FARMNAME}" Status |
ディスカバリされたアイテム名が重複しないよう、変数{#FARMNAME}を名前に入れるようにする。 |
| タイプ | Zabbixエージェント(アクティブ) | 今回はログ監視となるため、左記のタイプを選択する。 |
| キー | log[/var/log/messages,"farmguardian.*{#FARMNAME}",,,skip] |
logを使用し、変数{#FARMNAME}の文字列が含まれるログの取得を行う。 |
| データ型 | ログ | ログの取得のため、左記の設定を行う。 |
| 監視間隔 | 1m | 任意で設定。 |
5. トリガーのプロトタイプを作成
ディスカバリされた情報をもとに作成されるトリガーのプロトタイプを作成さる。アイテムと同様に、JSON形式で受け取るデータの変数名(今回の場合は{#FARMNAME})を名前やキーに使うことで、検出した対象ごとにアイテムを作成することができる。
「ディスカバリルール」→「トリガーのプロトタイプ」にて、以下の通りトリガーのプロトタイプを作成する。
| 設定項目 | 設定値 | 説明 |
|---|---|---|
| 名前 | ZEVENET Farm "{#FARMNAME}" Status Down from {HOST.NAME} |
ディスカバリされたトリガー名が重複しないよう、変数{#FARMNAME}を名前に入れるようにする。 |
| 深刻度 | 軽度の障害 | 任意の深刻度で設定。 |
| 障害の条件式 | {Template Net Zevenet:log[/var/log/messages,"farmguardian.*{#FARMNAME}",,,skip].regexp(down)}=1 |
負荷分散対象のサーバーがダウンしたことを検知させるため、downの文字列があった場合に検知させる。 |
| 正常イベントの生成 | 復旧条件式 | 今回は復旧条件式を設定。 |
| 復旧条件式 | {Template Net Zevenet:log[/var/log/messages,"farmguardian.*{#FARMNAME}",,,skip].regexp(resurrect)}=1 |
負荷分散対象のサーバーが復旧したことを検知させるため、resurrectの文字列があった場合に検知させる。 |
6. 動作確認
作成したテンプレートを実際にZEVENETのホストに割り当てを行い動作確認を行う。
ディスカバリルールで設定した監視間隔を過ぎると、負荷分散対象ごとにアイテムとトリガーが作成されていることが確認できた。

















































