Zabbix’te SLA Raporu Oluşturma ve Yönetimi

Yıllarca “uptime yüzde kaç?” sorusunu elle hesaplayarak cevaplamak zorunda kaldıysanız, Zabbix’in SLA modülünü keşfettiğinizde neden bu kadar mutlu olduğumu anlarsınız. Özellikle yöneticilerin aylık raporlar için üstünüze geldiği dönemlerde, SLA verilerini otomatik olarak üretebilmek ciddi bir zaman ve sinir tasarrufu sağlıyor. Bu yazıda Zabbix 6.0 ve üzeri sürümlerde SLA raporlarını nasıl oluşturup yönetebileceğinizi, API üzerinden nasıl otomatize edebileceğinizi ve gerçek dünya senaryolarında nasıl işe yaradığını ele alacağız.

Zabbix SLA Modülüne Genel Bakış

Zabbix 6.0 ile birlikte SLA yönetimi ciddi ölçüde yenilendi. Eski sürümlerde IT Services altında birkaç tıklamayla kaybolan bir özellikken, artık Services menüsü altında bağımsız ve kapsamlı bir modül haline geldi.

Temel mantık şöyle işliyor: Bir veya birden fazla servis tanımlıyorsunuz, bu servislere problem etiketleri (tags) bağlıyorsunuz ve SLA hesaplamaları bu etiketlere dayalı problem kayıtları üzerinden yapılıyor. Eskisi gibi tetikleyici (trigger) bazlı değil, etiket bazlı çalışması büyük bir esneklik sağlıyor.

Bir SLA raporunun temel bileşenleri şunlar:

  • Service: İzlemek istediğiniz servis tanımı (web sunucusu, veritabanı, ödeme sistemi vb.)
  • SLA Definition: Minimum uptime yüzdesi, hesaplama periyodu, servis saatleri
  • Scheduled Downtime: Planlı bakım pencereleri (bu süreler SLA hesabına dahil edilmiyor)
  • SLA Report: Günlük, haftalık, aylık veya yıllık olarak üretilen raporlar

Servis Tanımlaması

İlk adım doğru servis hiyerarşisi kurmak. Örneğin bir e-ticaret platformunu izlediğinizi düşünelim. Üst seviyede “E-Ticaret Platformu” servisi olacak, altında “Web Katmanı”, “Veritabanı Katmanı”, “Ödeme Servisi” gibi alt servisler yer alacak.

Services > Services menüsüne gidin ve yeni bir servis oluşturun. Burada dikkat etmeniz gereken birkaç nokta var:

Algorithm seçimi kritik: Bir servisin durumu nasıl hesaplanacak?

  • Most critical if all children have problems: Tüm alt servisler sorunlu olduğunda üst servis de sorunlu sayılır
  • Most critical of child services: Herhangi bir alt servis sorunluysa üst servis sorunlu
  • Set status to OK: Her zaman OK göster (placeholder servisler için)

Problem bağlamak için etiket tabanlı filtreleme kullanıyoruz. Örneğin web sunucusu servisine şu etiketleri bağlayabilirsiniz:

# Zabbix agent üzerinde özel item tanımlamak için
# /etc/zabbix/zabbix_agentd.d/web_check.conf

UserParameter=web.availability,curl -s -o /dev/null -w "%{http_code}" http://localhost/ | grep -c "200"

Bu item’ı bir trigger’a bağlayıp trigger’a etiket eklemeniz gerekiyor. Trigger etiketleri servis tanımındaki filtrelerle eşleştiğinde, o trigger’dan üretilen problemler ilgili servise atanıyor.

SLA Tanımı Oluşturma

Services > SLA menüsünden yeni bir SLA tanımı oluşturuyorsunuz. Bir SLA tanımında şu alanlar bulunuyor:

Name: SLA’nın adı. Anlamlı isimler koyun, “SLA_1” değil “Kritik Servisler – Aylık %99.9” gibi.

