Zabbixサーバーまたはプロキシへのデータ送信

zabbix_utilsを使用すると、Zabbix senderと同様に、Zabbixサーバーまたはプロキシのトラッパーアイテムにアイテムの値を送信できます。

単一の値、複数の値、さらには複数のZabbixクラスタを対象に送信することも可能です。

データは同期モードまたは非同期モードで送信できます:

  • 同期モードでは、Pythonスクリプトは値を送信し、応答を待ってから処理を続行します。これは、シンプルで順次的かつ予測可能な操作に適しています。
  • 非同期モードでは、スクリプトは各応答を待たずに値を送信し、他の操作を並行して進めることができます。これは、遅いリクエストや大量のデータバッチに対してより効率的です。

このページの例は同期モードに焦点を当てていますが、非同期モードも同様のパターンに従います。 追加の例はGitHubリポジトリにもあります。

インポート

zabbix_utilsを使用してアイテム値を送信するには、スクリプトでSenderクラスをインポートします:

from zabbix_utils import Sender

複数の値を送信する場合は、ItemValueクラスもインポートできます:

from zabbix_utils import Sender, ItemValue

単一の値を送信する

アイテムの値を送信するには:

  1. Senderインスタンスを作成し、ZabbixサーバーまたはプロキシのIPアドレスとポートを指定します。
  2. Senderインスタンスでsend_value()メソッドを次の形式で呼び出します:
sender_instance.send_value('host', 'item.key', 'value', optional_timestamp, optional_nanoseconds)

例えば、Linux serverホストのservice.statusトラッパーアイテムに1を送信するには:

sender = Sender(server='127.0.0.1', port=10051)
response = sender.send_value('Linux server', 'service.status', 1)
デフォルト以外のIPの使用

スクリプトを実行しているサーバーに複数のIPアドレスがある場合、Zabbixサーバーまたはプロキシに値を送信する際にSenderが使用するsource_ipを指定できます。

sender = Sender(
    server='127.0.0.1',
    port=10051,
    source_ip='10.10.7.1'
)
タイムアウトの使用

Senderの応答timeoutを設定することで、スクリプトがZabbixサーバーまたはプロキシからの応答を待つ最大時間を制御できます。

sender = Sender(
    server='127.0.0.1',
    port=10051,
    timeout=30
)
エージェントの設定ファイルを使用する

zabbix_utilsにローカルのZabbixエージェントまたはエージェント2の設定ファイルからServerまたはServerActiveパラメータを読み込ませることができます。 この場合、Senderインスタンスを作成する際に接続パラメータを指定する必要はありません。

sender = Sender(
    use_config=True,
    config_path='/etc/zabbix/zabbix_agent2.conf'
)

ServerActiveに複数のサーバーインスタンスを持つ1つ以上のZabbixクラスタが含まれている場合、Senderは各クラスタの最初に利用可能なサーバーにデータを送信します。 ServerActiveが設定されていない場合は、Serverのアドレスとデフォルトポート(10051)が使用されます。

暗号化の使用

Senderには組み込みの暗号化サポートはありませんが、サードパーティのライブラリを使用してラッパーを作成することで提供できます。

def psk_wrapper(sock, tls):
    # ...
    # ソケットのTLS PSKラッパーの実装
    # ...

sender = Sender(
    server='127.0.0.1',
    port=10051,
    socket_wrapper=psk_wrapper
)
単一値のレスポンス

Zabbixサーバーまたはプロキシから返されたレスポンスはライブラリによって処理され、TrapperResponseオブジェクトとして返されます:

print(response)
# {"processed": 1, "failed": 0, "total": 1, "time": "0.000123", "chunk": 1}

print(response.processed)
# 1

print(response.failed)
# 0

print(response.total)
# 1
非同期モード

非同期モードでは、PythonスクリプトがZabbixサーバーやプロキシからの応答を待たずに値を送信できます。 多くの値を送信する必要がある場合や、一部の値の送信に時間がかかる場合に、スクリプトをより効率的に実行できます。

非同期モードを使用する場合、同期モードと比較していくつか重要な違いがあります。

  • Pythonのasyncioモジュールをインポートします(事前に必要な依存関係をインストールする必要があります)。
  • Senderの代わりにAsyncSenderをインポートします。
  • コードはasync関数内に記述します。
  • send_value()メソッドを呼び出す際はawaitを使用します。

例えば、非同期モードで単一の値を送信するには:

