Ocak 8 2026

Zabbix LLD ile Dinamik Altyapı İzleme: SRE El Kitabı

Modern karmaşık altyapılarda monitoring süreçlerini otomatize etmek artık bir lüks değil; zabbix üzerinde lld (Low-Level Discovery) kullanarak dinamik sunucu ve servis keşfi yapmak ise bu otomasyon sürecinin tam kalbinde yer alıyor. YAML dosyaları arasında kaybolduğumuz, Kubernetes cluster’larının her saniye pod döküp topladığı bir dünyada, kimsenin Zabbix arayüzüne girip elle host ekleyecek, yeni bir disk mount edildiğinde onun için manuel item tanımlayacak vakti yok. Eğer hala “Yeni makine geldi, IP’sini Zabbix’e ekleyelim” diyorsanız, bu makale operasyonel yükünüzü sıfıra indirmek için yazıldı.

Neden Standart Discovery Değil de LLD?

Zabbix kullanan ekiplerin sıklıkla düştüğü ilk hata, Network Discovery ile Low-Level Discovery (LLD) kavramlarını karıştırmaktır. Network Discovery, belirli IP bloklarını tarayıp “Burada bir cihaz var, işletim sistemi de Linux” der ve host’u sisteme ekler. Ancak o host’un içine girdikten sonra işler değişir.

LLD ise bir host’un mikroskobik anatomisini dinamik olarak çıkartır. Sunucuda o an çalışan Docker container’larını, mount edilmiş disk partition’larını, aktif dinlenen TCP portlarını veya dinamik olarak ayağa kalkan systemd servislerini otomatik olarak tespit eder. LLD’nin arkasındaki sihirli güç JSON formatıdır. Zabbix Agent veya bir external script, Zabbix Server’a standardize edilmiş bir JSON döndürür; Server ise bu JSON’ı parse ederek dinamik prototiplerden gerçek Item, Trigger ve Graph’lar üretir.

Uygulama Senaryosu: Dinamik Mikroservis Port Keşfi

Geliştirme ekibinin her hafta yeni bir mikroservis deploy ettiği, her servisin rastgele (veya belirli bir pattern’e sahip) portlardan ayağa kalktığı bir senaryoyu ele alalım. Amacımız: Sunucuda dinlenen dynamic portları keşfetmek, bunları izlemek ve port kapandığında alarm üretmek.

Adım 1: Custom LLD Scripti Yazımı

Öncelikle hedef sunucuda çalışacak ve dinlenen portları Zabbix’in anlayacağı LLD formatında (JSON) döndürecek bir Bash scriptine ihtiyacımız var. Zabbix 5.0 ve üzeri sürümler artık flat JSON formatını da destekliyor, ancak biz geriye dönük uyumluluk ve standart olması açısından klasik LLD macro array formatını kullanacağız.

Aşağıdaki scripti hedef sunucuda /etc/zabbix/scripts/discover_ports.sh yoluna kaydedelim:

#!/bin/bash

# Dinlenmekte olan 8000-9000 arasındaki portları bulalım (mikroservis port aralığı)
PORTS=$(netstat -tlnp | awk '{print $4}' | grep -o '[0-9]*$' | sort -u | awk '$1>=8000 && $1<=9000')

echo "{"
echo "  \"data\": ["

FIRST=1
for PORT in $PORTS; do
    # Servis adını systemd veya prosesten çekmeye çalışalım
    SERVICE_NAME=$(ss -tlnp | grep ":$PORT " | awk -F'pid=' '{print $2}' | cut -d, -f1 | tr -d '"')
    if [ -z "$SERVICE_NAME" ]; then
        SERVICE_NAME="unknown-service"
    fi

    if [ $FIRST -ne 1 ]; then
        echo ","
    fi
    echo "    {"
    echo "      \"{#MICROSERVICE_PORT}\": \"$PORT\","
    echo "      \"{#MICROSERVICE_NAME}\": \"$SERVICE_NAME\""
    echo "    }"
    FIRST=0
done

echo "  ]"
echo "}"