SLO (Service Level Objective): Hedeflenen minimum uptime yüzdesi. Örneğin 99.9 yazarsanız aylık maksimum 43 dakika 49 saniyelik kesinti hakkınız var demektir.

Effective date: SLA’nın geçerlilik başlangıç tarihi. Geriye dönük veri toplamak istiyorsanız eski bir tarih girebilirsiniz, ancak o tarihten itibaren veri olması gerekiyor.

Schedule: Servis saatleri. 7/24 mi yoksa sadece iş günleri mi? Eğer “Pazartesi-Cuma 09:00-18:00” seçerseniz, gece ve hafta sonu yaşanan kesintiler SLA hesabına dahil edilmiyor. Bu özellik kritik.

Timezone: Servis saati hesaplamasında hangi saat dilimi kullanılacak. Türkiye için Europe/Istanbul seçin.

Örnek bir senaryo: Kurumsal ERP sisteminiz için SLA tanımı yapıyorsunuz. Sistem sadece iş günleri kullanıldığından, hafta sonu kesintileri SLA’yı etkilememeli. Bu durumda schedule’ı iş günleri 08:00-19:00 olarak ayarlayabilirsiniz.

API ile SLA Yönetimi

Zabbix API’si SLA operasyonları için oldukça yetenekli. Özellikle birden fazla müşteriyi veya departmanı yönetiyorsanız, servisleri ve SLA tanımlarını API üzerinden programatik olarak oluşturmak büyük kolaylık sağlıyor.

Önce API token almanız gerekiyor:

curl -s -X POST 
  -H "Content-Type: application/json" 
  -d '{
    "jsonrpc": "2.0",
    "method": "user.login",
    "params": {
      "username": "Admin",
      "password": "zabbix"
    },
    "id": 1
  }' 
  http://zabbix.sirketiniz.com/zabbix/api_jsonrpc.php

Bu size bir auth token döndürecek. Bunu bir değişkene atayıp sonraki çağrılarda kullanın:

TOKEN=$(curl -s -X POST 
  -H "Content-Type: application/json" 
  -d '{"jsonrpc":"2.0","method":"user.login","params":{"username":"Admin","password":"zabbix_sifresi"},"id":1}' 
  http://zabbix.sirketiniz.com/zabbix/api_jsonrpc.php | 
  python3 -c "import sys,json; print(json.load(sys.stdin)['result'])")

echo "Token: $TOKEN"

Şimdi API üzerinden SLA raporu çekelim. sla.getsli metodu SLI (Service Level Indicator) verilerini döndürüyor:

curl -s -X POST 
  -H "Content-Type: application/json" 
  -d "{
    "jsonrpc": "2.0",
    "method": "sla.getsli",
    "params": {
      "slaid": "1",
      "period": 1,
      "periods": 3
    },
    "auth": "$TOKEN",
    "id": 2
  }" 
  http://zabbix.sirketiniz.com/zabbix/api_jsonrpc.php | python3 -m json.tool

Buradaki period değerleri şunlar:

  • 0: Günlük
  • 1: Haftalık
  • 2: Aylık
  • 3: Üç aylık
  • 4: Yıllık

periods ise kaç periyot geriye gidileceğini belirtiyor. Yukarıdaki örnek son 3 haftanın verilerini getiriyor.

Otomatik Rapor Oluşturma Scripti

Çoğu ortamda yönetim aylık SLA raporlarını PDF veya e-posta olarak istiyor. Aşağıdaki Python scripti Zabbix API’den veri çekip basit bir rapor oluşturuyor:

#!/usr/bin/env python3
# /opt/scripts/zabbix_sla_report.py

import requests
import json
from datetime import datetime
import smtplib
from email.mime.text import MIMEText

ZABBIX_URL = "http://zabbix.sirketiniz.com/zabbix/api_jsonrpc.php"
ZABBIX_USER = "sla_readonly"
ZABBIX_PASS = "guclu_sifre_buraya"

