noharaのブログ

興味のあることについてゆる~く書きます

node-redからzabbixにデータを飛ばす

node-redで取得した値をzabbixに飛ばすメモ。

node-red初めて触ったのでおかしいところあればこっそり教えてください。

方針

すぐ思いつくのは以下の二つだと思います。

  1. node-redからcsv等でログを吐いて、zabbix-agentを使ってアクティブチェックで値を送り付ける
  2. node-redから直接zabbixに値を送り付ける(zabbix_senderのような感じ)

今回は2番目の node-redから直接zabbixに値を送り付ける を実装してみます。

実装した後気づいたのですが、すでにnpmのパッケージとして存在しているようです(未検証)

環境

公式のdockerコンテナを利用

Zabbix: 4.2.4
node-red: 0.20.6

準備

  1. node-redを準備します

    docker run -it -p 1880:1880 --name mynodered nodered/node-red-docker

  2. zabbixサーバーを用意します

    docker run --name some-zabbix-appliance -p 80:80 -p 10051:10051 -d zabbix/zabbix-appliance

  3. zabbixサーバー側にアイテムを登録します

    f:id:nohararc:20190703002913p:plain
    item

    zabbix_sender使う時と同じですが、TypeをZabbix trapperとしているところだけ注意

node-red側の実装

全体図

f:id:nohararc:20190703003202p:plain
node-red全体図

  1. 入力部 Injectノードのペイロードに以下のjsonを記入

    複数の値を飛ばしたい場合は、data配列の中に追加すればよい

     {
         "request": "sender data",
         "data": [
             {
                 "host": "Zabbix server",
                 "key": "node-red",
                 "value": 20
             }
         ]
     }
    
  2. 関数部 functionノードのコード部分に以下を追加

     var payload = new Buffer(JSON.stringify(msg.payload), 'utf8'),
           header  = new Buffer(5 + 4); // ZBXD\1 + packed payload.length
    
     header.write('ZBXD\x01');
     header.writeInt32LE(payload.length, 5);
     msg.payload = Buffer.concat([header, new Buffer('\x00\x00\x00\x00'), payload]);
    
     return msg;
    
  3. 出力部 zabbixの待ち受けポート(デフォルトは10051)にtcpでデータを送り付ける

     ホスト: zabbixサーバーのIP
     種類:  接続
     ポート: 10051
     メッセージを送信するたびに接続を切断: チェック
    

完成

(Injectノードで値を色々変えてます)

f:id:nohararc:20190703005141p:plain
グラフ

おまけ

ハマったところ

  • Zabbix公式でheaderのpython実装はPython2
  • headerという単語だけをみてなぜかhttpでつなぎに行ってしまう(ドキュメント読みましょう)

node-redで実装する前に簡単にPython3で実装したなにか

import struct
import telnetlib
import json

data = {"request": "sender data", "data": [{"host":"Zabbix server", "key": "test_zabbix_sender", "value": 100}]}
data_json = json.dumps(data)
header = b"ZBXD\1" + struct.pack("<Q", len(data_json))

packet = header + data_json.encode()

tn = telnetlib.Telnet(host="127.0.0.1", port="10051")
tn.write(packet)
print(tn.read_all().decode())
tn.close()

参考

GitHub - shamil/node-zabbix-sender: A zabbix_sender implementation, to send zabbix item(s) using the zabbix trapper protocol.

node-red-contrib-zabbix-sender - Node-RED