Zabbixサーバーまたはプロキシにデータを送信する

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

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

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

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

このページの例は同期モードに重点を置いていますが、非同期モード も同様のパターンに従います。 追加の例は、GitHubリポジトリの zabbix_utils で利用できます。

インポート

アイテムの値を送信するために 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 serverまたはプロキシに値を送信する際に、Sender が使用する source_ip を指定できます。

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

Sender に応答 timeout を設定して、スクリプトが Zabbix server または proxy からの応答をあきらめるまでに、どれくらい待機するかを制御できます。

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

zabbix_utils に、ローカルの Zabbix エージェントまたは agent 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. ItemValue オブジェクトの配列を準備します。各オブジェクトは、send_value() メソッドと同じ形式を使用します。
  2. Sender インスタンスを作成し、ZabbixサーバーまたはプロキシのIPアドレスとポートを指定します。
  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"{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"{node.address}:{node.port}{resp.total} 件中 {resp.processed} 件を処理しました")
            # 127.0.0.1:10051 で 1 件中 1 件を処理しました
            # zabbix.example.local:10051 で 1 件中 1 件を処理しました