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
Ekim 4 2024

Cron İşlerini Bash ile Monitör Etme ve Alerting

Modern altyapılarda Kubernetes cronjob’ları, serverless scheduler’lar havada uçuşsa da, günün sonunda hepimizin bir yerlerde tıkır tıkır çalışan (ya da çalıştığını umduğu) emektar bir linux sunucusu ve içinde barınan klasik cron işleri vardır. Ancak cron’un en büyük problemi “sessiz ölüm” (silent failure) dediğimiz durumdur. Bir backup script’i patladığında, disk dolduğunda veya API key’in süresi geçtiğinde cron bunu size söylemez. Bu yazıda, kendi yazacağımız esnek bir bash wrapper script ile tüm cron işlerinizi merkezi olarak monitoring dünyasına entegre edecek, hata durumlarında anında alert üretecek ve üçüncü parti servislerle nasıl haberleştireceğimizi göreceğiz.

Klasik Cron Yaklaşımlarının Sorunu Nedir?

Hepimiz o yollardan geçtik. Bir cron işinin çıktısını almak için satırın sonuna efsanevi >> /var/log/myjob.log 2>&1 yönlendirmesini yazarız. Sonra ne mi olur? O log dosyası gigabaytlarca büyür, diski doldurur ve bir gün script hata verdiğinde kimsenin haberi olmaz. Çünkü logları aktif olarak okuyan kimse yoktur.

Eski usul Linux yöneticileri size “MTA (Mail Transfer Agent) kurun, cron hata aldığında lokal mail atsın” diyecektir. Yıl 2024+. ephemeral VM’lerin, cloud instance’larının cirit attığı bu çağda localhost mail kuyruklarıyla uğraşmak, postfix yapılandırmak ve spame düşen lokal mailleri takip etmek tam bir operasyonel işkencedir. Bizim daha proaktif, modern ve DevOps pratiklerine uygun bir çözüme ihtiyacımız var.

Wrapper Script Pattern Neden En İyi Çözümdür?

Elinizde 20 farklı cron script’i olduğunu düşünün. Her birinin içine tek tek Slack webhook entegrasyonu, hata yakalama (error handling) ve çalışma süresi ölçümü eklemek tam bir anti-pattern’dir. Kod tekrarı yaratır ve yarın öbür gün Slack yerine Teams’e geçildiğinde 20 farklı script’i update etmeniz gerekir.

Wrapper Script Pattern, çalıştırılacak asıl komutu sarmalayan, onun exit code’unu yakalayan, standart output (stdout) ve standart error (stderr) akışlarını yöneten merkezi bir aracıdır. Crontab içerisindeki tanımımız şuna benzer:

0 4 * * * /usr/local/bin/cron-wrapper.sh --job "db-backup" --cmd "/opt/scripts/backup.sh --force"

Bu yaklaşım sayesinde, asıl işi yapan script’in monitoring mantığından tamamen bağımsız (decoupled) kalmasını sağlarız. Script sadece işini yapar ve exit code döner; wrapper ise raporlamayı üstlenir.

Adım 1: Savaşçı Ruhlu Bash Wrapper Script

Lafı uzatmadan production ortamında güvenle kullanabileceğiniz, hata durumunda exit code’u ve logları yakalayan, zaman aşımı (timeout) kontrolü yapabilen wrapper script’imizi yazalım. Bu script’i /usr/local/bin/cron-wrapper.sh olarak kaydedebilirsiniz.

#!/usr/bin/env bash

# Robust Bash Ayarları
set -o nounset
set -o pipefail

# Değişken Tanımları
JOB_NAME=""
COMMAND=""
SLACK_WEBHOOK_URL="${SLACK_WEBHOOK_URL:-""}"
HEALTHCHECK_URL="${HEALTHCHECK_URL:-""}"

# Kullanım Yardımcısı
usage() {
    echo "Kullanım: $0 --job [JOB_NAME] --cmd [COMMAND]"
    exit 1
}

# Parametreleri Parse Etme
while [[ $# -gt 0 ]]; do
    case "$1" in
        --job)
            JOB_NAME="$2"
            shift 2
            ;;
        --cmd)
            COMMAND="$2"
            shift 2
            ;;
        *)
            usage
            ;;
    esac
done

if [[ -z "$JOB_NAME" || -z "$COMMAND" ]]; then
    usage
fi

# Geçici Log Dosyası Oluşturma (Güvenli yöntem)
LOG_FILE=$(mktemp /tmp/cron_wrapper_${JOB_NAME}.XXXXXX)

# Her durumda temizlik yapılması için trap kullanımı
cleanup() {
    rm -f "$LOG_FILE"
}
trap cleanup EXIT

# Zamanı Ölçmeye Başla
START_TIME=$(date +%s)

echo "[$(date '+%Y-%m-%d %H:%M:%S')] Job '$JOB_NAME' başlatılıyor..." >> "$LOG_FILE"
echo "Komut: $COMMAND" >> "$LOG_FILE"
echo "--------------------------------------------------" >> "$LOG_FILE"

# Komutu çalıştır ve tüm çıktıyı log dosyasına yönlendir
# set +e kullanıyoruz çünkü komut hata verirse wrapper script'in hemen çökmesini istemiyoruz,
# hatayı yakalayıp alert üreteceğiz.
set +e
eval "$COMMAND" >> "$LOG_FILE" 2>&1
EXIT_CODE=$?
set -e

# Zamanı Hesapla
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))

echo "--------------------------------------------------" >> "$LOG_FILE"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Job bitti. Süre: ${DURATION}sn, Exit Code: $EXIT_CODE" >> "$LOG_FILE"

# Sonuçları Değerlendir
if [ $EXIT_CODE -eq 0 ]; then
    echo "Başarılı: $JOB_NAME sorunsuz tamamlandı."
    # Eğer tanımlıysa Healthcheck ping'i gönder (Mavi Tik)
    if [ -n "$HEALTHCHECK_URL" ]; then
        curl -fsS --retry 3 "$HEALTHCHECK_URL" > /dev/null 2>&1 || true
    fi