Bu scriptin çıktısı tam olarak aşağıdaki gibi bir JSON olmalıdır. Zabbix LLD motoru, anahtar kelime olarak süslü parantez ve diyez ile başlayan makroları ({#MACRO}) arar:

{
  "data": [
    {
      "{#MICROSERVICE_PORT}": "8081",
      "{#MICROSERVICE_NAME}": "auth-service"
    },
    {
      "{#MICROSERVICE_PORT}": "8085",
      "{#MICROSERVICE_NAME}": "payment-service"
    }
  ]
}

Adım 2: UserParameter Tanımlama

Zabbix Agent’ın bu scripti çalıştırıp çıktıyı sunucuya gönderebilmesi için yetkilendirilmesi gerekir. /etc/zabbix/zabbix_agentd.d/userparameter_services.conf dosyasını oluşturup şu satırı ekliyoruz:

UserParameter=custom.microservice.discovery,sudo /etc/zabbix/scripts/discover_ports.sh

Burada kritik bir detay var: Script netstat ve ss komutlarını kullandığı için proses isimlerini okurken root yetkisine ihtiyaç duyabilir. Bu yüzden /etc/sudoers dosyasına zabbix kullanıcısı için şifresiz çalıştırma izni eklemeyi unutmayın:

zabbix ALL=(ALL) NOPASSWD: /etc/zabbix/scripts/discover_ports.sh

Konfigürasyonu yaptıktan sonra agent servisini restart ediyoruz:

systemctl restart zabbix-agent

Zabbix Arayüzünde Template ve LLD Yapılandırması

Artık altyapıyı hazırladığımıza göre, Zabbix Server tarafında bu veriyi işleyecek kuralları tanımlayabiliriz.

Discovery Rule Oluşturma

  1. Zabbix Web UI’da Configuration > Templates sekmesine gidin ve yeni bir template oluşturun (Örn: Template App Microservices Dynamic).
  2. Oluşturduğunuz template’in içindeki Discovery rules sekmesine tıklayın ve Create discovery rule butonuna basın.
  3. Name: Microservice Port Discovery
  4. Type: Zabbix agent (veya zabbix agent active – mimarinize göre)
  5. Key: custom.microservice.discovery
  6. Update interval: 1h (Üretim ortamında her dakika keşif yapmak gereksiz yük bindirir, 1 saat veya duruma göre 15 dakika idealdir).

Item Prototiplerini Tanımlama

Discovery Rule oluştuktan sonra, bu kuralın altında Item prototypes sekmesine giriyoruz. Burada tanımlayacağımız her item, keşfedilen her port için otomatik olarak klonlanacak.

Create item prototype diyerek ilk prototipimizi oluşturalım:

  • Name: Service {#MICROSERVICE_NAME} on Port {#MICROSERVICE_PORT} Status
  • Key: net.tcp.service[tcp,,{#MICROSERVICE_PORT}]
  • Type: Simple check (veya Agent üzerinden kontrol etmek için agent key’leri kullanabilirsiniz)
  • Type of information: Numeric (unsigned)

Burada kritik nokta, Key alanında dinamik makromuz olan {#MICROSERVICE_PORT} ifadesini kullanmış olmamızdır. Zabbix her keşifte bu değeri gerçek port numarasıyla değiştirecektir.

Trigger Prototiplerini Tanımlama

Sadece izlemek yetmez, servis çöktüğünde alarm üretmeliyiz. Aynı Discovery Rule altındaki Trigger prototypes sekmesine gidiyoruz:

  • Name: Microservice {#MICROSERVICE_NAME} on port {#MICROSERVICE_PORT} is DOWN
  • Expression: last(/Template App Microservices Dynamic/net.tcp.service[tcp,,{#MICROSERVICE_PORT}])=0
  • Severity: Average (veya High)

Bu tanım sayesinde, örneğin 8085 portundaki `payment-service` çöktüğünde trigger otomatik olarak evaluate edilecek ve alarm başlığı dinamik olarak çözümlenerek “Microservice payment-service on port 8085 is DOWN” şeklinde Slack/PagerDuty entegrasyonlarınıza düşecektir.

SRE Gözünden LLD Optimizasyonları ve Best Practice’ler

Büyük ölçekli ortamlarda (10.000+ host, 500.000+ item) LLD kullanırken dikkat edilmezse Zabbix Server database’i ve LLD housekeeper süreçleri darboğaza girebilir. Aşağıdaki optimizasyonları mutlaka dikkate alın:

1. Discard Unchanged (Throttling) Kullanın

Keşif scriptiniz her çalıştığında aynı JSON çıktısını üretiyorsa, Zabbix Server’ın her seferinde bu veriyi veritabanına yazıp işlem yapmasına gerek yoktur. Discovery Rule konfigürasyonundaki Preprocessing sekmesine gidin ve Discard unchanged with heartbeat ekleyin. Heartbeat süresini 12h veya 24h yapın. Bu, DB write I/O oranınızı dramatik ölçüde düşürür.

2. Keep Lost Resources Period Ayarı

Bir mikroservis kapatıldığında veya taşındığında, ona ait eski item ve trigger verilerinin ne kadar süre sistemde kalacağını belirleyen parametre LLD rule içindeki Keep lost resources period seçeneğidir. Varsayılan olarak 30 gündür. Dinamik ortamlarda bu değeri 1d (1 gün) veya 12h gibi düşük sürelere çekin. Aksi takdirde, artık var olmayan yüzlerce geçici portun “Unknown” statüsündeki çöpleriyle uğraşırsınız.

3. Filtreleri Doğru Kullanın

Scriptinizden gelen tüm verileri izlemek istemeyebilirsiniz. LLD kuralındaki Filters sekmesini kullanarak sadece belirli pattern’e uyan makroları işleme alabilirsiniz. Örneğin, sadece {#MICROSERVICE_NAME} değeri “prod-” ile başlayanları izlemek için regex filtresi koyabilirsiniz:

{#MICROSERVICE_NAME} matches ^prod-.*

Özet

Zabbix LLD, altyapınızın dinamik yapısına ayak uydurabilen, kendi kendini temizleyen ve sürekli güncel kalan bir monitoring katmanı kurmanın en efektif yoludur. Statik template mantığından çıkıp, veriyi doğrudan kaynaktan (OS, API, Docker socket) çekerek otomatik kural setleri türetmek, SRE ekiplerinin operasyonel yükünü minimize eder. Bir sonraki aşamada bu LLD mekanizmasını Kubernetes API’si ile entegre ederek cluster dışındaki Zabbix cluster’ınızdan pod seviyesinde keşifler tetikleyebilirsiniz.

Category: Genel | LEAVE A COMMENT
Temmuz 26 2024

Zabbix’te LLD ile Dinamik Monitoring Otomasyonu: Custom Script ve Trigger Entegrasyonu

Modern altyapılarda statik konfigürasyon dosyalarıyla veya arayüzden tek tek host ekleyerek hayatta kalmak imkansız. Hele ki her gün onlarca microservice’in, disk partition’ının veya network interface’inin ayağa kalkıp kapandığı dinamik bir Kubernetes ya da bare-metal cluster yönetiyorsanız, manuel izleme (monitoring) tam bir kabusa dönüşür. Bu noktada imdadımıza yetişen en güçlü mekanizmalardan biri, şüphesiz Zabbix LLD (Low-Level Discovery) tabanlı dinamik monitoring otomasyonu mimarisidir.

Bu makalede, teorik tanımları bir kenara bırakıp doğrudan production ortamında çalışan, özelleştirilmiş (custom) bir LLD senaryosunu sıfırdan inşa edeceğiz. Amacımız, host üzerindeki dinamik Docker container’larını otomatik keşfetmek, bunlara ait metrikleri toplamak ve dinamik trigger prototipleri ile akıllı alarmlar üretmek.

Neden Standart Discovery Değil de LLD?

Zabbix’te iki tip keşif mekanizması bulunur: Network Discovery ve Low-Level Discovery (LLD). Network Discovery, ağdaki IP bloklarını tarayıp “Burada yeni bir sunucu var mı?” sorusuna yanıt ararken; LLD, “Bu sunucunun içinde izlemem gereken ve sürekli değişen hangi alt bileşenler var?” sorusunu yanıtlar. Diskler, network arayüzleri, CPU çekirdekleri, veritabanı instance’ları veya Docker container’ları LLD’nin ana hedefidir.

LLD’nin arkasındaki sihir JSON formatındadır. Zabbix Agent veya bir script, Zabbix Server’a belirli bir yapıda JSON döndürür. Server bu JSON’ı parse eder, içindeki makroları (`{#MACRO}`) ayıklar ve tanımladığınız prototiplere göre otomatik olarak Item, Trigger ve Graph oluşturur.

Adım 1: Custom LLD Scripti Yazımı (JSON Formatı)

Zabbix’in bir yapıyı LLD ile keşfedebilmesi için çıktının mutlaka `data` array’i içeren veya doğrudan düz bir JSON array formatında olması gerekir. Biz, sunucuda çalışan aktif Docker container’larını adlarıyla keşfedecek bir Python scripti yazacağız. Bu scripti Zabbix Agent’ın kurulu olduğu hedef makinede konumlandıracağız.

Aşağıdaki scripti hedef sunucuda /etc/zabbix/scripts/discover_containers.py olarak kaydedin:

#!/usr/bin/env python3
import json
import subprocess

def get_containers():
    try:
        # Çalışan container adlarını alıyoruz
        cmd = "docker ps --format '{{.Names}}'"
        result = subprocess.check_output(cmd, shell=True).decode('utf-8')
        containers = [line.strip() for line in result.split('\n') if line.strip()]
        
        # Zabbix LLD formatına uygun JSON şeması oluşturuyoruz
        lld_data = []
        for container in containers:
            lld_data.append({
                "{#CONTAINERNAME}": container
            })
        
        # Zabbix 5.x ve sonraki sürümler doğrudan array kabul eder
        print(json.dumps(lld_data))
    except Exception as e:
        print(json.dumps([]))

if __name__ == "__main__":
    get_containers()

Scriptin çalıştırılabilir olduğundan emin olun:

chmod +x /etc/zabbix/scripts/discover_containers.py

Adım 2: Zabbix Agent Konfigürasyonu (UserParameter)

Yazdığımız scripti Zabbix Server’ın tetikleyebilmesi için Zabbix Agent üzerinde bir UserParameter tanımlamamız gerekiyor. Neden böyle yapıyoruz? Çünkü Agent’ın yeteneklerini dışarıdan güvenli bir şekilde genişletmenin en performanslı yolu budur.

/etc/zabbix/zabbix_agentd.d/userparameter_docker.conf dosyasını oluşturun ve şu satırı ekleyin:

UserParameter=docker.container.discovery,/etc/zabbix/scripts/discover_containers.py
UserParameter=docker.container.cpu[*],docker stats --no-stream --format "{{.CPUPerc}}" $1 | cut -d'%' -f1
UserParameter=docker.container.status[*],docker inspect -f '{{.State.Running}}' $1

Burada ne yaptık?
1. docker.container.discovery anahtarı ile LLD JSON çıktısını sağladık.
2. docker.container.cpu[*] parametrik anahtarı ile keşfettiğimiz container’ın anlık CPU tüketimini çekeceğiz.
3. docker.container.status[*] ile de container’ın çalışıp çalışmadığını (true/false) denetleyeceğiz.

Değişikliklerin devreye girmesi için Zabbix Agent servisini yeniden başlatın:

systemctl restart zabbix-agent

Şimdi Zabbix Server veya proxy üzerinden bu mekanizmanın çalışıp çalışmadığını test edelim:

zabbix_get -s 127.0.0.1 -k docker.container.discovery

Eğer her şey doğru yapılandırıldıysa, ekranda şu tarz bir JSON görmelisiniz:

[{"{#CONTAINERNAME}": "nginx-prod"}, {"{#CONTAINERNAME}": "postgres-db"}]

Adım 3: Zabbix UI Üzerinde Template ve LLD Rule Tanımlama

Sistem katmanındaki hazırlığımız bitti. Şimdi Zabbix Web UI üzerinde bu veriyi işleyecek şablonu (Template) hazırlayalım.

1. Discovery Rule Oluşturma

Zabbix UI’da Configuration > Templates adımına gidin ve yeni bir template oluşturun (Örn: Template App Docker Custom).

  • Oluşturduğunuz template içinde Discovery rules sekmesine gelin ve Create discovery rule butonuna tıklayın.
  • Name: Docker Container Discovery
  • Type: Zabbix agent (veya agent active)
  • Key: docker.container.discovery
  • Update interval: 1m (Geliştirme aşamasında hızlı görmek için 1 dakika, production’da 10m veya 30m idealdir).

2. Item Prototypes (Öğe Prototipleri) Oluşturma

Keşfedilen her bir container için hangi metrikleri toplayacağımızı burada tanımlıyoruz. Discovery rule içindeki Item prototypes sekmesine geçin ve Create item prototype deyin.

CPU Metriği İçin:

  • Name: Container {#CONTAINERNAME}: CPU Usage
  • Key: docker.container.cpu[{#CONTAINERNAME}]
  • Type: Zabbix agent
  • Type of information: Numeric (float)
  • Units: %

Status Metriği İçin:

  • Name: Container {#CONTAINERNAME}: Status
  • Key: docker.container.status[{#CONTAINERNAME}]
  • Type: Zabbix agent
  • Type of information: Character (veya boolean/numeric dönüşümü yapabilirsiniz, inspect çıktımız ‘true’/’false’ döneceği için Character seçip trigger’da regex ile kontrol etmek pratik bir yoldur).

Adım 4: Dinamik Trigger Prototipleri ile Akıllı Alarmlar

Sadece veri toplamak yetmez, bu verilerin anomali durumlarında nöbetçi mühendisi ayağa kaldırması gerekir. Ancak her yeni container için manuel alarm yazamayız. LLD burada devreye girerek her container için bağımsız trigger’lar üretir.

Discovery rule altındaki Trigger prototypes sekmesine gelin ve Create trigger prototype butonuna tıklayın.

Senaryo: Container Stop Olduysa Alarm Üret

  • Name: Container {#CONTAINERNAME} is not running on {HOST.NAME}
  • Expression:
    last(/Template App Docker Custom/docker.container.status[{#CONTAINERNAME}])="false"
  • Severity: High veya Average

Bu ifade sayesinde, sistemde yeni bir container (örneğin redis-cache) ayağa kalktığı anda Zabbix bunu LLD ile keşfedecek, ardından docker.container.status[redis-cache] item’ını oluşturacak ve eğer bu container stop durumuna düşerse otomatik olarak “Container redis-cache is not running on Server-01” başlığıyla alarm üretecektir.

Production İpuçları ve “Neden Böyle?” Analizi

Büyük ölçekli ortamlarda LLD kullanırken sistem kaynaklarını tüketmemek ve false-positive alarmların önüne geçmek için şu mimari kararları uygulamalısınız:

Keep Lost Resources Period (Kayıp Kaynakları Tutma Süresi)

LLD rule konfigürasyonunda Keep lost resources period adında bir parametre göreceksiniz. Varsayılan değeri 30 gündür. Eğer dinamik ortamlarda (örn. Jenkins agent’ları gibi sürekli açılıp kapanan container’lar) çalışıyorsanız, bu değeri 30 gün bırakırsanız Zabbix veritabanınız çöpe döner. Silinen container’ların monitoring öğelerinin sistemden hızlıca temizlenmesi için bu değeri 1h (1 saat) veya en fazla 1d (1 gün) olarak ayarlayın.

Discard Unchanged (Değişmeyen Veriyi Yoksayma)

Container status metriği her dakika “true” dönecektir. Veritabanında her dakika aynı veriyi yazarak I/O tüketmemek için Item Prototype ayarlarındaki Preprocessing sekmesine gidin. Buraya Discard unchanged with heartbeat ekleyin ve süresini 1h yapın. Böylece durum değişmediği sürece veritabanına sadece saatte bir yazılır, ancak durum “false” olduğu an hemen kayıt düşülür.

Zabbix LLD, altyapınızı kodla yönettiğiniz (Infrastructure as Code) modern dünyada izleme katmanının da bu hıza ayak uydurmasını sağlayan en kritik araçtır. Doğru kurgulanmış bir LLD şablonu, operasyonel iş yükünüzü kalıcı olarak azaltır.

Category: Genel | LEAVE A COMMENT