Zabbix ile Docker Container İzleme
Production ortamında Docker izleme meselesi benim için gerçek bir dönüm noktasıydı. Birkaç yıl önce, tam bir gece yarısı kritik bir container sessizce çöktü ve kimse fark etmedi, ta ki sabah iş başlayıp müşterilerden şikayet gelene kadar. O günden sonra “container çalışıyorsa sorun yok” mantığını bir kenara bıraktım. Çalışıyor olmak yeterli değil; ne kadar bellek yiyor, CPU’yu ne zaman patlatıyor, volume’lar dolmuyor mu, bunların hepsini gerçek zamanlı görmek lazım. Zabbix bu iş için mükemmel bir araç, ancak Docker entegrasyonunu doğru kurmak biraz emek istiyor.
Mimariyi Anlamak: Zabbix Docker İzlemede Ne Yapıyor?
Zabbix’in Docker container’larını izlemesi iki farklı yaklaşımla mümkün. Birinci yöntem Zabbix Agent 2 kullanmak; bu agent Docker socket’ine doğrudan erişebilen native plugin’lere sahip. İkinci yöntem ise custom script’lerle docker stats çıktısını işlemek. Profesyonel ortamlarda Zabbix Agent 2 tercih ediliyor çünkü Agent 2, Go diliyle yazılmış ve Docker plugin’i native olarak destekliyor; ayrı bir şey kurmanıza gerek kalmıyor.
Mimarimiz şöyle işleyecek: Zabbix Server merkezi olarak topluyor, her Docker host’una Zabbix Agent 2 kuruyoruz, agent Docker socket’iyle konuşuyor, veriyi server’a gönderiyor. Basit ama dikkat edilmesi gereken detaylar var.
Zabbix Agent 2 Kurulumu ve Docker Socket Erişimi
İlk iş Agent 2’yi kurmak. Eğer hâlâ classic Agent kullanıyorsanız geçiş yapmanın zamanı geldi; Docker izleme için Agent 2 şart.
# Ubuntu/Debian için Zabbix Agent 2
wget https://repo.zabbix.com/zabbix/6.4/ubuntu/pool/main/z/zabbix-release/zabbix-release_6.4-1+ubuntu22.04_all.deb
dpkg -i zabbix-release_6.4-1+ubuntu22.04_all.deb
apt-get update
apt-get install -y zabbix-agent2 zabbix-agent2-plugin-*
# RHEL/Rocky Linux için
rpm -Uvh https://repo.zabbix.com/zabbix/6.4/rhel/8/x86_64/zabbix-release-6.4-1.el8.noarch.rpm
dnf install -y zabbix-agent2 zabbix-agent2-plugin-*
Şimdi kritik nokta: Zabbix Agent 2’nin Docker socket’ine erişebilmesi için zabbix kullanıcısının docker grubunda olması gerekiyor.
# zabbix kullanıcısını docker grubuna ekle
usermod -aG docker zabbix
# Değişikliğin uygulanması için servisi yeniden başlat
systemctl restart zabbix-agent2
# Kontrol et
id zabbix
# Çıktıda docker grubu görünmeli: uid=...(zabbix) gid=...(zabbix) groups=...,docker
Güvenlik konusunda bir not düşeyim: Docker socket’e erişim vermek pratikte root yetkisi vermekle eşdeğer. Üretim ortamında bunu kabul edebilir bir risk olarak görüyorsanız, alternatif olarak Docker’ın TCP socket’ini TLS ile açıp o yönde bağlanabilirsiniz. Ancak çoğu iç ağ ortamı için unix socket yöntemi kullanılıyor.
Agent 2 Konfigürasyonu
/etc/zabbix/zabbix_agent2.conf dosyasını düzenleyelim:
# /etc/zabbix/zabbix_agent2.conf içine eklenecekler
Server=192.168.1.100 # Zabbix Server IP
ServerActive=192.168.1.100 # Active check için
Hostname=docker-host-01 # Bu host'un adı
# Docker plugin konfigürasyonu
Plugins.Docker.Endpoint=unix:///var/run/docker.sock
# Timeout değerini artır, container listesi uzunsa zaman alabilir
Timeout=30
Servisi başlatıp test edelim:
systemctl enable --now zabbix-agent2
# Docker bağlantısını manuel test et
zabbix_agent2 -t docker.info
# Container listesini kontrol et
zabbix_agent2 -t docker.containers.discovery
Eğer docker.containers.discovery çıktısında tüm container’larınızı JSON formatında görüyorsanız, temel entegrasyon çalışıyor demektir.
Zabbix Frontend’de Docker Template’i Bağlamak
Zabbix 6.x ile birlikte gelen “Docker by Zabbix agent 2” template’i son derece kapsamlı. Bu template’i host’a bağlamak için:
- Zabbix Frontend’de Configuration > Hosts bölümüne gidin
- İlgili host’u seçin, Templates sekmesine tıklayın
- “Docker by Zabbix agent 2” template’ini arayıp ekleyin
- Update ile kaydedin
Template otomatik olarak şunları discovery edecek ve izleyecek:
- Çalışan ve durmuş tüm container’lar
- Her container’ın CPU kullanımı
- Memory limit ve kullanımı
- Network I/O (gelen/giden trafik)
- Block I/O (disk okuma/yazma)
- Container durumu (running, stopped, paused, exited)
Custom Docker Monitoring Script’leri
Template tek başına çoğu ihtiyacı karşılıyor ama gerçek dünya senaryolarında her zaman özelleştirme gerekiyor. Örneğin belirli bir container’ın log’unda hata sayısını izlemek isteyebilirsiniz.
İşte basit ama işe yarayan bir custom check script’i:
#!/bin/bash
# /usr/local/bin/docker-container-check.sh
# Belirli bir container'ın log'undaki ERROR sayısını son 5 dakikada döndürür
CONTAINER_NAME=$1
TIME_WINDOW=5 # dakika
if [ -z "$CONTAINER_NAME" ]; then
echo "Usage: $0 <container_name>"
exit 1
fi
# Container çalışıyor mu kontrol et
RUNNING=$(docker inspect --format='{{.State.Running}}' "$CONTAINER_NAME" 2>/dev/null)
if [ "$RUNNING" != "true" ]; then
echo "-1" # Container çalışmıyor
exit 0
fi
# Son 5 dakikadaki ERROR sayısı
ERROR_COUNT=$(docker logs --since "${TIME_WINDOW}m" "$CONTAINER_NAME" 2>&1 | grep -ic "error|ERROR|Error")
echo "$ERROR_COUNT"
Bu script’i Zabbix’e tanıtmak için UserParameter ekleyelim:
# /etc/zabbix/zabbix_agent2.d/docker-custom.conf
UserParameter=docker.container.errors[*],/usr/local/bin/docker-container-check.sh $1
UserParameter=docker.container.uptime[*],docker inspect --format='{{.State.StartedAt}}' $1 2>/dev/null | xargs -I{} date -d {} +%s | xargs -I{} echo $(( $(date +%s) - {} ))
# Script'e çalıştırma izni ver ve agent'ı yeniden yükle
chmod +x /usr/local/bin/docker-container-check.sh
systemctl reload zabbix-agent2
# Test
zabbix_agent2 -t "docker.container.errors[nginx]"
Low-Level Discovery ile Dinamik Container İzleme
Production ortamında container’lar sürekli gelip gidiyor. Bugün 5 container varken yarın 12 olabiliyor. Her birini elle eklemek yerine LLD (Low-Level Discovery) kullanmak çok daha mantıklı.
Custom discovery script yazalım; bu script sadece web_ prefix’iyle başlayan container’ları keşfedecek (örneğin birden fazla web uygulaması çalıştıran ortamlar için):
#!/bin/bash
# /usr/local/bin/docker-web-discovery.sh
# "web_" ile başlayan container'ları Zabbix LLD formatında döndürür
echo '{"data":['
FIRST=true
while IFS= read -r container; do
NAME=$(docker inspect --format='{{.Name}}' "$container" | sed 's////')
IMAGE=$(docker inspect --format='{{.Config.Image}}' "$container")
if [[ "$NAME" == web_* ]]; then
if [ "$FIRST" = false ]; then
echo ","
fi
printf ' {"{#CONTAINERNAME}":"%s","{#CONTAINERIMAGE}":"%s","{#CONTAINERID}":"%s"}'
"$NAME" "$IMAGE" "${container:0:12}"
FIRST=false
fi
done < <(docker ps -q)
echo
echo ']}'
Bu discovery script’ini Zabbix’e tanıtın:
# /etc/zabbix/zabbix_agent2.d/docker-discovery.conf
UserParameter=docker.web.discovery,/usr/local/bin/docker-web-discovery.sh
Zabbix Frontend’de bu discovery rule’u kullanarak her web container için otomatik item ve trigger oluşturabilirsiniz.
Önemli Trigger’lar ve Alert Mantığı
İzlemek bir şey, doğru alarm kurmak başka bir şey. Gereksiz alarm üretmek kadar tehlikeli bir şey yok; insanlar uyarıları görmezden gelmeye başlıyor. İşte production’da gerçekten işe yarayan trigger mantıkları:
Container bellek kullanımı için akıllı alarm: Zabbix Frontend’de aşağıdaki expression ile trigger oluşturun:
# Container memory kullanımı limit'in %90'ını geçerse
last(/docker-host-01/docker.container_info["{#CONTAINERNAME}",mem_usage])
/ last(/docker-host-01/docker.container_info["{#CONTAINERNAME}",mem_limit]) * 100 > 90
Container beklenmedik şekilde durdu mu?
# Son 5 dakikada container durumu "running" değilse
last(/docker-host-01/docker.container_info["{#CONTAINERNAME}",container_status]) <> 1
and nodata(/docker-host-01/docker.container_info["{#CONTAINERNAME}",container_status],5m) = 0
CPU spike tespiti:
# 3 kez art arda CPU %80 üzerindeyse alarm ver
min(/docker-host-01/docker.container_stats["{#CONTAINERNAME}",cpu_util],#3) > 80
Production’dan gerçek bir deneyim paylaşayım: nodata() fonksiyonunu container trigger’larına eklemeyi unutmayın. Container tamamen çöktüğünde veri gelmez ve Zabbix “değer yok” durumunu ayrıca fark etmeli. Bunu ilk kurduğumda atladım ve bir container 2 saat boyunca tamamen çökmüş halde veri göndermediği için alarm da üretmemişti.
Docker Compose Ortamlarında Stack İzleme
Tek container izlemekten çok, gerçek senaryolarda Docker Compose ile ayağa kalkan servis stack’leri izliyorsunuz. Bir stack’in sağlığını bütünsel değerlendirmek için şöyle bir script yazabilirsiniz:
#!/bin/bash
# /usr/local/bin/compose-stack-health.sh
# Bir Docker Compose projesinin kaç container'ının sağlıklı olduğunu döndürür
COMPOSE_PROJECT=$1
EXPECTED_COUNT=$2
if [ -z "$COMPOSE_PROJECT" ] || [ -z "$EXPECTED_COUNT" ]; then
echo "Usage: $0 <project_name> <expected_container_count>"
exit 1
fi
# Proje adına göre çalışan container sayısını bul
RUNNING_COUNT=$(docker ps --filter "label=com.docker.compose.project=${COMPOSE_PROJECT}"
--filter "status=running" -q | wc -l)
# Beklenen sayıya ulaştıysa 1 (OK), ulaşmadıysa çalışan sayıyı döndür
if [ "$RUNNING_COUNT" -eq "$EXPECTED_COUNT" ]; then
echo "1"
else
echo "$RUNNING_COUNT"
fi
Zabbix’te bu item için şöyle bir trigger:
# Proje container sayısı beklenen değerin altındaysa
last(/docker-host-01/compose.stack.health[myapp,5]) < 1
Bu sayede “myapp” projesine ait 5 container’dan herhangi biri düştüğünde alarm alırsınız.
Zabbix Proxy ile Dağıtık Docker Ortamları
Çok lokasyonlu veya mikroservis ağırlıklı ortamlarda her Docker host için ayrı Zabbix Proxy kullanmak gerekiyor. Proxy mimarisinde dikkat edilecek nokta: Her proxy kendi bölgesindeki Docker host’larını yönetir, merkezi server sadece proxy’lerden veri toplar.
Proxy konfigürasyonu için temel ayarlar:
# /etc/zabbix/zabbix_proxy.conf
Server=192.168.1.100 # Merkezi Zabbix Server
Hostname=proxy-datacenter-02
DBName=/tmp/zabbix_proxy.db # SQLite kullanıyorsanız
ProxyMode=0 # Active proxy
ConfigFrequency=60 # Her 60 saniyede config güncelle
DataSenderFrequency=5 # Her 5 saniyede veri gönder
Büyük ortamlarda (50’den fazla Docker host) bu mimari olmadan Zabbix Server çok fazla bağlantı yönetmek zorunda kalır ve performans sorunları başlar.
Görselleştirme: Dashboard Oluşturma
Veriyi toplamak kadar görselleştirmek de önemli. Zabbix 6.x Dashboard’ları oldukça gelişmiş. Docker container’ları için işe yarayan widget konfigürasyonları:
- Graph widget: CPU ve Memory için ayrı graflar oluşturun, tek grafikte karıştırmayın
- Item value widget: Toplam çalışan container sayısını büyük rakamla gösterin, ilk bakışta durum anlaşılsın
- Problems widget: Sadece Docker host’larına ait problemleri filtreleyin, gürültüyü kesin
- Top hosts widget: En çok CPU ve memory tüketen container’ları sıralı gösterin
Dashboard’u farklı ekipler için farklı configüre edin. Geliştirici ekibi kendi uygulamasının container’larını görmeli, altyapı ekibi tüm host’ları.
Performans Optimizasyonu: Polling Interval ve History
Container izlemede çok sık polling yapmak Zabbix Server’ı ve izlenen host’u yorar. Öte yandan çok seyrek polling sorunları geç yakalatır. Dengeli bir yaklaşım:
- Container durumu (running/stopped): 30 saniye polling yeterli
- CPU ve Memory: 60 saniye, production baskısı durumunda 30
- Network I/O: 60 saniye
- Log hata sayısı: 5 dakika, her dakika kontrol etmenin anlamı yok
- Discovery rule: 5-10 dakika, container’lar çok sık değişmiyorsa
History ve trend ayarları için de dikkatli olun. Her container için dakikalık veri 90 gün tutarsanız veritabanınız şişer. Pratik bir kural: CPU ve memory için 7-14 gün history, 90 gün trend yeterli. Eski container’lara ait history’yi periyodik temizleyin.
Sorun Giderme: Sık Karşılaşılan Hatalar
Gerçek kurulumda karşılaştığım ve zaman kaybettiren problemler:
“Cannot connect to Docker socket” hatası: Genellikle izin sorunu. ls -la /var/run/docker.sock ile socket’in group’una bakın, zabbix kullanıcısı o grupta mı kontrol edin.
Discovery çalışıyor ama item’lar oluşmuyor: Template’de LLD filter tanımlı olabilir. Varsayılan template bazı container’ları {#CONTAINERNAME} matches ^[a-z] gibi filtrelerle atlayabilir.
Container CPU değerleri mantıksız görünüyor: Docker CPU istatistikleri toplam CPU time kullanıyor, Zabbix’in hesaplama metodu bilinmeden grafikler yanıltıcı olabiliyor. cpu_util item’ı için Change per second value type’ını kullandığınızdan emin olun.
Zabbix Agent 2 servis başlamıyor: Plugin konfigürasyon dosyalarında syntax hatası olabilir. zabbix_agent2 -t docker.info -v ile detaylı çıktıya bakın.
Sonuç
Zabbix ile Docker izleme kurulumu ilk bakışta karmaşık görünüyor ancak katman katman inşa ettiğinizde her şey yerine oturuyor. Agent 2 native Docker desteğiyle başlayın, temel template’i bağlayın, sonra ihtiyaçlarınıza göre custom script’lerle genişletin. Körü körüne her metriği toplamak yerine önce “hangi soruların cevabını arıyorum?” diye düşünün.
En önemli çıkarımım şu: Alarm kalitesi, alarm miktarından çok daha önemli. Onlarca yanlış pozitif alarm üreten bir sistem zamanla görmezden gelinir. Her trigger’ın gerçekten aksiyon gerektirdiğinden emin olun, gerekiyorsa daha uzun zaman penceresi kullanın.
Container sayısı arttıkça izleme mimarisi de evrimilmek zorunda. Bugün 10 container için yeterli olan setup, yarın 100 container’la birlikte Zabbix Proxy gerektiriyor, belki 200’de Prometheus+Grafana’ya geçiş tartışması başlıyor. Araçlara dogmatik bağlanmayın, probleminizin ölçeğine uygun çözümü seçin. Ama küçük ve orta ölçekli Docker ortamları için Zabbix Agent 2 ile bu anlattıklarım yıllardır güvenilir biçimde çalışıyor.
