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.
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.
go.mod
al directori del plugin per fer un seguiment de les dependències del connector:golang.zabbix.com/sdk
):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:
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
.
main.go
buit per al codi font del connector:Ara la configuració inicial s'ha completat i el plugin és a punt per al desenvolupament.
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.
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.
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.
Ara, importeu el paquet plugin i creeu una estructura myIP
que inclogui l'estructura 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
.
El vostre plugin necessita les claus d'element per recopilar dades i proporcionar-les al servidor o proxy Zabbix.
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.")
El controlador facilita la comunicació entre l'agent i el plugin.
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
}
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)
import (
"io"
"net/http"
)
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
}
Això hauria de crear un executable myip
al directori actual.
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().
myip
, executeu: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!
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
}