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
  • RT @__apf__: How to write a research paper: a guide for software engineers & practitioners. docs.google.com/presentation/d… /cc @inwyrd 6 months ago
  • RT @HayatoChiba: 昔、自然と対話しながら数学に打ち込んだら何かを悟れるのではと思いたち、専門書1つだけ持ってパワースポットで名高い奈良の山奥に1週間籠ったことがある。しかし泊まった民宿にドカベンが全巻揃っていたため、水島新司と対話しただけで1週間過ぎた。 それ… 6 months ago
  • RT @googlecloud: Ever wonder what underwater fiber optic internet cables look like? Look no further than this deep dive w/ @NatAndLo: https… 6 months ago
  • @ijin UTC+01:00 な時間帯で生活しています、、、 1 year ago
  • RT @mattcutts: Google's world-class Site Reliability Engineering team wrote a new book: amazon.com/Site-Reliabili… It's about managing produc… 1 year ago
%d bloggers like this: