Esta página incluye contenido traducido automáticamente. Si detectas un error, selecciónalo y presiona Ctrl+Enter para informarlo a los editores.

1 Módulos cargables

Descripción general

Los módulos cargables ofrecen una opción orientada al rendimiento para ampliar la funcionalidad de Zabbix.

Puede ampliar la funcionalidad de Zabbix de muchas maneras, por ejemplo, con parámetros de usuario, comprobaciones externas y elementos del agent de Zabbix system.run. Estos funcionan muy bien, pero tienen un gran inconveniente, a saber, fork(). Zabbix tiene que bifurcar un nuevo proceso cada vez que maneja una métrica de usuario, lo cual no es bueno para el rendimiento. Normalmente no es un gran problema, sin embargo, podría ser un problema grave al monitorizar sistemas embebidos, tener un gran número de parámetros monitorizados o scripts pesados con lógica compleja o un largo tiempo de inicio.

La compatibilidad con módulos cargables ofrece formas de ampliar el agent, el server y el proxy de Zabbix sin sacrificar el rendimiento.

Un módulo cargable es básicamente una biblioteca compartida utilizada por el demonio de Zabbix y cargada al inicio. La biblioteca debe contener ciertas funciones, de modo que un proceso de Zabbix pueda detectar que el archivo es realmente un módulo que puede cargar y con el que puede trabajar.

Los módulos cargables tienen una serie de ventajas. El gran rendimiento y la capacidad de implementar cualquier lógica son muy importantes, pero quizás la ventaja más importante es la capacidad de desarrollar, utilizar y compartir módulos de Zabbix. Contribuye a un mantenimiento sin problemas y ayuda a ofrecer nuevas funcionalidades más fácilmente e independientemente de la base de código principal de Zabbix.

La licencia y distribución de módulos en forma binaria se rige por la licencia AGPL-3.0 (los módulos se enlazan con Zabbix en tiempo de ejecución y utilizan cabeceras de Zabbix; todo el código de Zabbix está licenciado bajo AGPL-3.0 desde Zabbix 7.0). Zabbix no garantiza la compatibilidad binaria.

La estabilidad de la API de los módulos está garantizada durante un ciclo de lanzamiento de Zabbix LTS (Long Term Support). No se garantiza la estabilidad de la API de Zabbix (técnicamente es posible llamar a funciones internas de Zabbix desde un módulo, pero no hay garantía de que dichos módulos funcionen).

API de módulos

Para que una biblioteca compartida sea tratada como un módulo de Zabbix, debe implementar y exportar varias funciones. Actualmente hay seis funciones en la API de módulos de Zabbix, de las cuales sólo una es obligatoria y las otras cinco son opcionales.

Interfaz obligatoria

La única función obligatoria es zbx_module_api_version():

int zbx_module_api_version(void);

Esta función debe devolver la versión de la API implementada por este módulo y, para que el módulo se cargue, esta versión debe coincidir con la versión de la API de módulo soportada por Zabbix. La versión de la API de módulo soportada por Zabbix es ZBX_MODULE_API_VERSION. Por lo tanto, esta función debe devolver esta constante. La antigua constante ZBX_MODULE_API_VERSION_ONE utilizada para este propósito ahora está definida como igual a ZBX_MODULE_API_VERSION para preservar la compatibilidad con el código fuente, pero no se recomienda su uso.

Interfaz opcional

Las funciones opcionales son zbx_module_init(), zbx_module_item_list(), zbx_module_item_timeout(), zbx_module_history_write_cbs() y zbx_module_uninit():

int zbx_module_init(void);

Esta función debe realizar la inicialización necesaria para el módulo (si la hay). Si tiene éxito, debe devolver ZBX_MODULE_OK. De lo contrario, debe devolver ZBX_MODULE_FAIL. En este último caso, Zabbix no se iniciará.

ZBX_METRIC  *zbx_module_item_list(void);

Esta función debe devolver una lista de items soportados por el módulo. Cada item se define en una estructura ZBX_METRIC, consulte la sección siguiente para más detalles. La lista termina con una estructura ZBX_METRIC con el campo "key" en NULL.

void    zbx_module_item_timeout(int timeout);

Si el módulo exporta zbx_module_item_list() entonces esta función es utilizada por Zabbix para especificar la configuración de timeout en el archivo de configuración de Zabbix que las comprobaciones de items implementadas por el módulo deben respetar. Aquí, el parámetro "timeout" está en segundos.

ZBX_HISTORY_WRITE_CBS   zbx_module_history_write_cbs(void);

Esta función debe devolver funciones de callback que el servidor Zabbix utilizará para exportar el histórico de diferentes tipos de datos. Las funciones de callback se proporcionan como campos de la estructura ZBX_HISTORY_WRITE_CBS, los campos pueden ser NULL si el módulo no está interesado en el histórico de cierto tipo.

int zbx_module_uninit(void);

Esta función debe realizar la desinicialización necesaria (si la hay), como liberar recursos asignados, cerrar descriptores de archivos, etc.

Todas las funciones se llaman una vez al iniciar Zabbix cuando se carga el módulo, con la excepción de zbx_module_uninit(), que se llama una vez al apagar Zabbix cuando se descarga el módulo.

Definiendo items

Cada item se define en una estructura ZBX_METRIC:

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

Aquí, key es la clave del item (por ejemplo, "dummy.random"), flags es CF_HAVEPARAMS o 0 (dependiendo de si el item acepta parámetros o no), function es una función en C que implementa el item (por ejemplo, "zbx_module_dummy_random"), y test_param es la lista de parámetros que se utilizará cuando el agent de Zabbix se inicie con el parámetro "-p" (por ejemplo, "1,1000", puede ser NULL). Una definición de ejemplo puede verse así:

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

Cada función que implementa un item debe aceptar dos parámetros de tipo puntero, el primero de tipo AGENT_REQUEST y el segundo de tipo 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;
       }

Estas funciones deben devolver SYSINFO_RET_OK, si el valor del item se obtuvo correctamente. De lo contrario, deben devolver SYSINFO_RET_FAIL. Consulte el ejemplo del módulo "dummy" a continuación para obtener detalles sobre cómo obtener información de AGENT_REQUEST y cómo establecer información en AGENT_RESULT.

Proporcionar callbacks de exportación de historial

La exportación de historial a través del módulo ya no es compatible con el proxy de Zabbix.

El módulo puede especificar funciones para exportar datos de historial por tipo: Numérico (float), Numérico (unsigned), Carácter, Texto y 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;

Cada una de ellas debe tomar como argumentos un array "history" de "history_num" elementos. Dependiendo del tipo de datos de historial a exportar, "history" es un array de las siguientes estructuras, respectivamente:

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;

Los callbacks serán utilizados por los procesos history syncer del servidor Zabbix al final del procedimiento de sincronización de historial, después de que los datos se escriban en la base de datos de Zabbix y se guarden en la caché de valores.

En caso de error interno en el módulo de exportación de historial, se recomienda que el módulo esté escrito de tal manera que no bloquee toda la monitorización hasta que se recupere, sino que descarte los datos y permita que el servidor Zabbix continúe funcionando.

Compilación de módulos

Actualmente, los módulos están destinados a ser compilados dentro del árbol de fuentes de Zabbix, porque la API del módulo depende de algunas estructuras de datos que se definen en los encabezados de Zabbix.

El encabezado más importante para los módulos cargables es include/module.h, que define estas estructuras de datos. Otros encabezados de sistema necesarios que ayudan a que include/module.h funcione correctamente son stdlib.h y stdint.h.

Teniendo en cuenta esta información, todo está listo para que el módulo se compile. El módulo debe incluir stdlib.h, stdint.h y module.h, y el script de compilación debe asegurarse de que estos archivos estén en la ruta de inclusión. Consulte el ejemplo de módulo "dummy" a continuación para más detalles.

Otro encabezado útil es include/zbxcommon.h, que define la función zabbix_log(), que puede utilizarse para fines de registro y depuración.