else
    echo "HATA: $JOB_NAME başarısız oldu! Exit code: $EXIT_CODE" >&2
    
    # Slack Alert Tetikleme fonksiyonunu çağır
    if [ -n "$SLACK_WEBHOOK_URL" ]; then
        # Log dosyasının son 20 satırını alalım ki Slack mesajı devasa olmasın
        LAST_LOGS=$(tail -n 20 "$LOG_FILE" | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
        
        PAYLOAD=$(cat <<EOF
{
  "text": "🚨 *Cron Job Hatası!*",
  "attachments": [
    {
      "color": "danger",
      "fields": [
        { "title": "Job Adı", "value": "${JOB_NAME}", "short": true },
        { "title": "Exit Code", "value": "${EXIT_CODE}", "short": true },
        { "title": "Süre", "value": "${DURATION} saniye", "short": true },
        { "title": "Sunucu", "value": "$(hostname)", "short": true }
      ],
      "text": "*Son Loglar:*\n\`\`\`${LAST_LOGS}\`\`\`"
    }
  ]
}
EOF
)
        curl -X POST -H 'Content-type: application/json' --data "$PAYLOAD" "$SLACK_WEBHOOK_URL" > /dev/null 2>&1 || true
    fi
    
    # Wrapper kendisi de hata koduyla çıksın ki pipeline'lar veya üst sistemler anlasın
    exit $EXIT_CODE
fi

Neden “set +e” ve “set -o pipefail” Kullandık?

Bash’te hata yönetimi hassas bir konudur. set -o pipefail komutu, bir pipe zincirindeki herhangi bir komut hata verirse tüm satırın hata kodu dönmesini sağlar. Wrapper script’in başında bunu aktif ettik. Ancak, sarmaladığımız asıl komut hata verdiğinde script’imizin patlayıp Slack alert’ini gönderemeden sonlanmasını engellemek için, çalıştırma aşamasında geçici olarak set +e ile esneklik sağladık, exit code’u güvenli bir şekilde $? ile lokal değişkene aldık ve ardından set -e ile güvenli modumuza geri döndük.

Ayrıca mktemp kullanımı, paralel çalışan cron işlerinin aynı log dosyası üzerine yazarak yarış durumuna (race condition) girmesini engeller.

Adım 2: “Dead Man’s Snitch” Mantığı ile Healthcheck Entegrasyonu

Peki ya sunucunun kendisi çökerse? Ya da cron daemon durursa? Bu durumlarda “hata aldığımda Slack’e yaz” mantığı tamamen devre dışı kalır. Çünkü çalışmayan bir sistem hata mesajı da gönderemez. Buna monitoring dünyasında silent failure denir.

Çözüm: Inverted Monitoring (Ters İzleme) ya da bilinen adıyla Heartbeat / Dead Man’s Snitch pattern. Sistem çalışmayı durdurduğunda alarm çalmasını istiyorsak, sistemin düzenli aralıklarla “Ben hayattayım!” sinyali göndermesi gerekir. Eğer sinyal gelmezse, monitoring sunucumuz bizi uyarır.

Bu iş için healthchecks.io veya kendi host ettiğiniz open-source alternatiflerini (örneğin Uptime Kuma) kullanabilirsiniz. Script’imizdeki HEALTHCHECK_URL tam olarak bunu yapar. Cron başarılı biterse ilgili adrese bir curl isteği atar. Eğer o istek zamanında gitmezse, dış dünya sunucunun patladığını anlar.

Adım 3: Slack Webhook ile Gerçek Zamanlı Alerting

Yukarıdaki script’imizde Slack için JSON payload’unu dinamik olarak oluşturduk. Bash içinde JSON oluştururken kaçış karakterleri (escaping) her zaman baş ağrıtır. Bu yüzden log dosyasından okuduğumuz son 20 satırı (LAST_LOGS) temizlemek için sed ile yeni satır karakterlerini (\n) ve çift tırnakları escape ettik.

Slack’te görünecek mesaj, hata anında debug yapmanızı inanılmaz kolaylaştıracaktır. Hangi sunucuda, ne kadar sürede patladığını ve hatanın son satırlarını terminale girmeden telefonunuzdan görebilirsiniz:

Slack Notification Alerting

Adım 4: Crontab Yapılandırması

Şimdi yazdığımız bu sistemi gerçek bir senaryoda test edelim. Sunucumuzdaki env variable’ları crontab ortamına geçirmek bazen can sıkıcı olabilir. En temiz yöntem webhook url gibi hassas verileri wrapper script içine hardcode etmek yerine wrapper’ı çağırırken bir konfigürasyondan beslemek veya crontab’ın üst kısmında tanımlamaktır.

# /etc/cron.d/my-monitored-crons veya crontab -e

SLACK_WEBHOOK_URL="https://hooks.slack.com/services/T00/B00/X00"
HEALTHCHECK_URL="https://hc-ping.com/your-uuid-here"

# Her gece 03:00'te yedek al, hata olursa Slack'e bildir, başarılı olursa ping at
0 3 * * * root /usr/local/bin/cron-wrapper.sh --job "database-backup" --cmd "/opt/backups/pg_dump.sh"

Dikkat Edilmesi Gereken İpuçları

  • Mutlak Yol (Absolute Paths) Kullanın: Cron ortamında $PATH değişkeni kısıtlıdır. Hem wrapper script’in içinde çağırdığınız tool’ların (curl, sed vb.) hem de crontab içindeki komutların tam yollarını yazmaya özen gösterin.
  • Yetkilendirme: Wrapper script’in çalıştırılabilir olduğundan emin olun: chmod +x /usr/local/bin/cron-wrapper.sh
  • Log Rotasyonu: Biz script içinde trap kullanarak geçici logları işlem sonunda siliyoruz. Ancak işlem yarıda kesilirse (örneğin kill -9) loglar kalabilir. Periyodik olarak /tmp dizininin temizlendiğinden emin olun (çoğu modern Linux dağıtımı bunu otomatik yapar).

Özet

Cron işlerini kendi haline bırakmak, prod ortamında saatli bir bomba üzerinde oturmak gibidir. Bu makalede yazdığımız esnek bash wrapper script sayesinde, mevcut hiçbir altyapınızı bozmadan, tek bir merkezi mekanizma ile tüm linux cron işlerinizi modern birer microservice gibi monitoring ve alert süreçlerine dahil ettik. Unutmayın, en iyi sistem tıkır tıkır çalışan değil, bozulduğunda neresinin bozulduğunu size ilk söyleyen sistemdir.

Category: Genel | LEAVE A COMMENT
Eylül 13 2024

Elastic Fleet ile Merkezi Agent Yönetimi: Elveda Config Karmaşası!

DevOps dünyasında monitoring ve log yönetimi denince akla gelen ilk isimlerden biri şüphesiz Elastic Stack. Ancak her sunucuya ayrı Filebeat, Metricbeat, Heartbeat kurup, Ansible playbook’ları içinde YAML indentasyon hatalarıyla boğuştuğumuz günler geride kaldı. Modern altyapılarda artık “single binary” felsefesi ve merkezi yönetim ön planda. İşte bu noktada sahneye elastic stack’in kurtarıcısı olan fleet ve onun her işe koşan askeri agent çıkıyor.

Bu makalede, production ortamlarında hayat kurtaran Elastic Fleet mimarisini, Fleet Server kurulumunu, policy yönetimini ve sisteme dinamik entegrasyonlar eklemeyi derinlemesine inceleyeceğiz. Çayınızı kahvenizi alın; Ansible playbook’larınızdaki Beats rollerini silmeye hazırlanıyoruz.

Neden Elastic Fleet? Eski Usul Beats vs. Modern Agent

Eski günleri hatırlayalım. Bir web sunucunuz var ve hem sistem metriklerini (CPU, RAM) hem de Nginx loglarını toplamak istiyorsunuz. Süreç kabaca şöyle işliyordu:

  • Sunucuya Metricbeat indir, kur, metricbeat.yml konfigüre et, servisi başlat.
  • Filebeat indir, kur, Nginx modülünü aktif et, filebeat.yml içinde Elasticsearch adresini gir, servisi başlat.
  • Elasticsearch cluster adresi veya şifresi değiştiğinde, tüm sunuculardaki o meşhur YAML dosyalarını CM (Configuration Management) araçlarıyla güncelle.

Bu yaklaşım ölçeklendikçe tam bir kabusa dönüşüyor. Elastic Agent ise bu karmaşayı tek bir binary altında topluyor. Agent arka planda gereken tüm “Beat” işlevlerini barındırıyor ve en önemlisi, konfigürasyonunu lokal bir dosyadan değil, doğrudan Kibana üzerinde koşan Fleet Server’dan dinamik olarak çekiyor. Siz Kibana arayüzünden tek bir tıkla yeni bir log kaynağı eklediğinizde, hedef sunucudaki Elastic Agent saniyeler içinde yeni policy’yi uyguluyor. Ne restart gerekiyor, ne de sunucuya SSH atmak.

Fleet Server Mimarisi: Olayın Arkasındaki Beyin

Fleet yapısını kurmadan önce mimariyi anlamak şart. Fleet, merkezi yönetim katmanıdır ve Kibana ile entegre çalışır. Ancak Kibana, binlerce agent ile doğrudan ham veri alışverişi yapacak şekilde tasarlanmamıştır. Bu yüzden araya Fleet Server girer.

Fleet Server, Elastic Agent’ların bağlandığı, policy güncellemelerini aldığı ve durum raporladığı bir kontrol merkezidir. Kendisi de aslında özel bir policy ile çalışan bir Elastic Agent’tır. Agent’lar Fleet Server’a HTTPS üzerinden bağlanır (genellikle port 8220). Fleet Server ise aldığı durumları ve metrikleri doğrudan Elasticsearch’e yazar.

Adım Adım Fleet Server Kurulumu (Self-Hosted)

Eğer Elastic Cloud kullanıyorsanız Fleet Server sizin için otomatik olarak yönetilir. Ancak gerçek DevOps mühendisleri olarak biz self-hosted yapıları severiz (veya mecbur kalırız). Gelin, kendi altyapımızda Fleet Server’ı Docker üzerinde ayağa kaldıralım.

Adım 1: Elasticsearch ve Kibana Hazırlığı

Öncelikle halihazırda HTTPS korumalı bir Elasticsearch cluster’ınız ve Kibana’nız olduğunu varsayıyoruz. Fleet Server’ın Elasticsearch ile haberleşebilmesi için bir “Service Token” üretmemiz gerekiyor. Kibana Console (Dev Tools) üzerinden şu komutla token’ımızı alalım:

POST _security/service/elastic/fleet-server/token/my-fleet-token

Dönen yanıttaki value değerini güvenli bir yere kaydedin. Bu bizim FLEET_SERVER_ELASTICSEARCH_SERVICE_TOKEN değerimiz olacak.

Adım 2: Fleet Server’ı Docker ile Çalıştırma

Aşağıdaki Docker komutu ile Fleet Server’ı ayağa kaldırabiliriz. Üretim ortamında mutlaka geçerli SSL sertifikaları kullanmalısınız, ancak test ortamı için doğrulama adımlarını esnetebiliriz.

docker run -d \
  --name fleet-server \
  -p 8220:8220 \
  -e FLEET_SERVER_ENABLE=1 \
  -e FLEET_SERVER_ELASTICSEARCH_HOST=https://elasticsearch.local:9200 \
  -e FLEET_SERVER_ELASTICSEARCH_SERVICE_TOKEN=AAEAAWVsYXN0aWMvZmxlZXQtc2VydmVyL3Rva2VuLTE2N... \
  -e FLEET_URL=https://fleet-server.local:8220 \
  -e FLEET_SERVER_CERT=/usr/share/elastic-agent/certs/fleet.crt \
  -e FLEET_SERVER_KEY=/usr/share/elastic-agent/certs/fleet.key \
  -v /path/to/certs:/usr/share/elastic-agent/certs \
  docker.elastic.co/beats/elastic-agent:8.11.1

Bu komutla Fleet Server, 8220 portundan agent bağlantılarını kabul etmeye hazır hale gelecektir. Kibana arayüzünde Management > Fleet sekmesine gittiğinizde Fleet Server’ın “Healthy” durumuna geçtiğini görmelisiniz.

Elastic Agent Kurulumu ve Fleet’e Enroll Etme

Sırada log ve metrik toplayacağımız hedef sunuculara (örneğin bir Linux VM) Elastic Agent kurmak var. Agent kurulumu son derece basittir çünkü tek bir binary indirip çalıştırmaktan ibarettir.

Adım 1: Agent Paketini İndirme

Hedef sunucuda terminale çıkıp işletim sistemimize uygun paketi indiriyoruz:

curl -L -O https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-8.11.1-linux-x86_64.tar.gz
tar xzvf elastic-agent-8.11.1-linux-x86_64.tar.gz
cd elastic-agent-8.11.1-linux-x86_64

Adım 2: Enrollment (Kayıt) İşlemi

Agent’ı sisteme kurarken onu Fleet Server’a “enroll” etmemiz, yani kaydetmemiz gerekir. Bunun için Kibana > Fleet > Enrollment Tokens sekmesinden hedef policy için üretilmiş token’ı alıyoruz. Ardından şu komutla kurulumu tetikliyoruz:

sudo ./elastic-agent install \
  --url=https://fleet-server.local:8220 \
  --enrollment-token=U0ZVMWhvMEJGUnp6eE5iNUp0eXU6cUpnZXA3V... \
  --certificate-authorities=/path/to/ca.crt

Bu komut arka planda şunları yapar:

  • Agent’ı sistem servisi olarak kaydeder (systemd).
  • Gerekli dizin yapılarını (/etc/elastic-agent, /var/log/elastic-agent) oluşturur.
  • Fleet Server ile el sıkışarak ilk policy’sini indirir ve servisi başlatır.

Servisin durumunu doğrulamak için:

sudo systemctl status elastic-agent

Policy Yönetimi: Tek Merkezden Gücü Dağıtmak

Elastic Fleet’in en güçlü yanı policy tabanlı yönetimdir. Bir policy; hangi logların toplanacağını, hangi metriklerin hangi sıklıkla çekileceğini belirten bir kurallar bütünüdür. Sunucularınızı rollerine göre gruplayabilirsiniz (örn: web-servers-policy, db-servers-policy).

Bir sunucunun davranışını değiştirmek istediğinizde, tek yapmanız gereken Kibana arayüzünden ilgili policy’yi editlemektir. Örneğin, tüm web sunucularında Apache log takibini kapatıp yerine Nginx log takibini açmak istiyorsunuz. Bu değişikliği policy üzerinde yaptığınız an, o policy’ye bağlı olan 500 sunucudaki Elastic Agent saniyeler içinde kendini günceller.

Pratik Örnek: Nginx Entegrasyonu Ekleme

Gelin, çalışan bir Elastic Agent’a Kibana üzerinden nasıl dinamik entegrasyon ekleyeceğimize bakalım:

  1. Kibana > Fleet > Agent Policies sayfasına gidin.
  2. Agent’ınızın bağlı olduğu policy’yi seçin.
  3. Add Integration butonuna tıklayın.
  4. Arama çubuğuna Nginx yazın ve entegrasyonu seçin.
  5. Nginx log dosyalarının yollarını (varsayılan: /var/log/nginx/access.log) ve metrik endpoint’ini (stub_status) konfigüre edin.
  6. Save Integration butonuna basarak kaydedin.

Arkanıza yaslanın. Hedef sunucudaki agent, konfigürasyon değişikliğini algılayacak, arka planda Nginx loglarını okumaya başlayacak ve Kibana’da hazır gelen “Nginx Overview” dashboard’larını verilerle dolduracaktır. Sıfır konfigürasyon dosyası editlendi, sıfır servis restart edildi!

Prodüksiyon Tavsiyeleri ve Savaş Hikayeleri

Her şey kağıt üzerinde harika görünse de, production ortamlarında Fleet koştururken dikkat etmeniz gereken bazı can alıcı noktalar var:

1. Resource Limits (Kaynak Sınırları)

Elastic Agent, eski Beats’lere göre biraz daha fazla memory tüketebilir çünkü arka planda birden fazla süreci yönetir. Özellikle çok sayıda log dosyası (wildcard ile binlerce log) izleniyorsa, agent memory limitlerine takılabilir. Sunucularınızda elastic-agent‘ın CPU ve RAM tüketimini mutlaka monitor edin.

2. SSL/TLS Sertifikaları

Fleet Server ile Agent arasındaki iletişim kesinlikle HTTPS olmalıdır. Self-signed sertifika kullanıyorsanız, agent kurulumu sırasında --certificate-authorities parametresiyle CA sertifikanızı belirtmeyi unutmayın. Aksi takdirde agent’lar “x509: certificate signed by unknown authority” hatasıyla kaydolmayacaktır.

3. Fleet Server Ölçekleme

Tek bir Fleet Server kabaca 1000 ila 2000 agent’a kadar sorunsuz hizmet verebilir. Ancak binlerce agent’ın olduğu büyük altyapılarda, Fleet Server’ı arkasında bir Load Balancer (HAProxy, AWS ALB vb.) olacak şekilde multi-node mimaride kurmalısınız.

Fleet Server’ları ölçeklerken şu parametre ile JVM heap boyutunu ve max connection limitlerini optimize edebilirsiniz:

# Örnek environment değişkeni
-e FLEET_SERVER_MAX_CONNECTIONS=5000

Özet

Elastic Fleet ve Agent ikilisi, modern DevOps dünyasındaki monitoring operasyonlarını büyük ölçüde kolaylaştırıyor. Altyapınızı kodla yönetirken (IaC), sunuculara sadece tek bir agent kurup geri kalan tüm konfigürasyonu UI veya Fleet API’leri üzerinden yönetmek, operasyonel yükü ciddi oranda azaltır. Eğer hala eski usul Beats konfigürasyonlarıyla uğraşıyorsanız, Fleet’e geçiş planını hemen sprint’inize eklemenizi öneririm.

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
Temmuz 19 2024

Zabbix 7.x ile Kubernetes Cluster Monitoring

Kubernetes ekosisteminde monitoring denildiğinde akla ilk gelen Prometheus-Grafana ikilisi olsa da, modern devops dünyasında zabbix 7.x sürümüyle kartları yeniden dağıtıyor. Bu yazımızda, legacy sistemlerden aşina olduğumuz bu devasa canavarın, kubernetes cluster’larındaki container metriklerini auto-discovery (LLD) yetenekleriyle nasıl saniyeler içinde yakaladığını, verileri nasıl işlediğini ve Grafana ile nasıl görselleştirdiğini ele alacağız. “Prometheus kurduk ama RAM tüketimi ocağımıza incir ağacı dikti” diyenlerdenseniz, kemerlerinizi bağlayın; Zabbix 7.x’in hafif ve güçlü Kubernetes entegrasyonuna dalıyoruz.

Neden Zabbix 7.x? (Eski Dostun Yeni Numaraları)

Yıllarca Zabbix’i sadece VM’lerin CPU ve disk doluluk oranlarını izlemek için kullandıysanız, kendinizi güncellemenin vakti geldi demektir. Zabbix 7.x, Kubernetes dünyasını yabancı bir gezegen gibi görmüyor. HTTP agent, out-of-the-box gelen gelişmiş Kubernetes template’leri ve JSONPath preprocessing yetenekleri sayesinde API Server üzerinden doğrudan cluster’ın kalbine inebiliyor.

Peki neden Prometheus yerine Zabbix? Cevap basit: Unified Monitoring ve Uzun Vadeli Veri Saklama (Long-term Retention). Eğer cluster dışında fiziksel switch’leriniz, legacy veritabanlarınız ve sanal makineleriniz varsa, hepsini tek bir panele toplamak ve bunu yaparken TSDB (Time Series Database) kaynaklı çılgın RAM maliyetlerinden kaçınmak istiyorsanız, Zabbix 7.x tam size göre.

Adım 1: Kubernetes Cluster Üzerinde Zabbix Helm Deployment

Zabbix’in cluster içindeki gözü kulağı olacak Zabbix Agent 2 ve Zabbix Proxy yapılandırmasını kurarak işe başlıyoruz. Kubernetes API’si ile güvenli bir şekilde konuşabilmek için service account ve rol tanımlamalarına ihtiyacımız var. Neyse ki resmi Helm chart bu işi bizim yerimize hallediyor.

İlk olarak Zabbix topluluk reposunu sistemimize ekleyelim:

helm repo add zabbix-community https://zabbix-community.github.io/helm-charts
helm repo update

Şimdi, cluster metriklerini toplamak için optimize edilmiş bir values.yaml dosyası hazırlayalım. Bu dosyada Zabbix Server adresimizi ve cluster adımızı belirtiyoruz. Aşağıdaki konfigürasyonu zabbix-values.yaml olarak kaydedebilirsiniz:

zabbixProxy:
  enabled: true
  resources:
    limits:
      cpu: 500m
      memory: 512Mi
    requests:
      cpu: 100m
      memory: 128Mi
  env:
    - name: ZBX_HOSTNAME
      value: "k8s-production-proxy"
    - name: ZBX_SERVER_HOST
      value: "zabbix-server.kertenkerem.local" # Zabbix Server IP veya FQDN'iniz

zabbixAgent:
  enabled: true
  resources:
    limits:
      cpu: 200m
      memory: 256Mi
    requests:
      cpu: 50m
      memory: 64Mi
  env:
    - name: ZBX_HOSTNAMEITEM
      value: "system.hostname"

Bu konfigürasyon ile cluster içinde bir DaemonSet olarak Zabbix Agent 2 ve cluster dışındaki ana sunucumuza verileri güvenli ve sıkıştırılmış şekilde iletecek bir Zabbix Proxy ayağa kaldırıyoruz. Kurulumu şu komutla tetikleyelim:

kubectl create namespace monitoring
helm install zabbix zabbix-community/zabbix-helm-ch --namespace monitoring -f zabbix-values.yaml

Adım 2: Auto-Discovery (LLD) ile Metrik Avcılığı

Kubernetes dinamik bir yapıya sahiptir; pod’lar saniyeler içinde ölür, yenileri doğar. Statik IP’ler veya host tanımlamaları burada sökmez. Zabbix 7.x, bu kaosu çözmek için Low-Level Discovery (LLD) mekanizmasını kullanır. Kubernetes API Server üzerinden pods, nodes, namespaces ve services discovery kurallarını çalıştırır.

Zabbix Web UI arayüzüne giriş yaptıktan sonra şu adımları izleyin:

1. API Token Oluşturma

Zabbix Server’ın cluster API’si ile konuşabilmesi için Helm kurulumu sırasında otomatik oluşturulan service account token’ını almamız gerekiyor:

kubectl get secret $(kubectl get serviceaccount zabbix-service-account -n monitoring -o jsonpath="{.secrets[0].name}") -n monitoring -o jsonpath="{.data.token}" | base64 --decode

Not: Kubernetes 1.24 ve üzeri kullanıyorsanız, secret manuel oluşturulmuş olabilir. Helm chart bunu sizin için halletmediyse, service account için bir `kubernetes.io/service-account-token` tipinde Secret oluşturup token’ı oradan okumalısınız.

2. Zabbix Üzerinde Host Tanımlama

  • Configuration -> Hosts -> Create Host yolunu izleyin.
  • Host Name alanına Kubernetes Cluster Production yazın.
  • Templates kısmına “Kubernetes by HTTP” template’ini ekleyin. Bu template, Zabbix 7.0 ile gelen out-of-the-box harika bir canavardır.
  • Macros sekmesine geçiş yapın ve aşağıdaki kritik değişkenleri tanımlayın:
{$KUBE.API.URL} -> https://<kubernetes-api-endpoint>:6443
{$KUBE.API.TOKEN} -> <Bir önceki adımda elde ettiğiniz token>

Bu tanımlamadan sonra Zabbix, HTTP agent yardımıyla cluster API’nize sorgu atmaya başlayacak. Birkaç dakika içinde “Discovery rules” altındaki kuralların tetiklendiğini ve cluster’ınızdaki tüm node’ların, pod’ların ve container’ların otomatik olarak sisteme “Graph” ve “Item” olarak eklendiğini göreceksiniz. İşte auto-discovery’nin gücü!

Adım 3: Grafana Entegrasyonu (Görsel Şölen)

Zabbix’in kendi arayüzündeki grafikler son yıllarda iyileşmiş olsa da, hiçbirimiz yöneticilerimize veya development ekiplerine o 90’lardan kalma görünümlü panelleri göstermek istemeyiz. Bize Grafana lazım.

Grafana üzerinde Zabbix veri kaynağını (datasource) aktifleştirmek için şu adımları izliyoruz:

grafana-cli plugins install alexanderzobnin-zabbix-app
systemctl restart grafana-server

Grafana arayüzüne gidip Connections -> Data Sources -> Add New Data Source dedikten sonra listeden Zabbix’i seçiyoruz. Konfigürasyon ayarlarında dikkat etmeniz gereken kritik noktalar şunlar:

  • URL: http://zabbix-server-ip/zabbix/api_jsonrpc.php
  • Access: Server (Default)
  • Zabbix API Connection: Zabbix admin kullanıcı adı ve şifreniz.

Bağlantıyı test edip kaydettikten sonra, Kubernetes cluster metriklerimizi içeren dashboard’ları tasarlayabiliriz. Örneğin, her pod’un CPU tüketimini dinamik olarak çeken bir panel yazmak istersek, Grafana query alanına şu regex’i girebiliriz:

Group: Kubernetes
Host: /.*/
Application: CPU
Item: /Calculated CPU usage percent/

Bu sorgu sayesinde, cluster’a yeni bir mikroservis deploy edildiğinde hiçbir manuel müdahale yapmadan o servisin CPU grafiği saniyeler içinde Grafana panelinizde belirecektir.

Adım 4: Akıllı Alerting Kuralları

Gecenin saat 3’ünde “Pod restart attı” diye uyanmak istemiyorsanız, Zabbix’in esnek trigger yapısını doğru kurgulamanız gerekir. Klasik CPU doldu alert’leri yerine Kubernetes dünyasına uygun akıllı trigger’lar yazmalıyız.

Örnek 1: CrashLoopBackOff Durumu tespiti

Bir pod sürekli hata alıp kapanıyorsa ve restart sayısı artıyorsa, bu kritik bir durumdur. Zabbix template’i içinde gelen varsayılan kuralı özelleştirebiliriz:

last(/Kubernetes by HTTP/kube.pod.restart_rate[{#POD.NAME}]) > 3 and last(/Kubernetes by HTTP/kube.pod.status[{#POD.NAME}]) = 0

Bu trigger, pod’un son 5 dakika içindeki restart hızı 3’ten fazla ise ve pod “Ready” durumunda değilse alarm üretir. Geçici network kesintilerinde boşuna Slack kanallarınızı spam’lemez.

Örnek 2: Node Disk Basıncı (Disk Pressure)

Kubelet’in node üzerindeki pod’ları evict etmeye başlamadan (yani sistem dışına atmadan) önce diskin dolduğunu anlamamız gerekir:

last(/Kubernetes by HTTP/kube.node.status.disk_pressure[{#NODE.NAME}]) = 1

Bu alarm tetiklendiğinde, Zabbix’in Webhook entegrasyonu sayesinde Slack veya PagerDuty üzerinden anlık bildirim alabilir, hatta otomatik aksiyon (Remote Command) tanımlayarak ilgili node üzerindeki gereksiz docker imajlarını temizleyen bir script çalıştırabilirsiniz.

Zabbix 7.x Kubernetes Monitoring’in Avantaj ve Dezavantajları

Her sistemde olduğu gibi bu mimarinin de güçlü ve zayıf yanları var. Kararınızı vermeden önce bunları masaya yatıralım:

Avantajları Dezavantajları
Düşük kaynak tüketimi (RAM/CPU dostu) Kubernetes native olmaması (Prometheus operator kadar cluster içine entegre değil)
Merkezi yönetim ve güçlü LLD yetenekleri Custom Metric API ile HPA (Horizontal Pod Autoscaler) entegrasyonu görece zor
Uzun vadeli verileri saklamada veritabanı esnekliği (PostgreSQL/TimescaleDB) Grafana template kütüphanesinin Prometheus kadar zengin olmaması

Sonuç

Zabbix 7.x, Kubernetes cluster’larını izlemek için hantal ve “outdated” bir çözüm olmaktan çok uzak. Aksine, kaynak tüketimini minimize etmek isteyen ve tüm IT altyapısını (fiziksel, sanal, container) tek bir merkezi noktadan yönetmeyi hedefleyen kıdemli sistem ve devops mühendisleri için biçilmiş kaftan. Auto-discovery mekanizmasının gücü ve Grafana’nın görsel yetenekleri birleştiğinde, production ortamınızda uçtan uca izlenebilirlik (observability) sağlamak işten bile değil.

Siz de cluster’larınızda Zabbix kullanmayı denediniz mi? Yaşadığınız tecrübeleri veya takıldığınız yerleri yorumlarda bizimle paylaşın, debugging seansına beraber devam edelim!

Category: Genel | LEAVE A COMMENT