Создание плагина (руководство)

Это пошаговое руководство по созданию простого загружаемого плагина для Zabbix агента 2.

Не стесняйтесь использовать наш репозиторий примеров в качестве шаблона или руководства для создания собственных плагинов.

Что вы создадите

В ходе этого руководства вы добавите новый загружаемый плагин MyIP. Плагин будет реализовывать 1 метрику под названием myip, которая возвращает внешний IP-адрес хоста, на котором работает Zabbix агент 2.

Часть 1. Написание кода Go

В этом разделе вы узнаете, как написать плагин, который добавляет новую метрику в Zabbix агент 2.

  1. Создайте новый каталог myip в /usr/local/zabbix/go/plugins/.

  2. Создайте файл main.go внутри каталога myip и определите имя вашего пакета Go.

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

package main

Keep the file open to add more lines as described in the next steps.

  1. Укажите пакеты для импорта. Это пакеты, которые поддерживают плагин.

/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. Определите структуру плагина. Вставьте структуру plugin.Base, чтобы получить доступ к стандартным функциям плагина.

/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. Реализовать интерфейс плагина Экспорт.

/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. Добавьте логирование. Сообщения журнала появятся в журнале Zabbix агента 2. Вы можете использовать одну из функций журналирования, доступных плагинам: 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. Реализуйте основную логику плагина. Эта логика извлекает ответ из указанного URL-адреса и считывает его, затем возвращает IP-адрес в качестве ответа и закрывает запрос. В случае ошибки при выполнении запроса GET или чтении ответа вместо этого возвращается ошибка.

/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. Зарегистрируйте метрику. Zabbix агент 2 инициирует выполнение функции init() при запуске. Эта функция вызовет метод plugin.RegisterMetrics(structure, name, metric name, description) для получения данных плагина.

Описание параметра метода plugin.RegisterMetrics:

  • structure — указатель на реализацию плагина; предоставляет доступ к структуре плагина, включая список доступных интерфейсов плагина (например, &impl).
  • name - название плагина; должен быть уникальным (например, "Myip").
  • metric name — имя метрики (например, "myip"). Это ключ элемента, используемый для сбора данных из плагина.
  • description — описание метрики; должно начинаться с заглавной буквы и заканчиваться точкой (например, ""Вернуть внешний IP-адрес хоста, на котором запущен агент.").

Чтобы зарегистрировать несколько метрик, повторите параметры имя метрики и описание для каждой метрики. Например: plugin.RegisterMetrics(&impl, "Myip", "metric.one", "Описание метрики один.", "metric.two", "Описание метрики два.")

/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. Определите функцию main(), которая создаст новый экземпляр обработчика плагина, назначит его для использования плагином для журналирования, а затем выполнит обработчик плагина.

Определение функции main() является обязательным.

/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()))
           }
       }

Часть 2: Создание плагина

В этом разделе вы узнаете, как скомпилировать плагин.

  1. Чтобы создать файлы Go для обработки зависимостей и загрузить зависимости, автоматически выполните этот сценарий bash из CLI.
go mod init myip
       GOPROXY=direct go get git.zabbix.com/ap/plugin-support/plugin@branchname
       go mod tidy
       go build

Обязательно укажите правильное имя ветки, т.е. замените branchname (см. строку 2) на одно из следующих:

  • release/* - для ветки стабильного выпуска, где "*" — это версия выпуска (т.е. 7.0)
  • master - для главной ветки
  • <commit hash> - для конкретной версии коммита (используйте конкретный хеш коммита)

Вывод должен быть похож на этот:

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. Создайте исполняемый файл myip для загружаемого плагина.

  2. Укажите путь к файлу конфигурации плагина в параметре Plugins.Myip.System.Path файла конфигурации Zabbix агента 2.

Имя плагина в имени параметра конфигурации (Myip в этом руководстве) должно совпадать с именем плагина, определенным в функции plugin.RegisterMetrics().

echo 'Plugins.Myip.System.Path=/usr/local/zabbix/go/plugins/myip/myip' > /etc/zabbix_agent2.d/plugins.d/myip.conf
  1. Проверьте метрику:
zabbix_agent2 -t myip

Ответ должен содержать внешний IP-адрес вашего узла сети.

В случае ошибки проверьте, есть ли у пользователя zabbix права доступа к каталогу /usr/local/zabbix/go/plugins/myip.