Zabbixプロトコルを調べた

監視システム Zabbix の manager – agent 間通信のプロトコルを調べる機会があった。エージェントからデータを取得する zabbix_get コマンドの簡易版を自作したのでメモ。

Zabbix のサイトにある以下のドキュメントを参考にした。

パケットの構成

利用したのは Zabbix 1.8 系列なので、調査対象のプロトコルのバージョンは 1.4。パケットは以下の4つのフィールドで構成される。

Header:”ZBXD” 固定
Version:”1″ 固定
Data length:データ長。64ビット整数で表す(little-endian)。
Data:データ(ペイロード)。

zabbix_agent の実行例

Zabbix には マネージャーがエージェントに問い合わせるパッシブ監視と、エージェントがマネージャーに(ログなどを)データ送信するアクティブ監視の2つの監視がある。
zabbix_agent はパッシブ監視系でコマンドラインにキーを渡してエージェントに問い合わせる。

エージェントのバージョンを確認

$ zabbix_get -s localhost -k agent.version
1.8.14

/ のあるドライブの空き容量をパーセントで確認。

$ zabbix_get -s localhost -k vfs.fs.size[/,pfree]
36.600925

利用可能なキー一覧とその結果は $ zabbix_agent -p で確認できる。

Zabbix プロトコルを実装

この zabbix_get を Python で再実装して、プロトコルを体感する。Python のデータ型とバイナリの変換は struct モジュールを使う。

エージェント向けデータ作成

キー ‘agent.version’ を送信するためのデータを作成してみる。キーの長さを調べたあと、little endian の64ビット整数としてバイナリに変換すればよい。ヘッダー部のHeaderとVersionは固定。

>>> import struct
>>> key = 'agent.version'
>>> length = len(key)
>>> length
13
>>> struct.pack('<Q', length)
'\r\x00\x00\x00\x00\x00\x00\x00'
>>> struct.pack('<4sBQ', 'ZBXD', 1, length)
'ZBXD\x01\r\x00\x00\x00\x00\x00\x00\x00'
>>> struct.pack('<4sBQ', 'ZBXD', 1, length) + key
'ZBXD\x01\r\x00\x00\x00\x00\x00\x00\x00agent.version'

エージェントにデータ送信

作成したデータは TCP でエージェントに送信。エージェントのポートは 10050

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip. posrt))
s.sendall(data)

エージェントからのレスポンスをパース

受信したデータをパースする。送信時に pack した時と同じ要領で unpack すればよい。
ヘッダー部は header(4) + version(1) + data length(8) の 13 バイト。

>>> response = 'ZBXD\x01\x06\x00\x00\x00\x00\x00\x00\x001.8.14'
>>> struct.unpack('<4sBQ', response[:13])
('ZBXD', 1, 6L)  # (Header, Version, Data Length)
>>> (data, ) = struct.unpack('<6s', response[13:13+6])
>>> data
'1.8.14'
>>> len(data)
6

一連の処理をまとめる

実行例

$ python zabbix_get.py --help
usage: PROG [-h] [--host HOST] [--port PORT] [--key KEY]

optional arguments:
  -h, --help   show this help message and exit
  --host HOST  Specify host name or IP address of a host
  --port PORT  Specify port number of agent running on the host. Default is
               10050
  --key KEY    Specify key of item to retrieve value for
$ python zabbix_get.py --host 192.168.10.20 --port 10050 --key vfs.fs.size[/,pfree]
36.600020
$ python zabbix_get.py --host 192.168.10.20 --port 10050 --key agent.version
1.8.14
$ python zabbix_get.py --host localhost --key invalid.key
ZBX_NOTSUPPORTED

MEMO

ということで、期待通りに動いてくれた。

サーバーサイドを実装する場合も、パケットの基本的な処理は同じ。
なお、アクティブ監視の場合、ペイロード部のデータは JSON 形式。

Advertisements
Tagged with: ,
Posted in middleware

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
%d bloggers like this: