O czym jest ten artykuł:
Makra w Zabbix są bardzo użytecznym wbudowanym „narzędziem” do ułatwiania sobie konfiguracji i utrzymywania porządku. Temat ten jednak jest na tyle skomplikowany dla początkującego (i nie tylko) użytkownika, że często bywa pomijany.
W tym artykule omówimy teorię makr oraz wyjaśnimy, jak efektywnie ich używać. Nauczymy się również obsługiwać konteksty, a wszystkie aspekty zostaną przedstawione na praktycznych przykładach.
Uwaga – poradnik dotyczy wersji Zabbix 7.0, jednakże duża część opisanych elementów znajdzie zastosowanie we wcześniejszych wersjach. Zaczynamy!
Teoria
Makra to nic innego jak zmienne — posiadają one nazwę oraz przypisaną do nich wartość. Nazwa makra może składać się z dużych liter, cyfr, znaku podkreślenia (“_”) lub kropki (“.”). Zawsze znajduje się w nawiasach klamrowych np. {MAKRO_TEST.1}. Na początku musimy wiedzieć, że istnieją cztery typy makr:
- Makra wbudowane w Zabbix (ang. “built-in macro”),
- Makra wykrywania niskopoziomowego (ang. “macro for low-level discovery, LLD macro”),
- Makra wyrażeń (ang. “expression macro”),
- Makra użytkownika (ang. “user-defined macro”).
W dalszej części postaramy się omówić wszystkie dostępne makra, jednakże w artykule postaramy się skupić głównie na ostatnim typie, czyli makra użytkownika.
Makra wbudowane
Makra wbudowane można poznać po tym, że nazwa nie posiada żadnego przedrostka w nazwie np. {MAKRO}. Jak sama nazwa wskazuje, są to predefiniowane zmienne, które Zabbix potrafi zamienić na odpowiednie wartości np. {HOST.NAME} zostanie zamienione na nazwę hosta, {DATE} - na aktualną datę itd. Makra te są podstawowym typem zmiennych używanych w Zabbix i są wspierane już od jego pierwszych wersji.
Pełną listę makr wbudowanych można znaleźć w >dokumentacji. Warto przyjrzeć się od razu, gdzie możemy użyć dane makro (kolumna “Supported in”) oraz ich opis (kolumna “Description”). Jeżeli nie mamy najnowszej wersji Zabbix, należy zmienić wybraną wersję dokumentacji na odpowiednią i wtedy sprawdzić interesujące nas makro (mogą wystąpić różnice pomiędzy wersjami).
Jednym z ciekawych przykładów użycia makr wbudowanych są domyślne szkice do wysyłki maili. Wystarczy wejść w zakładkę “Administration” -> “Media Types”, następnie wybrać z listy „Email”, potem „Message templates” i wybrać pierwszy szkic o typie „Problem” i kliknąć „Edit”:
Rysunek 1: Domyślny szkic wiadomości o problemie dla wysyłki maili.
Powyżej można zauważyć dużo wbudowanych makr, które podczas wysyłki maila zostaną zamienione na odpowiednie wartości np. {EVENT.NAME} zostanie zamienione na nazwę problemu itp.:
Rysunek 2: Przykład odebranego maila z problemami.
Przy pracy z makrami wbudowanymi lub przeglądając dokumentację, można zauważyć, że niektóre posiadają tzw. indeksy np. {HOST.NAME1}, {HOST.NAME2} itp. Najlepiej wyjaśnić to na przykładzie.
Wyobraźmy sobie, że posiadamy trigger, który wyzwala się przy problemach z oprogramowaniem Apache na serwerach o nazwach “WWW1” i “WWW2” (warto zauważyć, że składa się z 2 wyrażeń logicznych rozdzielonych operacją “and”, czyli logicznym „i”):
Rysunek 3: Przykładowy wyzwalacz.
Teraz przy problemach na obydwu serwerach Apache pokaże się trigger o następującej nazwie:
Nie działa serwer apache na WWW1 oraz WWW1
Wiadomość ta może być myląca, ponieważ Zabbix pobrał nazwę hosta tylko z pierwszego wyrażenia logicznego (gdy nie podamy numeru indeksu, Zabbix zawsze pobiera wartość z pierwszego elementu, w tym przypadku — wyrażenia). Dlatego musimy wskazać, z których wyrażeń logicznych pobieramy nazwę hosta (ważna jest tutaj ich kolejność). Dlatego gdy ustawimy trigger tak jak na „Rysunek 4”, otrzymamy następujący komunikat:
Rysunek 4: Przykładowy wyzwalacz – makra z indeksami.
Makra wykrywania niskopoziomowego
Makra te są wykorzystywane podczas wykrywania niskopoziomowego np. przy wykrywaniu systemów plików albo kart sieciowych. Charakteryzują się znakiem “#” na początku nazwy np. {#MAKRO}. Makra te (oraz ogólnie reguły wykrywania niskopoziomowego) są wspierane od wersji 2.0.
Na „Rysunek 5” można zauważyć makra wykrywania niskopoziomowego dla systemów plików — pod makro {#FSNAME} będzie wstawiana nazwa każdego wykrytego systemu plików (a skąd ta nazwa się bierze to już temat na inny artykuł).
Rysunek 5: Przedstawienie makra wykrywania niskopoziomowego.
Makra wyrażeń
Makra wyrażeń służą do wyliczenia i pokazania nam jakieś wartości np. wartości download/upload pomiędzy dwoma hostami na mapie. Makra te pojawiły się dopiero od wersji 6.0. Nazwy tych makr zawsze zaczynają się od znaku “?” np. {?MAKRO}, a dokładniej to:
{?funkcja(/HOST/KLUCZ,parametry)}
Jako przykład spróbujmy wyświetlić stan usługi Apache na mapie, gdzie posiadamy połączone hosty „WWW1” oraz „WWW2”. W edycji połączenia hostów dodajemy następujący wpis:
Rysunek 6: Użycie makr wyrażeń w elemencie mapy.
W tym przypadku używamy funkcji „last” dla hostów „WWW1” oraz „WWW2” dla klucza „apache.status” (do zamierzonego efektu nie musimy używać parametrów funkcji, więc zostały pominięte).
Teraz gdy wyświetlimy mapę, na połączeniu będziemy mogli zauważyć, że makra wyrażeń zostały zastąpione aktualnymi wartościami odpowiadającymi za status usługi (w tym przypadku – wartości 0, które odpowiadają za niedostępność):
Rysunek 7: Zmiana makr wyrażeń na wartości pomiędzy hostami na mapie.
Makra użytkownika
Dopiero makra użytkownika ukazują prawdziwy potencjał tego rozwiązania. Są to zmienne tworzone przez użytkownika i mogą być wykorzystywane w >wielu miejscach. Nazwy tych makr zawsze zaczynają się od znaku “$” np. {$MAKRO}. Makra użytkownika pojawiły się już od wersji 1.8.
Makra użytkownika można podzielić na 3 rodzaje:
- Globalne — makro, które działa w całym obszarze konfiguracji środowiska Zabbix; ustawia się je poprzez wejście w zakładkę “Administration” -> “Macros”; na „Rysunek 8” można zauważyć domyślne makro globalne ustawiające community dla SNMP na wartość “public”,
Rysunek 8: Konfiguracja makr globalnych.
- Szablonu — makra, które są ustawiane w template i działają w obrębie tego szablonu i wszystkich hostów, które są do niego podłączone; przykładowe makra przedstawia ‘Rysunek 9”,
Rysunek 9: Konfiguracja makr szablonu.
- Hosta — makra, które są ustawione na samym hoście i działają tylko w jego obrębie; przykładowe makra dla hosta przedstawia „Rysunek 10”.
Rysunek 10: Konfiguracja makr hosta.
Najczęstszymi wątpliwościami podczas pracy z makrami użytkownika jest sytuacja, gdy kilka makr użytkownika posiada taką samą nazwę. Patrząc na „Rysunek 9” oraz „Rysunek 10” można zauważyć, że zarówno w szablonie “Template OS Linux”, jak i na samym hoście jest makro {$CPU.UTIL.CRIT}. Następuje wtedy pytanie: “Które makro jest brane jako pierwsze?”. W dużym uproszczeniu kolejność jest następująca:
- na początku brana jest wartość makra hosta,
- jeżeli go nie ma, uwzględniana jest wartość makra szablonu,
- gdy szablon nie posiada makra, na końcu jest sprawdzane makro globalne.
Kolejność może budzić wiele wątpliwości, dlatego deweloperzy Zabbix wprowadzili listę “makr dziedziczonych” (przycisk ten pojawił się od wersji 3.0). W naszym przykładzie wystarczy podczas wyświetlania makr na hoście kliknąć na przycisk “Inherited and host macros”, aby zobaczyć:
- Makro hosta (1°),
- Niezmienione makro szablonu (2°),
- Makro szablonu, które zostało zastąpione przez makro hosta (3°),
- Makro globalne (4°).
Rysunek 11: Widok makr dziedziczonych.
Konteksty
By wyjaśnić pojęcie kontekstów, wyobraźmy sobie następującą sytuację — posiadamy monitoring routera, gdzie posiadamy 4 interfejsy sieciowe (eth0, eth1, eth2 oraz eth3) i monitoruje ruch przychodzący (w % zajętości; 0% - brak ruchu w danym kierunku, 100% - wysycenie łącza). Chcemy być poinformowani, gdy ruchu przychodzącego będzie za dużo.
Przyjmujemy również, że ustawiliśmy makro użytkownika w wyzwalaczu o nazwie {$NET_IN} i wartości 80 (należy pamiętać, że to jest wartość procentowa). Dzięki temu będziemy mogli zmienić wartość, od której uruchomi się alarm w dowolnym momencie. Przykład takiego triggera dla interfejsu eth0 pokazuje „Rysunek 12”.
Rysunek 12: Konfiguracja wyzwalacza dla ruchu przychodzącego.
Rysunek 13: Makro użytkownika dla ruchu przychodzącego.
Załóżmy, że do ostatniego portu (eth3) podpięty jest serwer, który służy do backupu innych serwerów, przez co wysycenie łącza jest stałe i wynosi 90%. W powyższej sytuacji trigger dla eth3 będzie cały czas włączony (jest powyżej ustawionej przez nas wartości 80%). Pierwszą myślą jest zmienienie makra {$NET_IN} na powiedzmy 95% - ale wtedy podniesiemy próg również i dla innych portów, co w naszym przypadku jest niedopuszczalne. W takiej sytuacji pomocne będą konteksty.
Używanie makr użytkowników z kontekstami jest bardzo przydatne w sytuacji, gdy mamy użyte to samo makro w kilku miejscach w obrębie hosta czy szablonu. W szczególności użyteczne są przy użyciu wykrywania niskopoziomowego. Dzięki nim wartość makra użytkownika może być zależna od wykrytych elementów. Makra z kontekstami pojawiły się w wersji 3.2. Składnia makra z kontekstem wygląda następująco:
{$MAKRO:kontekst}
Warto dodać, że sam kontekst może być w cudzysłowie, lecz nie jest to wymagane. Wtedy kontekst będzie traktowany w trochę inny sposób (szerzej został opisany >pod tym linkiem).
{$MAKRO:”kontekst”}
Dodatkowo nic nie stoi na przeszkodzie, by podczas tworzenia reguł i prototypów wykrywania niskopoziomowego używać makr użytkownika razem z makrami wykrywania niskopoziomowego. Wtedy nazwy te podczas uruchomienia reguły zostaną zmienione na odpowiednie wartości użyte w makrze LLD.
{$MAKRO:”{#MAKRO}”}
Przykładowo – przyjmijmy, że w fizycznym serwerze posiadamy 2 dyski fizyczne oznaczone jako „SDA” oraz „SDB”. W regule LLD dla wykrywania dysków fizycznych nazwy te używają makro {#DISK_NAME}, natomiast w prototypie wyzwalacza użyto makro z kontekstem: {$DISK_FAIL:”{#DISK_NAME}”}. Podczas wykrywania elementów makro to zostanie zamienione na {$DISK_FAIL:”SDA”} oraz {$DISK_FAIL:”SDB”}.
Wróćmy do naszego przykładu - w tym przypadku różnymi kontekstami (lub elementami) są porty routera, a dokładniej ich nazwy (od eth0 do eth3). Zmieńmy wyrażenia regularne wyzwalaczy dla wszystkich interfejsów, by używały makra z kontekstem. Przykład dla wspomnianego wcześniej eth3:
Rysunek 14: Konfiguracja wyzwalacza — makro z kontekstem.
W wyrażeniu wyzwalacza pojawiło się makro z kontekstem: {$NET_IN:"eth3"}. Teraz możemy teraz ustawić inną wartość progu dla interfejsu sieciowego eth3:
Rysunek 15: Przykład makra z kontekstem w konfiguracji hosta.
Na szczęście nie musimy dodawać wszystkich makr z kontekstem, ponieważ gdy Zabbix ich nie wykryje (np. {$NET_IN:”eth0”}), to wtedy będzie szukał makra bez kontekstu ({$NET_IN}). Dlatego w naszym przykładzie (Rysunek 15) dla eth0, eth1 i eth2 wartość makra będzie wynosiła 80, a dla eth3 - 95.
Załóżmy teraz, że nasza infrastruktura się rozrasta i w naszej sieci pojawił się nowy router, który posiada 24 porty ethernetowe (nazwy od eth0 do eth23) oraz 4 porty światłowodowe (nazwane sfp0 do sfp3). Dostaliśmy zadanie zmiany dla wszystkich portów ethernetowych wartość progu {$NET_IN} na 70%, natomiast dla portów światłowodowych ma pozostać wartość domyślna – 80%.
Czy teraz jesteśmy zmuszeni do utworzenia 24 makr użytkownika z kontekstami dla każdego portu? Na szczęście odpowiedź brzmi przecząco, ponieważ deweloperzy Zabbix dodali możliwość użycia wyrażenia regularnego dla kontekstu (od wersji 5.0.2). Składnia wygląda następująco:
{$MAKRO:regex:”wyrażenie regularne”}
Środkowy zapis („:regex:”) jest stały – wtedy Zabbix wie, że zamiast zwykłego teksu użyliśmy wyrażenia regularnego.
W naszym przykładzie możemy użyć następującego makra:
{$NET_IN:regex:”^eth.*”}
Spowoduje to użycie tego makra dla każdego interfejsu, zaczynającego się od znaków „eth”. Wtedy makra hosta wyglądałyby następująco:
Rysunek 16: Przykład makra z użyciem wyrażenia regularnego w kontekście.
Praktyka
Czas na praktyczne wykorzystanie tej wiedzy. Załóżmy, że na serwerze Zabbix posiadamy cztery systemy plików:
- “/” - wielkość 50 GB,
- “/mnt/disk1” - wielkość 10 GB,
- “/mnt/disk2” - wielkość 10 GB,
- “/backup” - wielkość 20 GB.
Rysunek 17: Przykładowy wyzwalacz dla zajętości systemu plików.
Zauważyliśmy, że ktoś podpiął do hosta stary szablon dla Linuxa (“Template Linux OLD”), który dla każdego systemu plików tworzy następujący wyzwalacz:
Po pewnym czasie zauważamy następujące wyzwalacze:
Rysunek 18: Przykładowe alarmy zajętości systemów plików.
Jako zaawansowani użytkownicy Zabbixa zauważamy dwa dość poważne problemy:
- próg alarmu dla wszystkich hostów z tym szablonem jest sztywny i równy 20(%),
- Nie możemy tworzyć różnych progów dla różnych systemów plików; jak wiadomo, że procent procentowi nierówny — kiedy mamy poniżej 20% na systemie, który posiada 10TB, raczej jesteśmy spokojni o miejsce; jednak poniżej 20% na systemie plików o pojemności 10MB sygnalizuje dość poważny problem.
Chcąc naprawić w/w problemy, powinniśmy wykorzystać makra użytkownika wraz z kontekstem (w tym przypadku kontekstem będzie nazwa systemu plików). Dlatego musimy stworzyć nowe makro {$DISK_SPACE:”{#FSNAME}”}, gdzie {#FSNAME} to oczywiście makro wykrywania niskopoziomowego.
Na początku dodajmy makro na poziomie szablonu. Dzięki temu makro to pojawi się na każdym hoście podpiętym do tej template. Oczywiście w razie potrzeby będziemy mogli potem je nadpisać na poziomie hosta. Znajdujemy więc interesującą nas template i wchodzimy w jej konfiguracje, a następnie w zakładkę „Macros”. Klikamy napis „Add” i dodajemy nowe makro zgodnie z „Rysunek 19”. Na końcu pamiętaj o zapisaniu zmian, wciskając przycisk „Update”.
Rysunek 19: „Domyślne” makro na poziomie szablonu.
Zauważ, że dodajemy takie „domyślne” makro, które nie posiada kontekstu. Po pierwsze – zakładamy, że podpięte hosty mogą mieć różne punkty montowań niż te, które wyszczególniliśmy wyżej. Po drugie – pamiętajmy, że gdy Zabbix nie wykryje kontekstu, będzie brał wartość z makra bez niego – dzięki temu wszystkie wykryte przez nas systemy plików będą miały wartość 20(procent).
Następnie zmieńmy nazwę wyzwalacza oraz wyrażenie logiczne, by używały nowo wykreowane makro. W tym celu znowu wchodzimy w konfigurację template -> „Discovery rules” -> odnajdujemy regułę do wykrywania systemów plików -> „Trigger prototypes”:
Rysunek 20: Zmiana wyzwalacza – używanie makr z kontekstami.
Powyższy wyzwalacz można traktować następująco: wywołaj alarm, jeżeli procentowa wartość wolnego miejsca na systemie plików jest mniejsza niż wartość w makrze {$DISK_SPACE:”{#FSNAME}”} (w zależności od kontekstu). Jeżeli go nie znajdzie – użyje makro bez kontekstu (w tym przykładzie – nasze przyjęte 20 procent). Ta sama sytuacja będzie wykorzystana w nazwie triggera.
Po ponownym wykonaniu reguły LLD z poziomu hosta możemy zobaczyć, że makro wykrywania niskopoziomowego zostało zamienione na nazwy systemów plików:
Rysunek 21: Nazwy systemów plików w makrach z kontekstami.
Przy ponownym wykryciu małej dostępnej ilości wolnego miejsca będziemy mogli zauważyć, że niczym nie różni się od stanu początkowego – dalej będzie wyświetlał się problem z miejscem poniżej 20%. Jednakże w tym momencie możemy zmienić ten parametr na poziomie hosta, zmieniając nasze domyślne makro.
Załóżmy teraz następującą sytuację:
- dla punktu /backup chcemy wyświetlić alarm dopiero poniżej 5%,
- dla wszystkich systemów plików z początkiem /mnt (w tym /mnt/disk1 oraz /mnt/disk2) powinniśmy dać próg alarmu na poziomie 10%; zakładamy, że mogą pojawić się kolejne dyski (np. /mnt/disk3, /mnt/external_backup itp.), które powinny mieć taki sam próg,
- wszystkie inne punkty montowań (w tym – root „/”) powinny mieć wartość 25%.
Zajmijmy się na razie ostatnim punktem, czyli zmianą dla wszystkich „innych” punktów montowań. W tym celu wchodzimy w konfigurację hosta, następnie w zakładkę „Macros” a następnie w “Inherited and host macros”. Powinno ukazać nam się nasze makro „domyślne” z wartością 20. Chcemy zmienić je na 25, więc klikamy w napis „Change” i wpisujemy poprawną wartość. Pamiętajmy po zmianach kliknąć „Update”!
Rysunek 22: Umożliwienie zmiany „domyślnego” makro.
Rysunek 23: Zmiana „domyślnego” makro.
Teraz zajmijmy się progiem dla punktu /backup. Jeszcze raz wchodzimy w konfigurację hosta -> „Macros”. Możemy zauważyć, że teraz „domyślne” makro jest również widoczne z poziomu „Host macros”, ponieważ właśnie nadpisaliśmy te z poziomu szablonu do poziomu hosta. Jednakże makra z kontekstami nie dodają się same, więc musimy stworzyć własne. W tym celu klikamy na napis „Add” i dodajemy nowe makro {$DISK_SPACE:”/backup”} z wartością 5:
Rysunek 24: Dodanie makra z kontekstem dla punktu /backup.
Na końcu chcemy dodać makro dla wszystkich punktów zaczynających się od katalogu /mnt. Klikamy jeszcze raz napis „Add” i dodajemy makro z wyrażeniem logicznym {$DISK_SPACE:regex:”^/mnt/.*”} (wyrażenie odpowiada wszystkim punktom, których nazwa zaczyna się od „/mnt/”) i wartością 10. Pamiętamy, by na końcu zatwierdzić wszystko przyciskiem „Update”:
Rysunek 25: Dodanie makra z wyrażeniem regularnym dla punktów „/mnt/”.
Po odczekaniu, aż wykrywanie niskopoziomowe dysków się odświeży i ponownym wykryciu problemów na dysku, na ekranie powinny ukazać się następujące problemy:
Rysunek 26: Ulepszone alarmy.
Pamiętaj – jest to tylko przykład. Domyślny szablon dla systemu Linux (w szczególności – w wersji 7.0) posiada już reguły LLD dla systemu plików używające makra z kontekstami!
Podsumowanie
Jeżeli chcesz utrzymać porządek w konfiguracji środowiska Zabbix, powinieneś zacząć używać makr. Początkowo wydają się one trudne, jednak później zauważysz, że nie możesz bez nich żyć.
Na koniec, jako bonus, kilka zasad “best practice”:
- Używaj jednoznacznych nazw — makro {$CPU} nic nie mówi, nie mówiąc już o {$MAKRO_TESTOWE} czy {$123}.
- Załóż, że zawsze dodajesz opis danego makra w polu „Description”, gdyż przy większej ilości makr użytkowników potrafią być mylące, a pamięć zawodna,
- Gdy używasz jakiegoś makra na szablonie, zawsze dodawaj je do templatki (analogicznie do „Rysunek 23”); unikniesz sytuacji, że jakieś makro nie posiada wartości, a zawsze będziesz mógł je nadpisać na hoście,
- Ogranicz używanie makr globalnych do minimum; najlepiej używaj ich tylko wtedy, gdy potrzebujesz makro w wielu lokalizacjach (np. w kilku szablonach),
- Przy konfiguracji wykrywania niskopoziomowego i używaniu makr użytkowników w prototypach, w większości przypadków od razu załóż, że będziesz używać ich razem z kontekstami,
- Przy prezentowaniu danych przemyśl użycie funkcji formatujących ich wyświetlanie; np. dla makra {TIME} możemy podać dokładnie, jak powinna być sformatowana aktualna data (zamiast domyślnego „HH:MM:SS”) lub w makrach wyrażeń możemy zaokrąglić wynik do np. 2 miejsc po przecinku; więcej na temat funkcji formatujących możesz przeczytać >w dokumentacji.
- Jeżeli w którymś miejscu potrzebujesz użyć takich zmiennych, jak login użytkownika lub hasło, przemyśl użycie makr zamiast bezpośrednich wartości; będziesz mógł je zmieniać bez problemu w zależności od hosta. Dodatkowo – w polach typu hasło, token lub klucz przemyśl użycie makr typu „secret” – wtedy z poziomu frontendu nie będziemy w stanie wyciągnąć te dane i zapobiegniemy potencjalnemu wyciekowi danych. Więcej na ich temat możesz przeczytać >w dokumentacji.
Rysunek 27: Makra użytkownika typu „secret”.
I na koniec pamiętaj — wszystko z umiarem! Makra nie muszą znaleźć się w każdym miejscu twojej konfiguracji, natomiast one nie są „lekiem na każde zło”. Ale dzięki nim możemy tworzyć bardziej elastyczny i dostosowany pod nas monitoring.
Podziel się treścią: