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.