Crear un complemento (tutorial)

Este es un tutorial paso a paso para crear un complemento cargable simple para Zabbix agent 2.

Qué crearás

Durante este tutorial agregarás un nuevo complemento cargable MyIP. El complemento implementará 1 métrica llamada myip que devuelve la dirección IP externa del host donde se ejecuta el agente Zabbix 2.

Parte 1: Escribir el código Go

En esta sección aprenderá cómo escribir el complemento que agrega una nueva métrica al agente Zabbix 2.

  1. Cree un nuevo directorio myip en /usr/local/zabbix/go/plugins/.

  2. Cree el archivo main.go dentro del directorio myip y defina el nombre de su paquete Go.

/usr/local/zabbix/go/plugins/myip/main.go

package main

Mantenga el archivo abierto para agregar más líneas como se describe en los siguientes pasos.

  1. Especifique los paquetes a importar. Estos son los paquetes que admiten el complemento.

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
  1. Defina la estructura del complemento. Incruste la estructura plugin.Base para obtener acceso a la funcionalidad del complemento estándar.

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
       
       type Plugin struct {
           plugin.Base
       }
              
       var impl Plugin
  1. Implementar la interfaz del complemento Exportar. La interfaz Exportar realiza una encuesta y devuelve un valor.

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
       
       type Plugin struct {
           plugin.Base
       }
              
       var impl Plugin
       
       func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error)
  1. Agregue el registro. Los mensajes de registro aparecerán en el registro del agente 2 de Zabbix. Puede utilizar una de las funciones de registro disponibles para los complementos: Critf(), Errf(), Infof(), Warningf(), Debugf(), Tracef().

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
       
       type Plugin struct {
           plugin.Base
       }
              
       var impl Plugin
       
       func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error){
           p.Infof("received request to handle %s key with %d parameters", key, len(params))
       }
  1. Implemente la lógica del complemento principal. Esta lógica obtiene la respuesta de la URL especificada y la lee, luego devuelve la dirección IP como respuesta y cierra la solicitud. En caso de un error al ejecutar la solicitud GET o al leer una respuesta, se devuelve el error.

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
       
       type Plugin struct {
           plugin.Base
       }
              
       var impl Plugin
       
       func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error){
           p.Infof("received request to handle %s key with %d parameters", key, len(params))
           resp, err := http.Get("https://api.ipify.org")
           if err != nil {
               return nil, err
           }
              
           defer resp.Body.Close()
              
           body, err := ioutil.ReadAll(resp.Body)
           if err != nil {
               return nil, err
           }
              
           return string(body), nil    
       }
  1. Registre la métrica. El agente 2 de Zabbix inicia la ejecución de la función init() al inicio. Esta función llamará al método plugin.RegisterMetrics(structure, plugin name, metric name, description) para obtener los datos del complemento.

La descripción del parámetro del método plugin.RegisterMetrics:

  • structure - un puntero a la implementación del complemento; otorga acceso a la estructura del complemento, incluida la lista de interfaces de complementos disponibles (por ejemplo, &impl).
  • name - nombre del complemento; debe ser único (por ejemplo, "Myip").
  • metric name - nombre de métrica (por ejemplo, "myip"). Esta es la clave del elemento que se utiliza para recopilar datos de un complemento.
  • description - descripción de la métrica; debe comenzar con mayúscula y terminar con punto (por ejemplo, ""Devuelve la dirección IP externa del host donde se ejecuta el agente.").

Para registrar varias métricas, repita los parámetros metric name y description para cada métrica. Por ejemplo: plugin.RegisterMetrics(&impl, "Myip", "metric.one", "Descripción de métrica uno.", "metric.two", "Descripción de métrica dos.")

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
       
       type Plugin struct {
           plugin.Base
       }
              
       var impl Plugin
       
       func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error){
           p.Infof("received request to handle %s key with %d parameters", key, len(params))
           resp, err := http.Get("https://api.ipify.org")
           if err != nil {
               return nil, err
           }
              
           defer resp.Body.Close()
              
           body, err := ioutil.ReadAll(resp.Body)
           if err != nil {
               return nil, err
           }
              
           return string(body), nil    
       }
       
       func init() {
           plugin.RegisterMetrics(&impl, "Myip", "myip", "Return the external IP address of the host where agent is running.")
       }
  1. Defina la función main(), que creará una nueva instancia del controlador del complemento, la asignará para que el complemento la use para iniciar sesión y luego ejecutará el controlador del complemento.

Definir la función main() es obligatorio.

/usr/local/zabbix/go/plugins/myip/main.go

package main
       
       import (
           "fmt"
           "io/ioutil"
           "net/http"
           "git.zabbix.com/ap/plugin-support/plugin/container"
           "git.zabbix.com/ap/plugin-support/plugin"
       )
       
       type Plugin struct {
           plugin.Base
       }
              
       var impl Plugin
       
       func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) (result interface{}, err error){
           p.Infof("received request to handle %s key with %d parameters", key, len(params))
           resp, err := http.Get("https://api.ipify.org")
           if err != nil {
               return nil, err
           }
              
           defer resp.Body.Close()
              
           body, err := ioutil.ReadAll(resp.Body)
           if err != nil {
               return nil, err
           }
              
           return string(body), nil    
       }
       
       func init() {
           plugin.RegisterMetrics(&impl, "Myip", "myip", "Return the external IP address of the host where agent is running.")
       }
       
       func main() {
           h, err := container.NewHandler(impl.Name())
           if err != nil {
               panic(fmt.Sprintf("failed to create plugin handler %s", err.Error()))
           }
           impl.Logger = &h
              
           err = h.Execute()
           if err != nil {
               panic(fmt.Sprintf("failed to execute plugin handler %s", err.Error()))
           }
       }

Parte 2: Creación del complemento

En esta sección aprenderá cómo compilar el complemento.

  1. Para crear archivos Go para el manejo de dependencias y descargar las dependencias, ejecute automáticamente este script bash desde la CLI.
go mod init myip
       GOPROXY=direct go get git.zabbix.com/ap/plugin-support/plugin@branchname
       go mod tidy
       go build

Asegúrese de especificar el nombre correcto de la rama, es decir, reemplace branchname (ver Línea 2) con uno de los siguientes:

  • release/* - para la rama de lanzamiento estable, donde "*" es la versión de lanzamiento (es decir, 6.4)
  • master - para la rama master
  • <commit hash> - para la versión de confirmación específica (use el hash de confirmación específico)

El resultado debería ser similar a este:

go: creating new go.mod: module myip
       go: to add module requirements and sums:
       go mod tidy
       go: finding module for package git.zabbix.com/ap/plugin-support/plugin/container
       go: finding module for package git.zabbix.com/ap/plugin-support/plugin
       go: found git.zabbix.com/ap/plugin-support/plugin in git.zabbix.com/ap/plugin-support v0.0.0-20220608100211-35b8bffd7ad0
       go: found git.zabbix.com/ap/plugin-support/plugin/container in git.zabbix.com/ap/plugin-support v0.0.0-20220608100211-35b8bffd7ad0
  1. Cree un ejecutable myip para el complemento cargable.

  2. Especifique la ruta al archivo de configuración del complemento en el parámetro Plugins.Myip.System.Path del archivo de configuración del agente 2 de Zabbix.

El nombre del complemento en el nombre del parámetro de configuración (Myip en este tutorial) debe coincidir con el nombre del complemento definido en la función plugin.RegisterMetrics().

echo 'Plugins.Myip.System.Path=/usr/local/zabbix/go/plugins/myip/myip' > /etc/zabbix_agent2.d/plugins.d/myip.conf
  1. Pruebe la métrica:
zabbix_agent2 -t myip

La respuesta debe contener una dirección IP externa de su equipo.

En caso de error, verifique si el usuario zabbix tiene permisos para acceder al directorio /usr/local/zabbix/go/plugins/myip.