Creación de un plugin
Esta página está dirigida a quienes estén interesados en desarrollar su propio plugin (recopilador de datos independiente) para Zabbix agent 2.
Un plugin personalizado permite ampliar la funcionalidad de Zabbix agent 2 más allá de los plugins integrados y los plugins cargables proporcionados.
Cada plugin es un paquete de Go que define la estructura e implementa una o varias interfaces (Exporter, Configurator, Runner). Para más información, consulte Interfaces de plugin y Diagrama de conexión.
Esta guía le ayudará a crear un plugin cargable personalizado.
Para obtener orientación adicional, consulte también el repositorio de:
Lo que crearás
Este es un tutorial paso a paso para crear un plugin cargable simple llamado MyIP.
Este plugin implementará una única clave de item (myip) que devuelve la dirección IP externa del host del agent de Zabbix.
Paso 1: Configuración
- Un plugin es un módulo Go estándar.
Comience inicializando el archivo
go.moden el directorio del plugin para realizar el seguimiento de las dependencias del plugin:
cd path/to/plugins/myip # Cambie a su directorio del plugin
go mod init myip
- Instale la dependencia obligatoria Zabbix Go SDK (
golang.zabbix.com/sdk):
go get golang.zabbix.com/sdk@$LATEST_COMMIT_HASH
Sustituya $LATEST_COMMIT_HASH por el hash del commit HEAD más reciente del repositorio golang.zabbix.com/sdk en la rama de versión correspondiente.
Por ejemplo:
go get golang.zabbix.com/sdk@af85407
Tenga en cuenta que actualmente no se admite el control de versiones de golang.zabbix.com/sdk, pero esto puede cambiar en el futuro.
Las dependencias adicionales pueden instalarse según sea necesario mediante go get.
- Cree un archivo
main.govacío para el código fuente del plugin:
touch main.go
Ahora la configuración inicial está completa y el plugin está listo para el desarrollo.
Paso 2: Estructura del plugin
El módulo golang.zabbix.com/sdk, instalado en el paso anterior, proporciona el framework necesario para el desarrollo de plugins y garantiza que todos los plugins tengan una estructura coherente.
- Configurar el flujo de ejecución básico.
Comience definiendo el flujo de ejecución principal del plugin. Añada el siguiente código a main.go:
package main
func main() {
err := run()
if err != nil {
panic(err)
}
}
func run() error {
return nil
}
Esto establece el flujo de ejecución básico del plugin. La función run contendrá más adelante la lógica principal del plugin.
- Explorar las interfaces del plugin.
Un plugin de Zabbix agent 2 debe estar representado por una estructura que implemente interfaces del paquete golang.zabbix.com/sdk/plugin:
- Accessor - define los métodos esenciales que todos los plugins deben implementar, como establecer el nombre del plugin y gestionar los tiempos de espera de las claves de item.
- Una o más de las siguientes interfaces funcionales de plugin:
- Exporter - realiza una consulta y devuelve un valor (o valores), nada o un error; a menudo se utiliza junto con la interfaz Collector.
- Collector - gestiona la recopilación periódica de datos.
- Runner - define los procedimientos de inicio y apagado del plugin.
- Watcher - permite implementar la consulta independiente de métricas, omitiendo el planificador interno del agent; es útil para la monitorización basada en traps o eventos.
- Configurator - define cómo el plugin lee y aplica sus ajustes de configuración.
Puede implementar estas interfaces usted mismo o utilizar las predeterminadas proporcionadas por el SDK de Go de Zabbix, modificándolas según sea necesario. Este tutorial utiliza las implementaciones predeterminadas.
- Crear la estructura del plugin.
Ahora, importe el paquete plugin y cree una estructura myIP que incruste la estructura plugin.Base:
import "golang.zabbix.com/sdk/plugin"
type myIP struct {
plugin.Base
}
La estructura myIP actualmente satisface la interfaz Accessor.
Más adelante en el tutorial se añadirá un método para implementar una de las interfaces funcionales del plugin, Exporter.
Paso 3: Definir claves de item
Su plugin necesita las claves de item para recopilar datos y proporcionarlos al server o proxy de Zabbix.
- Importe el paquete errs para el manejo de errores:
import "golang.zabbix.com/sdk/errs"
- Registre las claves de item mediante la función
plugin.RegisterMetrics()dentro de la funciónrun():
func run() error {
p := &myIP{}
// Register the `myip` item key.
err := plugin.RegisterMetrics(
p,
"MyIP", // Plugin name
"myip", // Item key name
"Returns the host's IP address.", // Item key description
)
if err != nil {
return errs.Wrap(err, "failed to register metrics")
}
return nil
}
Para registrar varias claves de item, repita los parámetros nombre de métrica y descripción para cada métrica. Por ejemplo:
plugin.RegisterMetrics(&impl, "Myip", "metric.one", "Metric one description.", "metric.two", "Metric two description.")
Paso 4: Configurar el handler
El handler facilita la comunicación entre el agent y el plugin.
- Importe el paquete container:
import "golang.zabbix.com/sdk/plugin/container"
- Dentro de la función
run(), añada código para crear y configurar un handler:
func run() error {
p := &myIP{}
// Register the `myip` item key.
err := plugin.RegisterMetrics(
p,
"MyIP", // Plugin name
"myip", // Item key name
"Returns the host's IP address.", // Item key description
)
if err != nil {
return errs.Wrap(err, "failed to register metrics")
}
// Create a new handler.
h, err := container.NewHandler("MyIP") // Plugin name
if err != nil {
return errs.Wrap(err, "failed to create new handler")
}
// Setup logging to forward logs from the plugin to the agent.
// Available via p.Logger.Infof, p.Logger.Debugf, etc.
p.Logger = h
// Start plugin execution.
// Blocks until a termination request is received from the agent.
err = h.Execute()
if err != nil {
return errs.Wrap(err, "failed to execute plugin handler")
}
return nil
}
Paso 5: Implementar la recopilación de datos
La recopilación de datos se realiza mediante la interfaz Exporter, que describe el método Export:
func Export(
key string, // La clave del item que se va a recopilar.
params []string, // Argumentos pasados a la clave del item (`myip[arg1, arg2]`).
context ContextProvider // Metadatos sobre la recopilación de datos de la clave del item.
) (any, error)
- Importe los paquetes necesarios para solicitudes HTTP y lectura de respuestas:
import (
"io"
"net/http"
)
- Implemente el método
Exportpara la estructuramyIP:
func (p *myIP) Export(
key string, params []string, context plugin.ContextProvider,
) (any, error) {
// El plugin puede usar una lógica de recopilación de datos diferente según el parámetro `key`.
// Esta implementación solo verifica que la `key` proporcionada sea compatible.
if key != "myip" {
return nil, errs.Errorf("unknown item key %q", key)
}
// El registro se reenviará al registro del agent 2.
p.Infof(
"received request to handle %q key with %d parameters",
key,
len(params),
)
// Recopile los datos y devuélvalos.
resp, err := http.Get("https://api.ipify.org")
if err != nil {
return nil, errs.Wrap(err, "failed to get IP address")
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, errs.Wrap(err, "failed to read response body")
}
return string(body), nil
}
Paso 6: Compilar y configurar el plugin
- Para compilar el plugin, ejecute:
go mod tidy
go build
Esto debería crear un ejecutable myip en el directorio actual.
- Configure Zabbix agent 2 para usar el plugin:
echo "Plugins.MyIP.System.Path=$PATH_TO_THE_MYIP_PLUGIN_EXECUTABLE" > /etc/zabbix_agent2.d/plugins.d/myip.conf
Reemplace $PATH_TO_THE_MYIP_PLUGIN_EXECUTABLE por la ruta al myip creado en el paso 5.
El nombre del plugin en el nombre del parámetro de configuración (MyIP en este tutorial) debe coincidir con el nombre del plugin definido en la función plugin.RegisterMetrics().
- Para probar el plugin y su item
myip, ejecute:
zabbix_agent2 -c /etc/zabbix_agent2.conf -t myip
La salida debería contener una dirección IP externa de su host y verse similar a esto:
myip [s|192.0.2.0]
Con esto, ha creado un plugin cargable simple para Zabbix agent 2. ¡Felicidades!
Código fuente completo
package main
import (
"io"
"net/http"
"golang.zabbix.com/sdk/errs"
"golang.zabbix.com/sdk/plugin"
"golang.zabbix.com/sdk/plugin/container"
)
var _ plugin.Exporter = (*myIP)(nil)
type myIP struct {
plugin.Base
}
func main() {
err := run()
if err != nil {
panic(err)
}
}
func run() error {
p := &myIP{}
// Registra la clave de item `myip`.
err := plugin.RegisterMetrics(
p,
"MyIP", // Nombre del plugin
"myip", // Nombre de la clave de item
"Devuelve la dirección IP del host.", // Descripción de la clave de item
)
if err != nil {
return errs.Wrap(err, "failed to register metrics")
}
// Crea un nuevo controlador.
h, err := container.NewHandler("MyIP") // Nombre del plugin
if err != nil {
return errs.Wrap(err, "failed to create new handler")
}
// Configura el registro para reenviar los logs del plugin al agent.
// Disponible mediante p.Logger.Infof, p.Logger.Debugf, etc.
p.Logger = h
// Inicia la ejecución del plugin.
// Se bloquea hasta que se recibe una solicitud de finalización del agent.
err = h.Execute()
if err != nil {
return errs.Wrap(err, "failed to execute plugin handler")
}
return nil
}
func (p *myIP) Export(
key string, params []string, context plugin.ContextProvider,
) (any, error) {
// El plugin puede usar una lógica de recopilación de datos diferente según el parámetro `key`.
// Esta implementación solo verifica que la `key` proporcionada sea compatible.
if key != "myip" {
return nil, errs.Errorf("unknown item key %q", key)
}
// El log se reenviará al log 2 del agent.
p.Infof(
"received request to handle %q key with %d parameters",
key,
len(params),
)
// Recopila los datos y los devuelve.
resp, err := http.Get("https://api.ipify.org")
if err != nil {
return nil, errs.Wrap(err, "failed to get IP address")
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, errs.Wrap(err, "failed to read response body")
}
return string(body), nil
}