1 ローダブルモジュール
概要
ロード可能モジュールは、Zabbixの機能を拡張するための、パフォーマンスを重視した選択肢を提供します。
Zabbixの機能は、たとえば user parameters、external checks、および system.run Zabbixエージェントのアイテムなど、さまざまな方法で拡張できます。 これらは非常に有効に機能しますが、大きな欠点が1つあります。つまり、fork() です。 Zabbixはユーザーメトリクスを処理するたびに新しいプロセスをforkする必要があり、これはパフォーマンスの観点から好ましくありません。 通常は大きな問題ではありませんが、組み込みシステムの監視、大量の監視パラメータの利用、または複雑なロジックや長い起動時間を持つ重いスクリプトを使用する場合には、深刻な問題になる可能性があります。
ロード可能モジュールのサポートにより、パフォーマンスを損なうことなく、Zabbixエージェント、サーバー、プロキシを拡張する方法が提供されます。
ロード可能モジュールは基本的に、Zabbixデーモンによって使用され、起動時に読み込まれる共有ライブラリです。 ライブラリには特定の関数が含まれている必要があり、それによってZabbixプロセスは、そのファイルが実際に読み込み可能で利用可能なモジュールであることを検出できます。
ロード可能モジュールには多くの利点があります。 優れたパフォーマンスと任意のロジックを実装できる能力は非常に重要ですが、おそらく最も重要な利点は、Zabbixモジュールを開発、利用、共有できることです。 これにより、問題のない保守に貢献し、新しい機能をより容易に、かつZabbixコアコードベースとは独立して提供するのに役立ちます。
モジュールのライセンスおよびバイナリ形式での配布は、AGPL-3.0ライセンスによって規定されます(モジュールは実行時にZabbixとリンクし、Zabbixヘッダを使用します。Zabbix 7.0以降、Zabbixコード全体はAGPL-3.0ライセンスの下で提供されています)。 Zabbixはバイナリ互換性を保証しません。
モジュールAPIの安定性は、1つのZabbix LTS(Long Term Support)releaseサイクルの間は保証されます。 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 server が使用するコールバック関数を返す必要があります。
コールバック関数は 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")、flags は CF_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サーバーの履歴同期プロセスによって使用されます。
履歴エクスポートモジュールで内部エラーが発生した場合は、復旧するまで監視全体をブロックするのではなく、データを破棄してZabbixサーバーが動作を継続できるようにモジュールを実装することを推奨します。
モジュールのビルド
現在、モジュールはZabbixのソースツリー内でビルドすることを想定しています。これは、モジュールAPIがZabbixのヘッダーで定義されている一部のデータ構造に依存しているためです。
ロード可能なモジュールにとって最も重要なヘッダーは include/module.h で、これらのデータ構造を定義しています。 include/module.h が正しく動作するために必要なその他のシステムヘッダーは stdlib.h と stdint.h です。
この情報を踏まえると、モジュールをビルドする準備はすべて整っています。 モジュールには stdlib.h、stdint.h、module.h をインクルードする必要があり、ビルドスクリプトではこれらのファイルがインクルードパスに含まれていることを確認する必要があります。 詳細については、以下のサンプル「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.so、apache.so、kernel.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() 関数を提供している場合、履歴のエクスポートは自動的に有効になります。
ダミーモジュール
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"
/* the variable keeps timeout setting for item processing */
static int item_timeout = 0;
/* module SHOULD define internal functions as static and use a naming pattern different from Zabbix internal */
/* symbols (zbx_*) and loadable module API functions (zbx_module_*) to avoid conflicts */
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);
/* there is no strict validation of parameters and types for simplicity sake */
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)
{
/* initialization for 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++)
{
/* do something with 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++)
{
/* do something with 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++)
{
/* do something with 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++)
{
/* do something with 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++)
{
/* do something with 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 からモジュール関連の設定パラメータを読み取る必要があることがあります。
現在、これはサポートされていません。
モジュールで何らかの設定パラメータを使用する必要がある場合は、モジュール固有の設定ファイルの解析を実装する必要があります。