Parámetros de configuración

El agent, server y proxy de Zabbix admiten dos parámetros para trabajar con módulos:

  • LoadModulePath – ruta completa a la ubicación de los módulos cargables
  • LoadModule – módulo(s) a cargar al inicio. Los módulos deben estar ubicados en un directorio especificado por LoadModulePath o la ruta debe preceder al nombre del módulo. Si la ruta precedente es absoluta (comienza con '/') entonces se ignora LoadModulePath. Se permite incluir varios parámetros LoadModule.

Por ejemplo, para extender el agent de Zabbix podríamos añadir los siguientes parámetros:

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

Al iniciar el agent, cargará los módulos mariadb.so, apache.so y kernel.so desde el directorio /usr/local/lib/zabbix/agent, mientras que dummy.so se cargará desde /usr/local/lib/zabbix. El agent no podrá iniciarse si falta un módulo, en caso de permisos incorrectos o si una biblioteca compartida no es un módulo de Zabbix.

Configuración del frontend

Los módulos cargables son compatibles con el agent, server y proxy de Zabbix. Por lo tanto, el tipo de item en el frontend de Zabbix depende de dónde se cargue el módulo. Si el módulo se carga en el agent, entonces el tipo de item debe ser "Zabbix agent" o "Zabbix agent (active)". Si el módulo se carga en el server o proxy, entonces el tipo de item debe ser "Simple check".

La exportación de historial a través de módulos de Zabbix no necesita ninguna configuración en el frontend. Si el módulo se carga correctamente por el server y proporciona la función zbx_module_history_write_cbs() que devuelve al menos una función de callback distinta de NULL, entonces la exportación de historial se habilitará automáticamente.

Módulo de ejemplo

Zabbix incluye un módulo de ejemplo escrito en lenguaje C. El módulo se encuentra en 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

El módulo está bien documentado y puede utilizarse como plantilla para sus propios módulos.

Después de ejecutar ./configure en la raíz del árbol de fuentes de Zabbix como se describe arriba, simplemente ejecute make para construir dummy.so.

/*
       ** 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"
       
       /* la variable mantiene la configuración de timeout para el procesamiento de items */
       static int  item_timeout = 0;
       
       /* el módulo DEBE definir funciones internas como estáticas y usar un patrón de nombres diferente de los símbolos internos de Zabbix (zbx_*) y de las funciones API de módulos cargables (zbx_module_*) para evitar conflictos */
       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("Número de parámetros inválido."));
               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("Número de parámetros inválido."));
               return SYSINFO_RET_FAIL;
           }
       
           param1 = get_rparam(request, 0);
           param2 = get_rparam(request, 1);
       
           /* no hay validación estricta de parámetros y tipos por simplicidad */
           from = atoi(param1);
           to = atoi(param2);
       
           if (from > to)
           {
               SET_MSG_RESULT(result, strdup("Rango especificado inválido."));
               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)
       {
           /* inicialización para 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++)
           {
               /* hacer algo con 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++)
           {
               /* hacer algo con 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++)
           {
               /* hacer algo con 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++)
           {
               /* hacer algo con 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++)
           {
               /* hacer algo con 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;
       }

El módulo exporta tres nuevos items:

  • dummy.ping - siempre devuelve '1'
  • dummy.echo[param1] - devuelve el primer parámetro tal cual, por ejemplo, dummy.echo[ABC] devolverá ABC
  • dummy.random[param1, param2] - devuelve un número aleatorio dentro del rango param1-param2, por ejemplo, dummy.random[1,1000000]

Limitaciones

El soporte de módulos cargables está implementado solo para la plataforma Unix. Esto significa que no funciona para los agentes de Windows.

En algunos casos, un módulo puede necesitar leer parámetros de configuración relacionados con el módulo desde zabbix_agentd.conf. Actualmente no está soportado. Si necesita que su módulo utilice algunos parámetros de configuración, probablemente debería implementar el análisis de un archivo de configuración específico del módulo.