def get_auth_token():
    payload = {
        "jsonrpc": "2.0",
        "method": "user.login",
        "params": {"username": ZABBIX_USER, "password": ZABBIX_PASS},
        "id": 1
    }
    r = requests.post(ZABBIX_URL, json=payload)
    return r.json()["result"]

def get_all_slas(token):
    payload = {
        "jsonrpc": "2.0",
        "method": "sla.get",
        "params": {"output": "extend"},
        "auth": token,
        "id": 2
    }
    r = requests.post(ZABBIX_URL, json=payload)
    return r.json()["result"]

def get_sli_data(token, sla_id, periods=1):
    payload = {
        "jsonrpc": "2.0",
        "method": "sla.getsli",
        "params": {
            "slaid": sla_id,
            "period": 2,  # Aylik
            "periods": periods
        },
        "auth": token,
        "id": 3
    }
    r = requests.post(ZABBIX_URL, json=payload)
    return r.json()["result"]

def generate_report():
    token = get_auth_token()
    slas = get_all_slas(token)
    
    report_lines = []
    report_lines.append(f"=== Zabbix SLA Raporu - {datetime.now().strftime('%Y-%m')} ===n")
    
    for sla in slas:
        sli_data = get_sli_data(token, sla["slaid"])
        report_lines.append(f"nServis: {sla['name']}")
        report_lines.append(f"Hedef SLO: %{sla['slo']}")
        
        if "sli" in sli_data:
            for period_data in sli_data["sli"]:
                for service_id, metrics in period_data.items():
                    uptime_pct = metrics.get("uptime_percentage", 0)
                    status = "BASARILI" if float(uptime_pct) >= float(sla["slo"]) else "BASARISIZ"
                    report_lines.append(f"  Gerceklesen Uptime: %{uptime_pct} [{status}]")
    
    return "n".join(report_lines)

if __name__ == "__main__":
    rapor = generate_report()
    print(rapor)

Bu scripti cron’a ekleyerek her ayın ilk günü otomatik çalıştırabilirsiniz:

# /etc/cron.d/zabbix-sla-report
0 8 1 * * zabbix /usr/bin/python3 /opt/scripts/zabbix_sla_report.py >> /var/log/zabbix/sla_reports.log 2>&1

Planlı Bakım Pencereleri (Scheduled Downtime)

SLA yönetiminin en sık atlanan kısmı planlı bakım pencerelerinin doğru tanımlanması. Eğer Cumartesi gecesi yaptığınız 2 saatlik bakımı sisteme girmezsseniz, o süre downtime olarak hesaplanır ve SLA’nız gereksiz yere düşer.

Zabbix’te bunu iki farklı şekilde yapabilirsiniz. Birincisi servis üzerinde doğrudan “Scheduled downtime” tanımlamak, ikincisi “Maintenance” periyodu oluşturmak.

Bakım penceresi oluşturmak için API kullanımı:

# Bakim penceresi olusturma
curl -s -X POST 
  -H "Content-Type: application/json" 
  -d "{
    "jsonrpc": "2.0",
    "method": "maintenance.create",
    "params": {
      "name": "Haftalik Bakim - $(date +%Y-%m-%d)",
      "active_since": $(date -d 'next saturday 02:00' +%s),
      "active_till": $(date -d 'next saturday 04:00' +%s),
      "maintenance_type": 0,
      "hostids": ["10084", "10085"],
      "timeperiods": [{
        "timeperiod_type": 0,
        "start_date": $(date -d 'next saturday 02:00' +%s),
        "period": 7200
      }]
    },
    "auth": "$TOKEN",
    "id": 4
  }" 
  http://zabbix.sirketiniz.com/zabbix/api_jsonrpc.php

Servis seviyesinde scheduled downtime eklemek içinse servis güncellemesi yapmanız gerekiyor. Bu özellikle tek bir servisin bakımda olduğu, diğerlerinin etkilenmediği senaryolar için kullanışlı.

Gerçek Dünya Senaryosu: Hosting Firması Müşteri SLA Raporları

