1 ローダブルモジュール

概要

ロード可能なモジュールは、Zabbixの機能を拡張するためのパフォーマンス重視のオプションを提供します。

Zabbixの機能は、ユーザーパラメータ外部チェックsystem.run Zabbixエージェントアイテムなど、さまざまな方法で拡張できます。 これらは非常にうまく機能しますが、主な欠点はfork()です。 Zabbixはユーザーメトリックを処理するたびに新しいプロセスをforkする必要があり、これはパフォーマンスにとって良くありません。 通常は大きな問題ではありませんが、組み込みシステムの監視や、多数の監視パラメータ、複雑なロジックや起動時間の長い重いスクリプトを使用する場合には深刻な問題となる可能性があります。

ロード可能なモジュールのサポートにより、パフォーマンスを犠牲にすることなく、Zabbixエージェント、サーバー、プロキシを拡張する方法が提供されます。

ロード可能なモジュールは基本的にZabbixデーモンによって使用され、起動時にロードされる共有ライブラリです。 このライブラリには特定の関数が含まれている必要があり、Zabbixプロセスがそのファイルが実際にロードして動作できるモジュールであることを検出できるようになっています。

ロード可能なモジュールには多くの利点があります。 優れたパフォーマンスとあらゆるロジックを実装できる能力は非常に重要ですが、おそらく最も重要な利点は、Zabbixモジュールを開発、使用、共有できることです。 これにより、トラブルのないメンテナンスが可能になり、Zabbixのコアコードベースとは独立して新しい機能をより簡単に提供できるようになります。

モジュールのライセンスおよびバイナリ形式での配布はAGPL-3.0ライセンスによって管理されます(モジュールは実行時にZabbixとリンクし、Zabbixヘッダーを使用します。Zabbixの全コードはZabbix 7.0以降AGPL-3.0ライセンスでライセンスされています)。 バイナリ互換性はZabbixによって保証されません。

モジュールAPIの安定性は、1つのZabbix LTS(長期サポート)リリースサイクルの間保証されます。 Zabbix APIの安定性は保証されません(技術的にはモジュールからZabbix内部関数を呼び出すことは可能ですが、そのようなモジュールが動作する保証はありません)。

モジュールAPI

共有ライブラリがZabbixモジュールとして扱われるためには、いくつかの関数を実装しエクスポートする必要があります。 現在、ZabbixモジュールAPIには6つの関数があり、そのうち1つだけが必須で、他の5つはオプションです。

必須インターフェース

必須の関数は zbx_module_api_version() のみです:

int zbx_module_api_version(void);

この関数は、このモジュールで実装されている API バージョンを返す必要があります。また、モジュールを読み込むには、このバージョンが Zabbix でサポートされているモジュール API バージョンと一致していなければなりません。 Zabbix がサポートするモジュール API のバージョンは ZBX_MODULE_API_VERSION です。 したがって、この関数はこの定数を返す必要があります。 この目的で使用されていた旧定数 ZBX_MODULE_API_VERSION_ONE は、ソース互換性を維持するために ZBX_MODULE_API_VERSION と等しい値として定義されていますが、使用は推奨されません。

オプションのインターフェース

オプションの関数は zbx_module_init(), zbx_module_item_list(), zbx_module_item_timeout(), zbx_module_history_write_cbs() および zbx_module_uninit() です。

int zbx_module_init(void);

この関数は、モジュールに必要な初期化処理(ある場合)を実行する必要があります。
成功した場合は ZBX_MODULE_OK を返します。
それ以外の場合は ZBX_MODULE_FAIL を返します。
後者の場合、Zabbix は起動しません。

ZBX_METRIC  *zbx_module_item_list(void);

この関数は、モジュールがサポートするアイテムの一覧を返す必要があります。
各アイテムは ZBX_METRIC 構造体で定義されます。詳細は以下のセクションを参照してください。
一覧の終端は、key フィールドが NULL の ZBX_METRIC 構造体です。

void    zbx_module_item_timeout(int timeout);

モジュールが zbx_module_item_list() を公開している場合、この関数は、モジュールによって実装されたアイテムチェックが従うべき Zabbix 設定ファイル内のタイムアウト設定を Zabbix が指定するために使用されます。
ここで、timeout パラメータは秒単位です。

ZBX_HISTORY_WRITE_CBS   zbx_module_history_write_cbs(void);