# 1. 非同期モード用にasyncioと、zabbix_utilsからAsyncSenderをインポート:
import asyncio
from zabbix_utils import AsyncSender

# 2. すべてのデータ送信操作(awaitが必要)を実行するメインのasync関数を定義:
async def main():
    sender = AsyncSender(server='127.0.0.1', port=10051)
    response = await sender.send_value('Linux server', 'service.status', 1)

    # 3. Zabbixサーバーまたはプロキシから返された応答を出力:
    print(response)

# 4. asyncioのイベントループを使ってasync main()関数を実行:
asyncio.run(main())

複数の値を送信する

複数の値を送信するには:

  1. send_value()メソッドと同じフォーマットで、ItemValueオブジェクトの配列を用意します。
  2. ZabbixサーバーまたはプロキシのIPアドレスとポートを指定して、Senderインスタンスを作成します。
  3. Senderインスタンスでsend_value()の代わりにsend()メソッドを呼び出し、送信する値のオブジェクト配列を指定します。

例えば、異なるホストに5つの値を送信するには:

items = [
    ItemValue('server-de', 'service.status', 'up', 1770887205, 100),
    ItemValue('server-fr', 'service.status', 'up', 1770887205, 100),
    ItemValue('server-uk', 'service.status', 'up', 1770887205, 100),
    ItemValue('server-nl', 'service.status', 'up', 1770887205, 100),
    ItemValue('server-pl', 'service.status', 'up', 1770887205, 100),
]

sender = Sender(server='127.0.0.1', port=10051)
response = sender.send(items)
カスタムチャンクサイズの使用

1つのリクエストでトラッパーアイテムが受け入れられる値より多くの値を送信する必要がある場合は、それらをチャンクに分割できます。

デフォルトでは、チャンクサイズは250値です。 Senderインスタンスを作成する際にchunk_sizeパラメータを設定することで、これを変更できます。

たとえば、5つの値を3つのチャンク(2-2-1)で送信するには、chunk_sizeパラメータを2に設定します。

items = [
    ItemValue('server-de', 'service.status', 'up'),
    ItemValue('server-fr', 'service.status', 'up'),
    ItemValue('server-uk', 'service.status', 'up'),
    ItemValue('server-nl', 'service.status', 'up'),
    ItemValue('server-pl', 'service.status', 'up'),
]

sender = Sender(server='127.0.0.1', port=10051, chunk_size=2)
response = sender.send(items)
複数のZabbixクラスタに値を送信する

複数のZabbixクラスタに値を送信するには:

  1. Zabbixクラスタの配列を用意します。クラスタに複数のノードがある場合、値は各クラスタの最初の利用可能なノードに送信されます。
  2. Zabbixクラスタの配列を指定してSenderを作成します。
  3. send_value()メソッドと同じ形式で、Senderインスタンスのsend_value()メソッドを呼び出します。

例えば、各クラスタの最初の利用可能なノードに値を送信するには:

zabbix_clusters = [
    ['zabbix.cluster1.node1', 'zabbix.cluster1.node2:10051'],
    ['zabbix.cluster2.node1:10051', 'zabbix.cluster2.node2', 'zabbix.cluster2.node3']
]

sender = Sender(clusters=zabbix_clusters)
response = sender.send_value('Linux server', 'service.status', 1)
複数値のレスポンス

デフォルトでは、Senderはすべてのホストまたはクラスタに対して値を送信した集計結果を返します。

print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}

より詳細な情報が必要な場合は、response.details属性を使用して、各クラスタおよび各チャンクの結果を確認できます。

print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}

if response.failed == 0:
    print(f"Value sent successfully in {response.time}")
else:
    print(response.details)
    # {
    #     127.0.0.1:10051: [
    #         {
    #             "processed": 1,
    #             "failed": 0,
    #             "total": 1,
    #             "time": "0.000051",
    #             "chunk": 1
    #         }
    #     ],
    #     zabbix.example.local:10051: [
    #         {
    #             "processed": 1,
    #             "failed": 0,
    #             "total": 1,
    #             "time": "0.000057",
    #             "chunk": 1
    #         }
    #     ]
    # }

    for node, chunks in response.details.items():
        for resp in chunks:
            print(f"Processed {resp.processed} of {resp.total} at {node.address}:{node.port}")
            # Processed 1 of 1 at 127.0.0.1:10051
            # Processed 1 of 1 at zabbix.example.local:10051