Esta página foi traduzida automaticamente. Se você notar um erro, selecione-o e pressione Ctrl+Enter para reportá-lo aos editores.

Criar um plugin (tutorial)

Este é um tutorial passo a passo sobre como criar um plugin carregável simples para o agente Zabbix 2.

Você também pode usar o repositório de exemplo como modelo ou guia para criar seus próprios plugins.

O que você criará

Durante este tutorial, você adicionará um novo plug-in carregável MyIP. O plug-in implementará uma métrica chamada myip, que retorna o endereço IP externo do host em que o Zabbix Agent 2 está sendo executado.

Etapa 1: Configuração

  1. Um plugin é um módulo Go padrão. Comece inicializando o arquivo go.mod no diretório do plugin para rastrear as dependências do plugin:
cd caminho/para/plugins/myip # Mude para o diretório do seu plugin
       go mod init myip
  1. Instale a dependência obrigatória do Zabbix Go SDK (golang.zabbix.com/sdk):
go get golang.zabbix.com/sdk@$LATEST_COMMIT_HASH

Substitua $LATEST_COMMIT_HASH pelo hash de commit HEAD mais recente do golang.zabbix.com/sdk repositório na ramificação de lançamento apropriada.

Por exemplo:

go get golang.zabbix.com/sdk@af85407

Observe que o versionamento golang.zabbix.com/sdk não é suportado atualmente, mas isso pode mudar no futuro.

Dependências adicionais podem ser instaladas conforme necessário usando go get.

  1. Crie um arquivo main.go vazio para o código-fonte do plugin:
touch main.go

Agora a configuração inicial está concluída e o plugin está pronto para desenvolvimento.

Etapa 2: Estrutura do plugin

O módulo golang.zabbix.com/sdk, instalado na etapa anterior, fornece a estrutura necessária para o desenvolvimento de plugins e garante que todos tenham uma estrutura consistente.

  1. Configure o fluxo de execução básico.

Comece definindo o fluxo de execução principal do plugin. Adicione o seguinte código a main.go:

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

Isso estabelece o fluxo de execução básico para o plugin. A função run conterá posteriormente a lógica central do plugin.

  1. Explore as interfaces do plugin.

Um plugin do agente Zabbix 2 deve ser representado por uma estrutura que implementa interfaces do pacote golang.zabbix.com/sdk/plugin:

  • Assessor - define métodos essenciais que todos os plugins devem implementar, como definir o nome do plugin e lidar com timeouts de chaves de itens.
  • Uma ou mais das seguintes interfaces funcionais de plugin:
  • Exportador - realiza uma consulta e retorna um valor (ou valores), nada ou um erro; frequentemente usado em conjunto com a interface Coletor.
  • Coletor - gerencia a coleta periódica de dados.
  • Executor - define os procedimentos de inicialização e desligamento do plugin.
  • Observador - permite implementar consultas de métricas independentes, ignorando o agendador interno do agente; útil para monitoramento baseado em traps ou eventos.
  • Configurador - define como o plugin lê e aplica suas configurações.

Você pode implementar essas interfaces você mesmo ou usar as interfaces padrão fornecidas pelo Zabbix Go SDK, modificando-as conforme necessário. Este tutorial usa as implementações padrão.

  1. Crie a estrutura do plugin.

Agora, importe o pacote plugin e crie uma estrutura myIP que incorpore a estrutura plugin.Base:

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

A estrutura myIP atualmente atende à interface Accessor. Um método para implementar uma das interfaces funcionais do plugin, o Exporter, será adicionado posteriormente neste tutorial.

Etapa 3: Definir chaves de item

Seu plugin precisa das chaves de item para coletar dados e fornecê-los ao servidor ou proxy Zabbix.

  1. Importe o pacote errs para tratamento de erros:
import "golang.zabbix.com/sdk/errs"
  1. Registre as chaves de item usando a função plugin.RegisterMetrics() dentro da função run():
func run() error {
       p := &myIP{}
       
       // Registre a chave de item `myip`.
       err := plugin.RegisterMetrics(
       p,
       "MyIP", // Nome do plugin
       "myip", // Nome da chave do item
       "Retorna o endereço IP do host.", // Descrição da chave do item
       )
       if err != nil {
       return errs.Wrap(err, "falha ao registrar métricas")
       }
       
       return nil
       }

Para registrar várias chaves de item, repita os parâmetros nome da métrica e descrição para cada métrica. Por exemplo:

plugin.RegisterMetrics(&impl, "Myip", "metric.one", "Descrição da métrica um.", "metric.two", "Descrição da métrica dois.")

Etapa 4: Configurar o manipulador

O manipulador facilita a comunicação entre o agente e o plugin.

  1. Importe o pacote container:
import "golang.zabbix.com/sdk/plugin/container"
  1. Insira o código da função run() para criar e configurar um manipulador:
func run() error {
       p := &myIP{}
       
       // Registre a chave de item `myip`.
       err := plugin.RegisterMetrics(
       p,
       "MyIP", // Nome do plugin
       "myip", // Nome da chave do item
       "Retorna o endereço IP do host.", // Descrição da chave do item
       )
       if err != nil {
       return errs.Wrap(err, "falha ao registrar métricas")
       }
       
       // Crie um novo manipulador.
       h, err := container.NewHandler("MyIP") // Nome do plugin
       if err != nil {
       return errs.Wrap(err, "falha ao criar novo manipulador")
       }
       
       // Configura o registro para encaminhar logs do plugin para o agente.
       // Disponível via p.Logger.Infof, p.Logger.Debugf, etc.
       p.Logger = h
       
       // Inicia a execução do plugin.
       // Bloqueia até que uma solicitação de término seja recebida do agente.
       err = h.Execute()
       if err != nil {
       return errs.Wrap(err, "falha ao executar o manipulador do plugin")
       }
       
       return nil
       }

Etapa 5: Implementar a coleta de dados

A coleta de dados é feita por meio da interface Exporter, que descreve o método Export:

func Export(
       key string, // A chave do item a ser coletada.
       params []string, // Argumentos passados para a chave do item (`myip[arg1, arg2]`).
       context ContextProvider // Metadados sobre a coleta de dados da chave do item.
       ) (any, error)
  1. Importe os pacotes necessários para solicitações HTTP e leitura de respostas:
import(
       "io"
       "net/http"
       )
  1. Implemente o método Export para a estrutura myIP:
func (p *myIP) Export(
       key string, params []string, context plugin.ContextProvider,
       ) (any, error) {
       // O plugin pode usar diferentes lógicas de coleta de dados com base no parâmetro `key`.
       // Esta implementação apenas verifica se a `chave` fornecida é suportada.
       if key != "myip" {
       return nil, errs.Errorf("chave de item desconhecida %q", key)
       }
       
       // O log será encaminhado para o log do agente 2.
       p.Infof(
       "solicitação recebida para manipular a chave %q com %d parâmetros",
       key,
       len(params),
       )
       
       // Coleta os dados e os retorna.
       
       resp, err := http.Get("https://api.ipify.org")
       if err != nil {
       return nil, errs.Wrap(err, "falha ao obter o endereço IP")
       }
       
       defer resp.Body.Close()
       
       body, err := io.ReadAll(resp.Body)
       if err != nil {
       return nil, errs.Wrap(err, "falha ao ler o corpo da resposta")
       }
       
       return string(body), nil
       }

Etapa 6: Compilar e configurar o plugin

  1. Para compilar o plugin, execute:
go mod tidy
       go build

Isso deve criar um executável myip no diretório atual.

  1. Configure o agente Zabbix 2 para usar o plugin:
echo "Plugins.MyIP.System.Path=$PATH_TO_THE_MYIP_PLUGIN_EXECUTABLE" > /etc/zabbix_agent2.d/plugins.d/myip.conf

Substitua $PATH_TO_THE_MYIP_PLUGIN_EXECUTABLE pelo caminho para o myip criado na etapa 5.

O nome do plugin no parâmetro de configuração name (MyIP neste tutorial) deve corresponder ao nome do plugin definido na função plugin.RegisterMetrics().

  1. Para testar o plugin e seu item myip, execute:
zabbix_agent2 -c /etc/zabbix_agent2.conf -t myip

A saída deve conter um endereço IP externo do seu host e ser semelhante a este:

myip [s|192.0.2.0]

Com isso, você criou um plugin carregável simples para o agente Zabbix 2. Parabéns!

Código-fonte 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 a chave do item `myip`.
           err := plugin.RegisterMetrics(
               p,
               "MyIP",   // Nome do plugin
               "myip",   // Nome da chave do item
               "Retorna o endereço IP do host.", // Descrição da chave do item
           )
           if err != nil {
               return errs.Wrap(err, "falha ao registrar métricas")
           }
           // Cria um novo manipulador.
           h, err := container.NewHandler("MyIP") // Nome do plugin
           if err != nil {
               return errs.Wrap(err, "falha ao criar novo manipulador")
           }
       
           // Configura o registro para encaminhar logs do plugin para o agente.
           // Disponível via p.Logger.Infof, p.Logger.Debugf, etc.
           p.Logger = h
       
           // Inicia a execução do plugin.
           // Bloqueia até que uma solicitação de encerramento do agente seja recebida.
           err = h.Execute()
           if err != nil {
               return errs.Wrap(err, "falha ao executar o manipulador do plugin")
           }
           return nil
       }
       
       func (p *myIP) Export(
           key string, params []string, context plugin.ContextProvider,
       ) (any, error) {
           // O plugin pode usar uma lógica de coleta de dados diferente com base no parâmetro `key`.  
           // Esta implementação verifica apenas se a`key` fornecida é suportada. 
           if key != "myip" {
               return nil, errs.Errorf("unknown item key %q", key)
           }
       
           // O log será encaminhado para o log do agente 2.
           p.Infof(
               "received request to handle %q key with %d parameters",
               key,
               len(params),
           )
       
           // Coleta os dados e os retorna.
           resp, err := http.Get("https://api.ipify.org")
           if err != nil {
               return nil, errs.Wrap(err, "falha ao obter o endereço IP")
           }
       
           defer resp.Body.Close()
       
           body, err := io.ReadAll(resp.Body)
           if err != nil {
               return nil, errs.Wrap(err, "falha ao ler o corpo da resposta")
           }
       
           return string(body), nil
       }