この関数は、Zabbix サーバーがさまざまなデータ型の履歴をエクスポートするために使用するコールバック関数を返す必要があります。
コールバック関数は ZBX_HISTORY_WRITE_CBS 構造体のフィールドとして提供され、モジュールが特定の型の履歴に関心がない場合、そのフィールドは NULL にできます。

int zbx_module_uninit(void);

この関数は、割り当て済みリソースの解放、ファイルディスクリプタのクローズなど、必要な終了処理(ある場合)を実行する必要があります。

すべての関数は、モジュールがロードされたときに Zabbix の起動時に 1 回呼び出されます。ただし、zbx_module_uninit() は例外で、モジュールがアンロードされたときに Zabbix の終了時に 1 回呼び出されます。

アイテムの定義

各アイテムは ZBX_METRIC 構造体で定義されます。

typedef struct
{
    char        *key;
    unsigned    flags;
    int     (*function)();
    char        *test_param;
}
ZBX_METRIC;

ここで、key はアイテムキーです(例: "dummy.random")、flagsCF_HAVEPARAMS または 0 のいずれかです(アイテムがパラメータを受け付けるかどうかによります)、function はアイテムを実装する C 関数です(例: zbx_module_dummy_random)、test_param は Zabbix エージェントが -p フラグ付きで起動されたときに使用されるパラメータ一覧です(例: "1,1000"、NULL も可)。 定義例は次のようになります。

static ZBX_METRIC keys[] =
{
    { "dummy.random", CF_HAVEPARAMS, zbx_module_dummy_random, "1,1000" },
    { NULL }
}

アイテムを実装する各関数は 2 つのポインターパラメータを受け取る必要があります。1 つ目は AGENT_REQUEST 型、2 つ目は AGENT_RESULT 型です。

int zbx_module_dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result)
{
    ...

    SET_UI64_RESULT(result, from + rand() % (to - from + 1));

    return SYSINFO_RET_OK;
}

これらの関数は、アイテム値の取得に成功した場合は SYSINFO_RET_OK を返す必要があります。 それ以外の場合は SYSINFO_RET_FAIL を返します。 AGENT_REQUEST から情報を取得する方法と AGENT_RESULT に情報を設定する方法については、以下の "dummy" モジュールの例を参照してください。

履歴エクスポートコールバックの提供

モジュールによる履歴のエクスポートは、Zabbixプロキシではサポートされなくなりました。

モジュールは、履歴データを種類別にエクスポートする関数を指定できます。種類は、Numeric (float)、Numeric (unsigned)、Character、Text、Log です。

typedef struct
{
    void    (*history_float_cb)(const ZBX_HISTORY_FLOAT *history, int history_num);
    void    (*history_integer_cb)(const ZBX_HISTORY_INTEGER *history, int history_num);
    void    (*history_string_cb)(const ZBX_HISTORY_STRING *history, int history_num);
    void    (*history_text_cb)(const ZBX_HISTORY_TEXT *history, int history_num);
    void    (*history_log_cb)(const ZBX_HISTORY_LOG *history, int history_num);
}
ZBX_HISTORY_WRITE_CBS;

それぞれの関数は、引数として history_num 個の要素を持つ history 配列を受け取る必要があります。
エクスポートする履歴データ型に応じて、history はそれぞれ以下の構造体の配列になります。

typedef struct
{
    zbx_uint64_t    itemid;
    int     clock;
    int     ns;
    double      value;
}
ZBX_HISTORY_FLOAT;

typedef struct
{
    zbx_uint64_t    itemid;
    int     clock;
    int     ns;
    zbx_uint64_t    value;
}
ZBX_HISTORY_INTEGER;

typedef struct
{
    zbx_uint64_t    itemid;
    int     clock;
    int     ns;
    const char  *value;
}
ZBX_HISTORY_STRING;

typedef struct
{
    zbx_uint64_t    itemid;
    int     clock;
    int     ns;
    const char  *value;
}
ZBX_HISTORY_TEXT;

typedef struct
{
    zbx_uint64_t    itemid;
    int     clock;
    int     ns;
    const char  *value;
    const char  *source;
    int     timestamp;
    int     logeventid;
    int     severity;
}
ZBX_HISTORY_LOG;

コールバックは、Zabbixサーバーの履歴同期プロセスによって、履歴同期処理の最後に使用されます。これは、データがZabbixデータベースに書き込まれ、value cache に保存された後です。

履歴エクスポートモジュールで内部エラーが発生した場合は、復旧するまで監視全体を停止させるのではなく、データを破棄してZabbixサーバーの実行を継続できるような実装にすることを推奨します。

モジュールのビルド

