2022 Zabbix中国峰会
2022 Zabbix中国峰会

1 可加载模块

概览

可加载模块为扩展Zabbix的功能,提供了一个侧重性能的选择。

您可以通过多种方式 extend扩展 Zabbix的功能, 例如,使用 user parameters用户参数,external checks外部检查,and system.run[] Zabbix agent items监控项. 这些方法效果很好,但存在一个重要缺点,即 fork()。Zabbix 每次处理用户指标时都必须分叉一个新进程,这对性能不利。通常这不是什么大问题,但在监控嵌入式系统、拥有大量监控参数或逻辑复杂或启动时间长的繁重脚本时,这可能是一个严重的问题。

可加载模块的支持提供了在不牺牲性能的情况下扩展 Zabbix 代理、服务器和代理的方法。

可加载模块基本上是一个软件库,由Zabbix守护进程使用,并在启动时加载。该库应包含某些函数,以便 Zabbix 进程可以检测到该文件确实是它可以加载和使用的模块。

可加载模块有许多好处。出色的性能和实现任何逻辑的能力非常重要,但也许最重要的优势是开发、使用和共享 Zabbix 模块的能力。它有助于无故障维护,并有助于更轻松地独立于 Zabbix 核心代码库提供新功能。

模块许可和二进制形式的分发受 GPL 许可管辖(模块在运行时与 Zabbix 链接并使用 Zabbix 标头;目前整个 Zabbix 代码均在 GPL 许可下获得许可)。Zabbix 不保证二进制兼容性。

在一个 Zabbix LTS(长期支持)release发布版本周期内,模块 API 的稳定性得到保证。Zabbix API 的稳定性无法保证(从技术上讲,可以从模块调用 Zabbix 内部函数,但不能保证此类模块可以正常工作)。

模块 API

为了将共享库视作Zabbix模块,它应该实现并导出一些函数。目前,Zabbix 模块API 中由六个函数,其中一个是强制性的,另外五个是可选的。

强制必须接口

唯一的强制函数是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() and 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 配置文件中的超时设置,基于这个模块的监控项检查应遵守这个设置。这边,“timeout”参数以秒为单位。

ZBX_HISTORY_WRITE_CBS   zbx_module_history_write_cbs(void);

这个函数应当返回ZABBIX服务器将用于导出不同数据类型历史记录的回调函数。回调函数应以ZBX_HISTORY_WRITE_CBS结构的字段提供,如果模块对于某种类型的历史纪录不感兴趣,则字段可以为NULL 。

int zbx_module_uninit(void);

这个函数应当执行必要的反初始化(如果有的话),如释放分配的资源、关闭文件描述符等。

所有的函数会在ZABBIX启动的时候加载模块时,除了zbx_module_uninit()都将被调用一次。在卸载模块时,zbx_module_uninit()会被ZABBIX调用。

定义监控项

每个监控项都应当被定义在 ZBX_METRIC 结构中:

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

这里的key指的时监控项的key(例如:“ dummy.random”),flags可以是 CF_HAVEPARAMS 或 0 (取决于监控项是否接受参数),function 是实现该监控项的 C函数(例如:"zbx_module_dummy_random"),最后 test_param 是使用'' -P '' 标志启动 ZABBIX Agent 时使用的参数里列表(例如:"1,1000",可以是 NULL)。下面是一个具体示例:

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

每个实现一个监控项的函数应该接受俩哥哥指针参数函数,第一个是一种AGENT_REQUEST类型,第二个是一种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 4.0.0开始,不再支持通过Zabbix Proxy模块输出历史记录

模块可以按来行指定输出历史数据的函数:数字(浮点)、数字(无符号)、字符串、文本和日志:

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 Server 的历史记录同步进程完成历史记录同步操作,数据被写入Zabbix数据库并将值保存在值缓存中后执行。

如果历史记录导出模块出现内部错误,建议以这样的方式编写模块,使其不会阻止整个监控直到恢复,而是丢弃数据并允许 Zabbix server继续运行。

构建模块

目前,模块应当再ZABBIX源代码树中构建,因为模块API依赖于一些ZABBIX头文件中定义的一些数据结构。

对可加载模块来说,最重要的头是include/module.h,它定义了这些住居结构。另一个很有用的头文件include/sysinc.h ,它的执行会包含必要的系统头文件,这有助于include/module.h 的正常工作。

为了include/module.h 和 include/sysinc.h被导入,应在ZABBIX源代码树的根目录下执行./configure命令。这将创建 include/config.h文件,其中包含了 include/sysinc.h依赖。(如果你获得的ZABBIX源代码来自子版本存储库,则 ./configure脚本尚不存在,应首先运行 ./bootstrap.sh 脚本来生成它。)

记住这些信息,一切都准备好了去构建模块。该模块应包含 sysinc.hmodule.h,构建脚本应确保这两个文件包含于路径中。有关详细信息,参见下文“dummy”模块。

其它有用的头文件include/log.h,它定义了zabbix_log()函数,可用于记录和调试目的。

配置参数

ZABBIX Agent, Server和Proxy支持两个参数来处理模块:

  • LoadModulePath – 可加载模块所在的完整路径
  • LoadModule – 启动时加载的模块。这些模块必须位于 LoadModulePath制定的目录中。允许包含多个 LoadModule 参数

例如:要扩展ZABBIX Agent 我们可以添加以下参数:

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

在启动Agent时,它将从/usr/local/lib/zabbix/agent/目录加载mariadb.so,apache.so, kernel.so 和/usr/local/lib/zabbix目录下的dummy.so模块。如果发生缺少模块、权限错误或该共享库文件不是ZABBIX模块,那么Agent的启动将失败。

前端配置

Zabbix Agent、Server和Proxy支持可加载模块。因此Zabbix前端中的监控项类型依据模块在哪里被加载。如果模块在Agent端被加载那么监控项类型应当设置为“Agent检查”或“Agent检查(主动)”。如果在Server端或Proxy端被加载,那么响应的类型应当为“简单检查”。

通过Zabbix模块历史记录输出不需要进行前端配置。如果模块成功加载并提供zbx_module_history_write_cbs()函数且该函数应至少返回一个非NULL回调方法,则将自动启动历史记录输出。

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命令后,至于要运行 make 即可构建 dummy.so.

/*
       ** Zabbix
       ** Copyright (C) 2001-2016 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 "sysinc.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→timeout - processing should not take longer than     *
        *                                 this number of seconds                     *
        *              request→params[N-1] - pointers to item key parameters        *
        *                                                                            *
        *             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.                             *
        *                                                                            *
        ******************************************************************************/
       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 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;
       }

这个模块导出三个新的监控项类型:

  • dummy.ping - 总是返回 '1'
  • dummy.echo[param1] - 总是返回第一个参数,例如 dummy.echo[ABC] 将返回 '' ABC ''
  • dummy.random[param1, param2] - 返回param1与param2范围内的随机数,例如, dummy.random[1,1000000]

限制

仅对类Unix平台实现了可加载模块的支持。这意味着它不适用于Windows平台的Agent。

某些情况下,模块可能要从zabbix_agentd.conf读取与模块相关的配置参数。目前不支持这么操作。如果您需要模块使用某些配置参数,则应该实现特定与模块的配置文件解析。