Çalıştığım bir hosting firmasında yaklaşık 40 farklı müşteri için aylık SLA raporları üretmemiz gerekiyordu. Her müşterinin farklı SLO gereksinimleri vardı: bazıları %99.5 ile yetinirken, bazı fintech müşterileri %99.95 istiyordu.

Bu problemi çözmek için her müşteriye özel bir servis hiyerarşisi oluşturduk ve müşteri ID’sini tag olarak kullandık. Böylece bir host’ta yaşanan problem sadece ilgili müşterinin servisini etkiliyordu.

Trigger template’ımıza şu etiketleri ekledik:

# Zabbix frontend'inde template trigger'a eklenecek etiketler
# Tag Name: customer_tier
# Tag Value: {$CUSTOMER_TIER}

# Tag Name: service_component  
# Tag Value: {$SERVICE_COMPONENT}

# Host makroları:
# {$CUSTOMER_TIER} = gold | silver | bronze
# {$SERVICE_COMPONENT} = web | database | cache

Bu sayede “gold” tier müşterilerin web servislerini izleyen ayrı bir SLA tanımı oluşturabildik. Raporlama scripti de müşteri bazında ayrıştırılmış veriler üretir hale geldi.

SLA Verilerinin Grafana ile Görselleştirilmesi

Zabbix’in kendi SLA rapor ekranı işlevsel ama görsel olarak sınırlı. Yöneticilere daha etkileyici dashboard’lar sunmak istiyorsanız Grafana entegrasyonu yapabilirsiniz.

Grafana-Zabbix eklentisini kurabilir, ancak SLA verileri için doğrudan Zabbix API’yi kullanan bir veri kaynağı oluşturmak daha güvenilir. Basit bir Flask uygulaması bu iş için yeterli:

#!/usr/bin/env python3
# /opt/scripts/sla_api_proxy.py
# Grafana icin basit bir SLA proxy API

from flask import Flask, jsonify, request
import requests

app = Flask(__name__)

ZABBIX_URL = "http://localhost/zabbix/api_jsonrpc.php"

@app.route("/api/sla/<sla_id>/monthly")
def get_monthly_sla(sla_id):
    # Token alma islemi (uretim ortaminda cache'leyin)
    auth_response = requests.post(ZABBIX_URL, json={
        "jsonrpc": "2.0", "method": "user.login",
        "params": {"username": "readonly", "password": "sifre"},
        "id": 1
    })
    token = auth_response.json()["result"]
    
    # SLI verisi cekme
    sli_response = requests.post(ZABBIX_URL, json={
        "jsonrpc": "2.0", "method": "sla.getsli",
        "params": {"slaid": sla_id, "period": 2, "periods": 12},
        "auth": token, "id": 2
    })
    
    return jsonify(sli_response.json()["result"])

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=5001)

Sık Yapılan Hatalar ve Çözümleri

Birkaç yıllık deneyimden damıttığım hatalar şunlar:

Etiket filtrelerini yanlış yazmak: Servis tanımında problem etiket filtrelerini büyük/küçük harf duyarlı yazmanız gerekiyor. service:web ile Service:Web farklı şeyler. Trigger etiketlerini yazarken tutarlı bir standart belirleyin ve bunu zorunlu kılın.

Timezone karışıklığı: Zabbix sunucusu UTC çalışıyor ama servis saatlerini yerel saatle tanımlamak istiyorsunuz. SLA tanımındaki timezone ayarını mutlaka doğrulayın. Yanlış timezone, servis saati hesaplamalarını tamamen bozuyor.

Eski trigger’ları servise bağlamamak: Zabbix 6.0 öncesinden geçiş yaptıysanız, eski trigger tabanlı “IT Services” verilerinin yeni SLA modülüne otomatik taşınmadığını unutmayın. Sıfırdan yapılandırmanız gerekiyor.

Downtime kaydetmek: Birçok ekip planlı bakımları Zabbix’e girmeden geçiştiriyor. Sonradan “bu ay neden %98.7 çıktı” diye soruşturma yapmak zorunda kalıyorsunuz. Bakım pencerelerini sistematik olarak kaydetmek için runbook’unuza bunu ekleyin.

Readonly kullanıcı için yetki sorunu: API ile rapor çeken scriptlerde Admin hesabı kullanmayın. SLA verilerini okuma yetkisi olan ayrı bir readonly kullanıcı oluşturun ve ona sadece ilgili host gruplarını görme izni verin.

SLA Eşiği Aşıldığında Alarm Üretmek

Zabbix’te SLA ihlallerini otomatik olarak algılayıp alarm üretmek de mümkün. Bunun için sla.getsli API çağrısından dönen verileri periyodik olarak kontrol eden ve eşik aşıldığında bildirim gönderen bir script yazabilirsiniz:

#!/bin/bash
# /opt/scripts/sla_alert_check.sh
# Her saat calistir, SLA ihlali varsa Telegram'a bildir

ZABBIX_URL="http://localhost/zabbix/api_jsonrpc.php"
TELEGRAM_TOKEN="bot_token_buraya"
TELEGRAM_CHAT_ID="-100xxxxxxxxx"
ESIK=99.5

TOKEN=$(curl -s -X POST -H "Content-Type: application/json" 
  -d '{"jsonrpc":"2.0","method":"user.login","params":{"username":"readonly","password":"sifre"},"id":1}' 
  $ZABBIX_URL | python3 -c "import sys,json; print(json.load(sys.stdin)['result'])")

# Tum SLA'lari al ve kontrol et
SLA_LIST=$(curl -s -X POST -H "Content-Type: application/json" 
  -d "{"jsonrpc":"2.0","method":"sla.get","params":{"output":"extend"},"auth":"$TOKEN","id":2}" 
  $ZABBIX_URL | python3 -c "
import sys, json
data = json.load(sys.stdin)
for sla in data['result']:
    print(sla['slaid'] + ':' + sla['name'] + ':' + sla['slo'])
")

while IFS=: read -r sla_id sla_name slo; do
  UPTIME=$(curl -s -X POST -H "Content-Type: application/json" 
    -d "{"jsonrpc":"2.0","method":"sla.getsli","params":{"slaid":"$sla_id","period":1,"periods":1},"auth":"$TOKEN","id":3}" 
    $ZABBIX_URL | python3 -c "
import sys, json
data = json.load(sys.stdin)
try:
    sli = data['result']['sli'][0]
    for sid, metrics in sli.items():
        print(metrics.get('uptime_percentage', '100'))
        break
except:
    print('100')
")
  
  IHLAL=$(python3 -c "print('1' if float('$UPTIME') < float('$slo') else '0')")
  
  if [ "$IHLAL" = "1" ]; then
    MESAJ="UYARI: $sla_name SLA ihlali! Gerceklesen: %$UPTIME, Hedef: %$slo"
    curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_TOKEN/sendMessage" 
      -d "chat_id=$TELEGRAM_CHAT_ID&text=$MESAJ" > /dev/null
  fi
done <<< "$SLA_LIST"

Sonuç

Zabbix’in SLA modülü, doğru yapılandırıldığında gerçekten değerli bir araç. En büyük avantajı mevcut izleme altyapınıza entegre olması ve ekstra bir araç gerektirmemesi. Yöneticiye “geçen ay %99.87 uptime sağladık” diyebilmek, soyut alarm sayılarından çok daha ikna edici.

Başlangıç için önerim şu: önce tek bir kritik servisle başlayın, SLA tanımını doğru kurun, bir ay gerçek veri üretin. Sonuçları elle hesapladığınız değerlerle karşılaştırın. Tutuyorsa diğer servisleri de ekleyin. API entegrasyonlarını ve otomasyonları ikinci aşamaya bırakın.

Etiket standartlarınızı baştan oturup belirlemezseniz, birkaç ay sonra kaotik bir yapıyla karşılaşırsınız. Bu noktaya iki kez geldim, ikinci seferde sıfırdan başlamak zorunda kaldım. Siz bu hatayı yapmayın.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir