Tutorial per crear un plugin

Aquest és un tutorial passa a passa per crear un plugin senzill carregable per a l'agent Zabbix 2.

També podeu emprar el nostre repositori d'exemples com a plantilla o guia per crear els vostres propis plugins.

Què creareu

Aquest tutorial us ensenya com crear nou plugincarregable MyIP. El plugin implementarà una única clau d'element, myip, que retorna l'adreça IP externa de l'equip on s'executa l'agent Zabbix 2.

Passa 1: Configuració

  1. Un plugin és un mòdul estàndard de Go. Comenceu inicialitzant el fitxer go.mod al directori del plugin per fer un seguiment de les dependències del connector:
cd path/to/plugins/myip # Canvia al directori del vostre connector
       go mod init myip
  1. Instal·leu la dependència obligatòria Zabbix Go SDK (golang.zabbix.com/sdk):
go get golang.zabbix.com/sdk@$LATEST_COMMIT_HASH

Substituïu $LATEST_COMMIT_HASH amb el darrer hash de commit HEAD del repositori de golang.zabbix.com/sdk a la branca de llançament adequada. Per exemple:

go get golang.zabbix.com/sdk@af85407

Tingueu en compte que actualment no s'admet el control de versions de golang.zabbix.com/sdk, però això pot canviar més endavant.

Es poden instal·lar dependències addicionals segons calgui mitjançant go get.

  1. Creeu un fitxer main.go buit per al codi font del connector:
touch main.go

Ara la configuració inicial s'ha completat i el plugin és a punt per al desenvolupament.

Segona passa: Estructura del plugin

El mòdul golang.zabbix.com/sdk, instal·lat a la passa anterior, proporciona el marc necessari per al desenvolupament de connectors i garanteix que tots els plugins tinguin una estructura coherent.

  1. Configureu el flux d'execució bàsic.

Comenceu definint el flux d'execució principal del plugin. Afegiu el codi següent a main.go:

package main
       
       func main() {
       err := run()
       if err != nil {
       panic(err)
       }
       }
       
       func run() error {
       return nil
       }

Això estableix el flux d'execució bàsic per al plugin. La funció run contindrà més tard la lògica principal del plugin.

  1. Exploreu les interfícies del plugin.

Un complement Zabbix agent 2 es representarà mitjançant una estructura que implementi les interfícies del paquet golang.zabbix.com/sdk/plugin:

  • Accessor - defineix els mètodes essencials que tots els complements han d'implementar, com ara establir el nom del complement i gestionar els temps d'espera de les claus de l'element.

  • Una o més de les següents interfícies funcionals del complement:

  • Exporter - realitza una enquesta i retorna un valor (o valors), res o un error; sovint s'utilitza juntament amb la interfície Collector.

  • Collector - gestiona la recopilació periòdica de dades.

  • Runner - defineix els procediments d'inici i apagament del complement.

  • Watcher - permet implementar enquestes mètriques independents, evitant el planificador intern de l'agent; útil per al monitoratge basat en trampes o en esdeveniments.

  • Configurator - defineix com el complement llegeix i aplica els seus paràmetres de configuració.

Podeu implementar aquestes interfícies vosaltres mateixos o utilitzar les predeterminades proporcionades pel Zabbix Go SDK, modificant-les segons calgui. Aquest tutorial utilitza les implementacions per defecte.

  1. Creeu l'estructura del complement.

Ara, importeu el paquet plugin i creeu una estructura myIP que inclogui l'estructura plugin.Base:

import "golang.zabbix.com/sdk/plugin"
       
       type myIP struct {
       plugin.Base
       }

L'estructura myIP actualment satisfà la interfície Accessor. Més endavant al tutorial s'afegirà un mètode per implementar una de les interfícies funcionals del complement, l'Exporter.

Tercera passa: Definiu les claus d'element

El vostre plugin necessita les claus d'element per recopilar dades i proporcionar-les al servidor o proxy Zabbix.

  1. Importeu el paquet errs per a la gestió d'errors:
import "golang.zabbix.com/sdk/errs"
  1. Registreu les claus d'element mitjançant la funció plugin.RegisterMetrics() dins de la funció run():
func run() error {
       p := &myIP{}
       
       // Registreu la clau d'element `myip`.
       
       err := plugin.RegisterMetrics(
       p,
       "LaMevaIP", // Nom del complement
       "lamevaip", // Nom de la clau de l'element
       "Retorna l'adreça IP de l'equip.", // Descripció de la clau de l'element
       )
       if err != nil {
       return errs.Wrap(err, "no s'han pogut registrar les mètriques")
       }
       
       return nil
       }

Per registrar diverses claus d'element, repetiu els paràmetres nom de la mètrica i descripció per a cada mètrica. Per exemple:

plugin.RegisterMetrics(&impl, "LaMevaIP", "mètrica.un", "Descripció de la mètrica u.", "mètrica.dos", "Descripció de la mètrica dos.")

Quarta passa: Configura el controlador

El controlador facilita la comunicació entre l'agent i el plugin.

  1. Importa el paquet container:
import "golang.zabbix.com/sdk/plugin/container"
  1. Indiqueu la funció run() i afegiu el codi per crear i configurar un controlador:
func run() error {
       p := &myIP{}
       
       // Registra la clau de l'element `myip`.
       err := plugin.RegisterMetrics(
       p,
       "MyIP", // Nom del connector
       "myip", // Nom de la clau de l'element
       "Retorna l'adreça IP de l'amfitrió.", // Descripció de la clau de l'element
       )
       if err != nil {
       return errs.Wrap(err, "no s'han pogut registrar les mètriques")
       }
       
       // Crea un nou controlador.
       
       h, err := container.NewHandler("LaMevaIP") // Nom del connector
       if err != nil {
       return errs.Wrap(err, "no s'ha pogut crear el nou controlador")
       }
       
       // Configura el registre per reenviar els registres del plugin a l'agent.
       // Disponible a través de p.Logger.Infof, p.Logger.Debugf, etc.
       p.Logger = h
       
       // Inicia l'execució del plugin.
       // Es bloqueja fins que es rep una peticó de tancament de l'agent.
       err = h.Execute()
       if err != nil {
       return errs.Wrap(err, "no s'ha pogut executar el controlador del plugin")
       }
       
       return nil
       }

Cinquena passa: Implementar el recull de dades

El recull de dades es fa a través de la interfície Exporter, que descriu el mètode Export:

func Export(
       key string, // La clau de l'element a recopilar.
       params []string, // Arguments passats a la clau de l'element (`myip[arg1, arg2]`).
       context ContextProvider // Metadades sobre la recopilació de dades de la clau de l'element.
       ) (any, error)
  1. Importeu els paquets necessaris per a les peticions HTTP i la lectura de respostes:
import (
       "io"
       "net/http"
       )
  1. Implementeu el mètode Export per a l'estructura myIP:
func (p *myIP) Export(
       key string, params []string, context plugin.ContextProvider,
       ) (any, error) {
       // El plugin pot utilitzar diferents lògiques de recopilació de dades basades en el paràmetre `key`.
       
       // Aquesta implementació només verifica que la `clau` proporcionada sigui compatible.
       if key != "myip" {
       return nil, errs.Errorf("clau d'element desconeguda %q", key)
       }
       
       // El registre es reenviarà al registre de l'agent 2.
       p.Infof(
       "s'ha rebut una petició per gestionar la clau %q amb %d paràmetres",
       key,
       len(params),
       )
       
       // Recopila les dades i les retorna.
       
       resp, err := http.Get("https://api.ipify.org")
       if err != nil {
       return nil, errs.Wrap(err, "no s'ha pogut obtindre l'adreça IP")
       }
       
       defer resp.Body.Close()
       
       body, err := io.ReadAll(resp.Body)
       if err != nil {
       return nil, errs.Wrap(err, "no s'ha pogut llegir el cos de la resposta")
       }
       
       return string(body), nil
       }

Sisena passa: Compilar i configurar el plugin

  1. Per compilar el plugin, executeu:
go mod tidy
       go build

Això hauria de crear un executable myip al directori actual.

  1. Configureu l'agent 2 de Zabbix per utilitzar el plugin:
echo "Plugins.MyIP.System.Path=$PATH_TO_THE_MYIP_PLUGIN_EXECUTABLE" > /etc/zabbix_agent2.d/plugins.d/myip.conf

Substituïu $PATH_TO_THE_MYIP_PLUGIN_EXECUTABLE amb la ruta al myip creat al pas 5.

El nom del plugin al nom del paràmetre de configuració (MyIP en aquest tutorial) ha de coincidir amb el nom del plugin definit a la funció plugin.RegisterMetrics().

  1. Per provar el plugin i el seu element myip, executeu:
zabbix_agent2 -c /etc/zabbix_agent2.conf -t myip

La sortida hauria de contindre una adreça IP externa del vostre equip i tenir un aspecte similar a aquest:

myip [s|192.0.2.0]

Amb això, heu creat un plugin carregable senzill per a Zabbix agent 2. Felicitats!

Codi font complet

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 clau de l'element `myip`.
       err := plugin.RegisterMetrics(
       p,
       "LaMevaIP", // Nom del connector
       "laMevaIP", // Nom de la clau de l'element
       "Retorna l'adreça IP de l'equip.", // Descripció de la clau de l'element
       )
       if err != nil {
       return errs.Wrap(err, "no s'han pogut registrar les mètriques")
       }
       
       // Crea un nou controlador.
       h, err := container.NewHandler("LaMevaIP") // Nom del plugin
       if err != nil {
       return errs.Wrap(err, "no s'ha pogut crear un nou controlador")
       }
       
       // Configura el registre per reenviar els registres del plugin a l'agent.
       // Disponible a través de p.Logger.Infof, p.Logger.Debugf, etc.
       p.Logger = h
       
       // Inicia l'execució del connector.
       // Es bloqueja fins que es rep una petició de tancament de l'agent.
       err = h.Execute()
       if err != nil {
       return errs.Wrap(err, "no s'ha pogut executar el controlador del complement")
       }
       
       return nil
       }
       
       func (p *myIP) Export(
       key string, params []string, context plugin.ContextProvider,
       ) (any, error) {
       // El complement pot utilitzar una lògica de recopilació de dades diferent basada en el paràmetre `key`.
       // Aquesta implementació només verifica que la `key` proporcionada sigui compatible.
       if key != "myip" {
       return nil, errs.Errorf("clau d'element desconeguda %q", key)
       }
       
       // El registre es reenviarà al registre de l'agent 2.
       p.Infof(
       "s'ha rebut una petició per gestionar la clau %q amb %d paràmetres",
       key,
       len(params),
       )
       
       // Recopila les dades i les retorna.
       
       resp, err := http.Get("https://api.ipify.org")
       if err != nil {
       return nil, errs.Wrap(err, "no s'ha pogut obtindre l'adreça IP")
       }
       
       defer resp.Body.Close()
       
       body, err := io.ReadAll(resp.Body)
       if err != nil {
       return nil, errs.Wrap(err, "no s'ha pogut llegir el cos de la resposta")
       }
       
       return string(body), nil
       }