Tworzenie wtyczki
Ta strona jest przeznaczona dla osób zainteresowanych opracowaniem własnej wtyczki (niezależnego modułu zbierającego dane) dla Zabbix agent 2.
Niestandardowa wtyczka rozszerza funkcjonalność Zabbix agent 2 poza dostarczane wbudowane wtyczki i wtyczki ładowalne.
Każda wtyczka jest pakietem Go, który definiuje strukturę i implementuje jeden lub kilka interfejsów (Exporter, Configurator, Runner). Więcej informacji można znaleźć w sekcjach Interfejsy wtyczek i Diagram połączeń.
Ten przewodnik pomoże Ci utworzyć niestandardową wtyczkę ładowalną.
Dodatkowe wskazówki można znaleźć również w repozytoriach:
Co utworzysz
To jest samouczek krok po kroku dotyczący tworzenia prostego ładowalnego pluginu o nazwie MyIP.
Ten plugin zaimplementuje pojedynczy klucz pozycji (myip), zwracający zewnętrzny adres IP hosta agenta Zabbix.
Krok 1: Konfiguracja
- Wtyczka jest standardowym modułem Go.
Zacznij od zainicjowania pliku
go.modw katalogu wtyczki, aby śledzić zależności wtyczki:
cd path/to/plugins/myip # Przejdź do katalogu swojej wtyczki
go mod init myip
- Zainstaluj obowiązkową zależność Zabbix Go SDK (
golang.zabbix.com/sdk):
go get golang.zabbix.com/sdk@$LATEST_COMMIT_HASH
Zastąp $LATEST_COMMIT_HASH najnowszym hashem commita HEAD z repozytorium golang.zabbix.com/sdk w odpowiedniej gałęzi wydania.
Na przykład:
go get golang.zabbix.com/sdk@af85407
Pamiętaj, że wersjonowanie golang.zabbix.com/sdk nie jest obecnie obsługiwane, ale może się to zmienić w przyszłości.
Dodatkowe zależności można instalować w razie potrzeby za pomocą go get.
- Utwórz pusty plik
main.godla kodu źródłowego wtyczki:
touch main.go
Początkowa konfiguracja jest teraz zakończona i wtyczka jest gotowa do dalszego tworzenia.
Krok 2: Struktura wtyczki
Moduł golang.zabbix.com/sdk, zainstalowany w poprzednim kroku, udostępnia niezbędne środowisko do tworzenia wtyczek i zapewnia spójną strukturę wszystkich wtyczek.
- Skonfiguruj podstawowy przepływ wykonywania.
Zacznij od zdefiniowania głównego przepływu wykonywania wtyczki. Dodaj następujący kod do pliku main.go:
package main
func main() {
err := run()
if err != nil {
panic(err)
}
}
func run() error {
return nil
}
Ustanawia to podstawowy przepływ wykonywania wtyczki. Funkcja run będzie później zawierać główną logikę wtyczki.
- Zapoznaj się z interfejsami wtyczki.
Wtyczka Zabbix agent 2 powinna być reprezentowana przez strukturę implementującą interfejsy z pakietu golang.zabbix.com/sdk/plugin:
- Accessor - definiuje podstawowe metody, które muszą implementować wszystkie wtyczki, takie jak ustawianie nazwy wtyczki i obsługa limitów czasu kluczy pozycji.
- Jeden lub więcej z następujących funkcjonalnych interfejsów wtyczki:
- Exporter - wykonuje odpytywanie i zwraca wartość (lub wartości), nic albo błąd; często jest używany razem z interfejsem Collector.
- Collector - zarządza okresowym zbieraniem danych.
- Runner - definiuje procedury uruchamiania i zamykania wtyczki.
- Watcher - umożliwia niezależne odpytywanie metryk z pominięciem wewnętrznego harmonogramu agenta; jest przydatny w monitorowaniu opartym na pułapkach lub zdarzeniach.
- Configurator - definiuje sposób odczytywania i stosowania ustawień konfiguracji wtyczki.
Możesz zaimplementować te interfejsy samodzielnie albo użyć domyślnych implementacji udostępnianych przez Zabbix Go SDK i zmodyfikować je zgodnie z potrzebami. W tym samouczku używane są implementacje domyślne.
- Utwórz strukturę wtyczki.
Teraz zaimportuj pakiet plugin i utwórz strukturę myIP, która osadza strukturę plugin.Base:
import "golang.zabbix.com/sdk/plugin"
type myIP struct {
plugin.Base
}
Struktura myIP obecnie spełnia interfejs Accessor. Metoda implementująca jeden z funkcjonalnych interfejsów wtyczki, Exporter, zostanie dodana w dalszej części samouczka.
Krok 3: Zdefiniuj klucze pozycji
Twoja wtyczka potrzebuje kluczy pozycji do zbierania danych i przekazywania ich do serwera Zabbix lub proxy.
- Zaimportuj pakiet errs do obsługi błędów:
import "golang.zabbix.com/sdk/errs"
- Zarejestruj klucze pozycji za pomocą funkcji
plugin.RegisterMetrics()wewnątrz funkcjirun():
func run() error {
p := &myIP{}
// Register the `myip` item key.
err := plugin.RegisterMetrics(
p,
"MyIP", // Plugin name
"myip", // Item key name
"Returns the host's IP address.", // Item key description
)
if err != nil {
return errs.Wrap(err, "failed to register metrics")
}
return nil
}
Aby zarejestrować kilka kluczy pozycji, powtórz parametry nazwa metryki i opis dla każdej metryki.
Na przykład:
plugin.RegisterMetrics(&impl, "Myip", "metric.one", "Metric one description.", "metric.two", "Metric two description.")
Krok 4: Skonfiguruj handler
Handler ułatwia komunikację między agent a wtyczką.
- Zaimportuj pakiet container:
import "golang.zabbix.com/sdk/plugin/container"
- W funkcji
run()dodaj kod tworzący i konfigurujący handler:
func run() error {
p := &myIP{}
// Register the `myip` item key.
err := plugin.RegisterMetrics(
p,
"MyIP", // Plugin name
"myip", // Item key name
"Returns the host's IP address.", // Item key description
)
if err != nil {
return errs.Wrap(err, "failed to register metrics")
}
// Create a new handler.
h, err := container.NewHandler("MyIP") // Plugin name
if err != nil {
return errs.Wrap(err, "failed to create new handler")
}
// Setup logging to forward logs from the plugin to the agent.
// Available via p.Logger.Infof, p.Logger.Debugf, etc.
p.Logger = h
// Start plugin execution.
// Blocks until a termination request is received from the agent.
err = h.Execute()
if err != nil {
return errs.Wrap(err, "failed to execute plugin handler")
}
return nil
}
Krok 5: Implementacja zbierania danych
Zbieranie danych odbywa się za pośrednictwem interfejsu Exporter, który opisuje metodę Export:
func Export(
key string, // Klucz pozycji do zebrania.
params []string, // Argumenty przekazane do klucza pozycji (`myip[arg1, arg2]`).
context ContextProvider // Metadane dotyczące zbierania danych klucza pozycji.
) (any, error)
- Zaimportuj wymagane pakiety do żądań HTTP i odczytu odpowiedzi:
import (
"io"
"net/http"
)
- Zaimplementuj metodę
Exportdla strukturymyIP:
func (p *myIP) Export(
key string, params []string, context plugin.ContextProvider,
) (any, error) {
// Plugin może używać różnej logiki zbierania danych w zależności od parametru `key`.
// Ta implementacja jedynie sprawdza, czy podany `key` jest obsługiwany.
if key != "myip" {
return nil, errs.Errorf("unknown item key %q", key)
}
// Log zostanie przekazany do logu agent 2.
p.Infof(
"received request to handle %q key with %d parameters",
key,
len(params),
)
// Zbierz dane i zwróć je.
resp, err := http.Get("https://api.ipify.org")
if err != nil {
return nil, errs.Wrap(err, "failed to get IP address")
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, errs.Wrap(err, "failed to read response body")
}
return string(body), nil
}
Krok 6: Zbuduj i skonfiguruj plugin
- Aby zbudować plugin, uruchom:
go mod tidy
go build
Powinno to utworzyć plik wykonywalny myip w bieżącym katalogu.
- Skonfiguruj agent 2 Zabbixa, aby używał pluginu:
echo "Plugins.MyIP.System.Path=$PATH_TO_THE_MYIP_PLUGIN_EXECUTABLE" > /etc/zabbix/zabbix_agent2.d/plugins.d/myip.conf
Zastąp $PATH_TO_THE_MYIP_PLUGIN_EXECUTABLE ścieżką do myip utworzonego w kroku 5.
Nazwa pluginu w nazwie parametru konfiguracji (MyIP w tym samouczku) musi być zgodna z nazwą pluginu zdefiniowaną w funkcji plugin.RegisterMetrics().
- Aby przetestować plugin i jego pozycję
myip, uruchom:
zabbix_agent2 -c /etc/zabbix/zabbix_agent2.conf -t myip
Wynik powinien zawierać zewnętrzny adres IP twojego hosta i wyglądać podobnie do tego:
myip [s|192.0.2.1]
W ten sposób utworzyłeś prosty, ładowalny plugin dla agent 2 Zabbixa. Gratulacje!
Pełny kod źródłowy
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{}
// Zarejestruj klucz pozycji `myip`.
err := plugin.RegisterMetrics(
p,
"MyIP", // Nazwa wtyczki
"myip", // Nazwa klucza pozycji
"Zwraca adres IP hosta.", // Opis klucza pozycji
)
if err != nil {
return errs.Wrap(err, "failed to register metrics")
}
// Utwórz nowy program obsługi.
h, err := container.NewHandler("MyIP") // Nazwa wtyczki
if err != nil {
return errs.Wrap(err, "failed to create new handler")
}
// Skonfiguruj logowanie, aby przekazywać logi z wtyczki do agenta.
// Dostępne przez p.Logger.Infof, p.Logger.Debugf itd.
p.Logger = h
// Uruchom wykonywanie wtyczki.
// Blokuje do momentu otrzymania żądania zakończenia od agenta.
err = h.Execute()
if err != nil {
return errs.Wrap(err, "failed to execute plugin handler")
}
return nil
}
func (p *myIP) Export(
key string, params []string, context plugin.ContextProvider,
) (any, error) {
// Wtyczka może używać różnej logiki zbierania danych w zależności od parametru `key`.
// Ta implementacja jedynie sprawdza, czy podany `key` jest obsługiwany.
if key != "myip" {
return nil, errs.Errorf("unknown item key %q", key)
}
// Log zostanie przekazany do logu agenta 2.
p.Infof(
"received request to handle %q key with %d parameters",
key,
len(params),
)
// Zbierz dane i zwróć je.
resp, err := http.Get("https://api.ipify.org")
if err != nil {
return nil, errs.Wrap(err, "failed to get IP address")
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, errs.Wrap(err, "failed to read response body")
}
return string(body), nil
}