モジュールは現在、Zabbixのソースツリー内でビルドすることを想定しています。これは、モジュールAPIがZabbixのヘッダーで定義されているいくつかのデータ構造に依存しているためです。

ロード可能なモジュールにとって最も重要なヘッダーは include/module.h であり、ここでこれらのデータ構造が定義されています。
include/module.h を正しく動作させるために必要なその他のシステムヘッダーは stdlib.hstdint.h です。

この情報を踏まえると、モジュールをビルドする準備は整っています。
モジュールには stdlib.hstdint.h、および module.h を含める必要があり、ビルドスクリプトではこれらのファイルが include パスに含まれていることを確認する必要があります。
詳細は、以下の「dummy」モジュールの例を参照してください。

もう1つ便利なヘッダーは include/zbxcommon.h で、ここには zabbix_log() 関数が定義されています。この関数は、ログ記録やデバッグの目的で使用できます。

設定パラメータ

Zabbix エージェント、サーバー、およびプロキシは、モジュールを扱うために 2 つのパラメータをサポートしています。

  • LoadModulePath - 読み込み可能なモジュールの配置先へのフルパス
  • LoadModule - 起動時に読み込むモジュール

モジュールは LoadModulePath で指定されたディレクトリに配置する必要があります。あるいは、パスをモジュール名の前に付ける必要があります。 先頭のパスが絶対パス(/ で始まる)である場合、LoadModulePath は無視されます。 複数の LoadModule パラメータを含めることができます。

たとえば、Zabbix エージェントを拡張するには、次のパラメータを追加できます。

LoadModulePath=/usr/local/lib/zabbix/agent/
LoadModule=mariadb.so
LoadModule=apache.so
LoadModule=kernel.so
LoadModule=/usr/local/lib/zabbix/dummy.so

エージェントの起動時には、mariadb.soapache.sokernel.so モジュールを /usr/local/lib/zabbix/agent ディレクトリから読み込み、dummy.so/usr/local/lib/zabbix から読み込まれます。 モジュールが存在しない場合、権限が不正な場合、または共有ライブラリが Zabbix モジュールではない場合、エージェントは起動に失敗します。

Webインターフェースの設定

ロード可能なモジュールは、Zabbix エージェント、サーバー、およびプロキシでサポートされています。
そのため、Zabbix Webインターフェースでのアイテムタイプは、モジュールがどこにロードされるかによって異なります。
モジュールがエージェントにロードされる場合、アイテムタイプは "Zabbix agent" または "Zabbix agent (active)" である必要があります。
モジュールがサーバーまたはプロキシにロードされる場合、アイテムタイプは "Simple check" である必要があります。

Zabbix モジュールによる履歴エクスポートには、Webインターフェースの設定は不要です。
モジュールがサーバーによって正常にロードされ、少なくとも1つの非 NULL のコールバック関数を返す zbx_module_history_write_cbs() 関数を提供している場合、履歴エクスポートは自動的に有効になります。

Dummyモジュール

Zabbixには、C言語で書かれたサンプルモジュールが含まれています。
このモジュールは src/modules/dummy にあります:

alex@alex:~trunk/src/modules/dummy$ ls -l
-rw-rw-r-- 1 alex alex 9019 Apr 24 17:54 dummy.c
-rw-rw-r-- 1 alex alex   67 Apr 24 17:54 Makefile
-rw-rw-r-- 1 alex alex  245 Apr 24 17:54 README

このモジュールは十分にドキュメント化されており、独自のモジュールを作成する際のテンプレートとして使用できます。

上記の説明に従って Zabbix ソースツリーのルートで ./configure を実行した後、dummy.so をビルドするには make を実行するだけです。

/*
** Zabbix
** Copyright (C) 2001-2020 Zabbix SIA
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
**/

#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdint.h>

#include "module.h"

/* 変数はアイテム処理のタイムアウト設定を保持します */
static int  item_timeout = 0;

/* モジュールは内部関数を static として定義し、Zabbix の内部シンボル */
/* (zbx_*) およびロード可能モジュール API 関数 (zbx_module_*) とは異なる命名規則を使用して、競合を避ける必要があります */
static int  dummy_ping(AGENT_REQUEST *request, AGENT_RESULT *result);
static int  dummy_echo(AGENT_REQUEST *request, AGENT_RESULT *result);
static int  dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result);

static ZBX_METRIC keys[] =
/*  KEY         FLAG        FUNCTION    TEST PARAMETERS */
{
    {"dummy.ping",      0,      dummy_ping, NULL},
    {"dummy.echo",      CF_HAVEPARAMS,  dummy_echo, "a message"},
    {"dummy.random",    CF_HAVEPARAMS,  dummy_random,   "1,1000"},
    {NULL}
};

/******************************************************************************
 *                                                                            *
 * Function: zbx_module_api_version                                           *
 *                                                                            *
 * Purpose: returns version number of the module interface                    *
 *                                                                            *
 * Return value: ZBX_MODULE_API_VERSION - version of module.h module is       *
 *               compiled with, in order to load module successfully Zabbix   *
 *               MUST be compiled with the same version of this header file   *
 *                                                                            *
 ******************************************************************************/
int zbx_module_api_version(void)
{
    return ZBX_MODULE_API_VERSION;
}

/******************************************************************************
 *                                                                            *
 * Function: zbx_module_item_timeout                                          *
 *                                                                            *
 * Purpose: set timeout value for processing of items                         *
 *                                                                            *
 * Parameters: timeout - timeout in seconds, 0 - no timeout set               *
 *                                                                            *
 ******************************************************************************/
void    zbx_module_item_timeout(int timeout)
{
    item_timeout = timeout;
}

/******************************************************************************
 *                                                                            *
 * Function: zbx_module_item_list                                             *
 *                                                                            *
 * Purpose: returns list of item keys supported by the module                 *
 *                                                                            *
 * Return value: list of item keys                                            *
 *                                                                            *
 ******************************************************************************/
ZBX_METRIC  *zbx_module_item_list(void)
{
    return keys;
}

static int  dummy_ping(AGENT_REQUEST *request, AGENT_RESULT *result)
{
    SET_UI64_RESULT(result, 1);

    return SYSINFO_RET_OK;
}

static int  dummy_echo(AGENT_REQUEST *request, AGENT_RESULT *result)
{
    char    *param;

    if (1 != request->nparam)
    {
        /* set optional error message */
        SET_MSG_RESULT(result, strdup("Invalid number of parameters."));
        return SYSINFO_RET_FAIL;
    }

    param = get_rparam(request, 0);

    SET_STR_RESULT(result, strdup(param));

    return SYSINFO_RET_OK;
}

/******************************************************************************
 *                                                                            *
 * Function: dummy_random                                                     *
 *                                                                            *
 * Purpose: a main entry point for processing of an item                      *
 *                                                                            *
 * Parameters: request - structure that contains item key and parameters      *
 *              request->key - item key without parameters                    *
 *              request->nparam - number of parameters                        *
 *              request->params[N-1] - pointers to item key parameters        *
 *              request->types[N-1] - item key parameters types:              *
 *                  REQUEST_PARAMETER_TYPE_UNDEFINED (key parameter is empty) *
 *                  REQUEST_PARAMETER_TYPE_ARRAY (array)                      *
 *                  REQUEST_PARAMETER_TYPE_STRING (quoted or unquoted string) *
 *                                                                            *
 *             result - structure that will contain result                    *
 *                                                                            *
 * Return value: SYSINFO_RET_FAIL - function failed, item will be marked      *
 *                                 as not supported by zabbix                 *
 *               SYSINFO_RET_OK - success                                     *
 *                                                                            *
 * Comment: get_rparam(request, N-1) can be used to get a pointer to the Nth  *
 *          parameter starting from 0 (first parameter). Make sure it exists  *
 *          by checking value of request->nparam.                             *
 *          In the same manner get_rparam_type(request, N-1) can be used to   *
 *          get a parameter type.                                             *
 *                                                                            *
 ******************************************************************************/
static int  dummy_random(AGENT_REQUEST *request, AGENT_RESULT *result)
{
    char    *param1, *param2;
    int from, to;

    if (2 != request->nparam)
    {
        /* set optional error message */
        SET_MSG_RESULT(result, strdup("Invalid number of parameters."));
        return SYSINFO_RET_FAIL;
    }

    param1 = get_rparam(request, 0);
    param2 = get_rparam(request, 1);

    /* 簡潔さのため、パラメータと型の厳密な検証は行っていません */
    from = atoi(param1);
    to = atoi(param2);

    if (from > to)
    {
        SET_MSG_RESULT(result, strdup("Invalid range specified."));
        return SYSINFO_RET_FAIL;
    }

    SET_UI64_RESULT(result, from + rand() % (to - from + 1));

    return SYSINFO_RET_OK;
}

/******************************************************************************
 *                                                                            *
 * Function: zbx_module_init                                                  *
 *                                                                            *
 * Purpose: the function is called on agent startup                           *
 *          It should be used to call any initialization routines             *
 *                                                                            *
 * Return value: ZBX_MODULE_OK - success                                      *
 *               ZBX_MODULE_FAIL - module initialization failed               *
 *                                                                            *
 * Comment: the module won't be loaded in case of ZBX_MODULE_FAIL             *
 *                                                                            *
 ******************************************************************************/
int zbx_module_init(void)
{
    /* dummy.random の初期化 */
    srand(time(NULL));

    return ZBX_MODULE_OK;
}

/******************************************************************************
 *                                                                            *
 * Function: zbx_module_uninit                                                *
 *                                                                            *
 * Purpose: the function is called on agent shutdown                          *
 *          It should be used to cleanup used resources if there are any      *
 *                                                                            *
 * Return value: ZBX_MODULE_OK - success                                      *
 *               ZBX_MODULE_FAIL - function failed                            *
 *                                                                            *
 ******************************************************************************/
int zbx_module_uninit(void)
{
    return ZBX_MODULE_OK;
}

/******************************************************************************
 *                                                                            *
 * Functions: dummy_history_float_cb                                          *
 *            dummy_history_integer_cb                                        *
 *            dummy_history_string_cb                                         *
 *            dummy_history_text_cb                                           *
 *            dummy_history_log_cb                                            *
 *                                                                            *
 * Purpose: callback functions for storing historical data of types float,    *
 *          integer, string, text and log respectively in external storage    *
 *                                                                            *
 * Parameters: history     - array of historical data                         *
 *             history_num - number of elements in history array              *
 *                                                                            *
 ******************************************************************************/
static void dummy_history_float_cb(const ZBX_HISTORY_FLOAT *history, int history_num)
{
    int i;

    for (i = 0; i < history_num; i++)
    {
        /* history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... を使って何か処理する */
    }
}

static void dummy_history_integer_cb(const ZBX_HISTORY_INTEGER *history, int history_num)
{
    int i;

    for (i = 0; i < history_num; i++)
    {
        /* history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... を使って何か処理する */
    }
}

static void dummy_history_string_cb(const ZBX_HISTORY_STRING *history, int history_num)
{
    int i;

    for (i = 0; i < history_num; i++)
    {
        /* history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... を使って何か処理する */
    }
}

static void dummy_history_text_cb(const ZBX_HISTORY_TEXT *history, int history_num)
{
    int i;

    for (i = 0; i < history_num; i++)
    {
        /* history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... を使って何か処理する */
    }
}

static void dummy_history_log_cb(const ZBX_HISTORY_LOG *history, int history_num)
{
    int i;

    for (i = 0; i < history_num; i++)
    {
        /* history[i].itemid, history[i].clock, history[i].ns, history[i].value, ... を使って何か処理する */
    }
}

/******************************************************************************
 *                                                                            *
 * Function: zbx_module_history_write_cbs                                     *
 *                                                                            *
 * Purpose: returns a set of module functions Zabbix will call to export      *
 *          different types of historical data                                *
 *                                                                            *
 * Return value: structure with callback function pointers (can be NULL if    *
 *               module is not interested in data of certain types)           *
 *                                                                            *
 ******************************************************************************/
ZBX_HISTORY_WRITE_CBS   zbx_module_history_write_cbs(void)
{
    static ZBX_HISTORY_WRITE_CBS    dummy_callbacks =
    {
        dummy_history_float_cb,
        dummy_history_integer_cb,
        dummy_history_string_cb,
        dummy_history_text_cb,
        dummy_history_log_cb,
    };

    return dummy_callbacks;
}

このモジュールは 3 つの新しいアイテムを公開します:

  • dummy.ping - 常に '1' を返します
  • dummy.echo[param1] - 最初のパラメータをそのまま返します。たとえば、dummy.echo[ABC] は ABC を返します
  • dummy.random[param1, param2] - param1-param2 の範囲内のランダムな数値を返します。たとえば、dummy.random[1,1000000]

制限事項

ロード可能なモジュールのサポートは Unix プラットフォームでのみ実装されています。 つまり、Windows エージェントでは動作しません。

場合によっては、モジュールが zabbix_agentd.conf からモジュール関連の設定パラメータを読み取る必要があることがあります。 これは現在サポートされていません。 モジュールでいくつかの設定パラメータを使用する必要がある場合は、モジュール固有の設定ファイルの解析を実装する必要があるでしょう。