ZabbixでPrometheusのExporterの値を収集

Zabbix Advent Calendarも中盤に差し掛かってきました。まだまだ枠空いてます。。
今日はZabbixとPrometheusがテーマです。

先日のZabbix Conference Japan 2018のアレクセイさんの講演でPrometheusのExporterに対応する開発を今後していくとの発表もありました。

* [講演資料(pdf)](https://assets.zabbix.com/img/zabconf2018_jp/presentations/01_zabconf2018.pdf)

Zabbix Roadmapにも4.2のバージョンのところに以下の記載があります。

* https://www.zabbix.com/roadmap#v4_2

```
Out of the box support of Prometheus exporters
It is already possible to extract data from arbitrary data sources using regular expressions, which is not always easy to configure.
This functionality is about native support of high-performance data collection from Prometheus exporters.
```

ということでおそらく今後、Zabbix側でExporterのフォーマットにZabbixがNative対応していくでしょう。

4.0の現時点では、どのようにExporterから情報を収集できそうかを試してみます。

# Node exporterを導入・実行

ひとまず、監視対象にサーバノードのリソース状況等の監視用の[Node exporter](https://github.com/prometheus/node_exporter)を導入します。

goのbuild済みバイナリがGithubで公開されているのでそれをダウンロードして展開します。

```
$ wget https://github.com/prometheus/node_exporter/releases/download/v0.17.0/node_exporter-0.17.0.linux-amd64.tar.gz
$ tar xvzf node_exporter-0.17.0.linux-amd64.tar.gz
```

展開したフォルダ内のnode_exporterコマンドを実行。

```
$ ./node_exporter-0.17.0.linux-amd64/node_exporter
```

これで、デフォルト設定だと9100ポート/TCPでnode-exporterが起動し、各種サーバ内の情報を返すようになります。試しにcurlで取得してみます。

```
$ curl -XGET http://サーバIP:9100/metrics
・・・略
# HELP node_cpu_seconds_total Seconds the cpus spent in each mode.
# TYPE node_cpu_seconds_total counter
node_cpu_seconds_total{cpu="0",mode="idle"} 305464.49
node_cpu_seconds_total{cpu="0",mode="iowait"} 1462.92
node_cpu_seconds_total{cpu="0",mode="irq"} 0
node_cpu_seconds_total{cpu="0",mode="nice"} 0
node_cpu_seconds_total{cpu="0",mode="softirq"} 633.15
node_cpu_seconds_total{cpu="0",mode="steal"} 0
node_cpu_seconds_total{cpu="0",mode="system"} 3749.97
node_cpu_seconds_total{cpu="0",mode="user"} 7824.49
node_cpu_seconds_total{cpu="1",mode="idle"} 307983.81
node_cpu_seconds_total{cpu="1",mode="iowait"} 1068.86
node_cpu_seconds_total{cpu="1",mode="irq"} 0
node_cpu_seconds_total{cpu="1",mode="nice"} 0
node_cpu_seconds_total{cpu="1",mode="softirq"} 214.7
node_cpu_seconds_total{cpu="1",mode="steal"} 0
node_cpu_seconds_total{cpu="1",mode="system"} 3425.68
node_cpu_seconds_total{cpu="1",mode="user"} 7742.01
・・・略
```

こんな感じです。

# ZabbixのHTTPエージェントアイテムを登録

では、つぎにZabbix側にアイテム登録していきます。今回は、ZabbixのHTTPエージェントの機能を使い、プログラムコード無しでチャレンジしてみます。
node-exporterに対してHTTPリクエストを投げて応答を取得するHTTPエージェントタイプのアイテムを以下のように登録します。

* 名前: Node Exporter (任意)
* タイプ: HTTPエージェント
* キー: prom.node.exporter (任意)
* URL: http://監視対象サーバIP:9100/metrics
* データ型: テキスト
* 更新間隔: 1m

すると、こんな感じで大量のノード情報がテキストとして登録されてきます。

![prometheus_node_exporter1.png](https://qiita-image-store.s3.amazonaws.com/0/45851/f80f1284-a11f-269e-3cfc-48c82076db49.png)

# Zabbixの依存アイテムを登録

Node Exporterから取れてくるテキスト情報だけでは扱えないので、Exporterのテキスト情報から必要な情報をピックアップして監視アイテムに登録します。
これには依存アイテムを活用します。

依存アイテムを作る前にPrometheusのExporterのフォーマットを理解しておきます。
[こちら](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md)で説明されてる通りテキストベースフォーマットとなっています。

簡単に書くと以下のような感じです。

```
メトリクス名{ラベル=ラベルバリュー} 値 タイムスタンプ
```
このフォーマットに従って、Zabbixの監視アイテムとして取り込みたいものを指定していきます。

例えばnodeのロードアベレージ1分平均値だと以下のような感じです。
```
# HELP node_load1 1m load average.
# TYPE node_load1 gauge
node_load1 0.45
```

Zabbixの依存アイテムとして以下のように設定します。

* 名前: node_load1 data (任意)
* タイプ: 依存
* キー: prom.node.exporter.node_load1 (任意)
* マスターアイテム: Node Exporter (先程登録したHTTPエージェントアイテム)
* データ型: 数値(浮動小数)
* 保存前処理:
    * 正規表現 =>
        * パターン: \nnode_load1\s(\S*)
        * 出力: \1

保存前処理の正規表現指定がポイントです。
node-exporterの/metricsで取得されるデータは、「改行(\n)」区切りで複数の情報が連携されてテキストとして保存されています。そのため、\nにつづいてnode_load1が記録されている箇所を正規表現でピックアップして、その後ろのvalueを後方参照で出力し、監視しています。

![prometheus_node_exporter2.png](https://qiita-image-store.s3.amazonaws.com/0/45851/af0553f8-31e1-99a6-242f-354cabe8f9e4.png)

# まとめ

やはり現状では正規表現で指定が必要であったりとちょっと連携はやりづらいですね。Issue Trackerの[こちらのチケット](https://support.zabbix.com/browse/ZBXNEXT-4865)で開発されているようなのでZabbix4.2の開発状況に要注目ですね。