kertenkerem_
· DevOps · 5 dk okuma

Zabbix + Alertmanager: PagerDuty ve Slack Entegrasyonu

Gece saat 03:00. Cep telefonunuz ardı ardına titriyor. Zabbix “CPU usage high on prod-db-01” başlıklı tam 142 SMS göndermiş. Gözlerinizi oğuşturarak bilgisayarı açıyorsunuz ve olayın planlı bir veritabanı yedeğinden (backup job) ibaret olduğunu, ne diskin ne de veritabanının çöktüğünü görüyorsunuz. Sinirden köpürürken kendinize soruyorsunuz: “Neden bu alarmları gruplayamadım? Neden nöbetçi arkadaşım yerine tüm ekip ayağa kalktı?”

Geleneksel izleme canavarımız Zabbix ile modern bulut dünyasının alarm yönetim standardı Alertmanager’ı evlendirmenin vakti gelmiş. Bu yazıda Zabbix’in topladığı metrik ve trigger’ları Alertmanager’a köprüleyecek, oradan da Slack ve PagerDuty entegrasyonlarıyla gürültüsüz, insan odaklı bir oncall yönetimi kuracağız.

Neden doğrudan Zabbix değil de Alertmanager?

Zabbix metrik toplama (polling), agent yönetimi ve esnek trigger tanımlama konularında çok iyi bir araç. Ama iş alarm yönetimine (alert routing, deduplication, inhibition ve silencing) gelince aksiyon (Action) arayüzü hantal kalıyor. GitOps felsefesine uymuyor, sürüm kontrolü (version control) zor ve karmaşık eskalasyon senaryolarında konfigürasyon cehennemine dönüşebiliyor.

Alertmanager Prometheus ekosisteminin kalbidir ama yalnızca Prometheus ile sınırlı olmak zorunda değildir. Bize sunduğu avantajlar şunlar:

  • Deduplication (tekilleştirme): Aynı anda patlayan 50 benzer alarmı tek bir Slack mesajında birleştirir.
  • Inhibition (bastırma): Bir veri merkezi (datacenter) çöktüyse o merkezdeki 100 makine için “Node Down” alarmı göndermez, yalnızca “Datacenter Offline” alarmını geçirir, diğerlerini bastırır.
  • Dynamic routing (dinamik yönlendirme): Alarma basılan etiketlere (labels) göre alarmı doğru ekibe (DBA, Network, Frontend) yönlendirir.

Adım 1: Zabbix webhook ile Alertmanager API köprüsü kurmak

İlk iş, Zabbix’te bir trigger tetiklendiğinde bunu Alertmanager’ın /api/v2/alerts endpoint’ine gönderecek bir “Media Type” tanımlamak. Alertmanager, kendisine gönderilen JSON payload’unda belirli standartlar bekler.

Zabbix arayüzünde Administration -> Media Types sekmesine gidin ve “Create media type” butonuna tıklayın. Tipi Webhook olarak seçin ve aşağıdaki parametreleri ekleyin:

// Zabbix Webhook Script içeriği
try {
    var params = JSON.parse(value),
        req = new HttpRequest(),
        payload = [];

    if (typeof params.AlertmanagerURL === 'undefined') {
        throw 'AlertmanagerURL parametresi eksik.';
    }

    // Alertmanager API v2 formatı
    var alert = {
        "labels": {
            "alertname": params.AlertName,
            "severity": params.Severity,
            "instance": params.HostName,
            "service": params.Service || "infrastructure",
            "environment": params.Environment || "production"
        },
        "annotations": {
            "summary": params.TriggerDescription,
            "value": params.TriggerValue,
            "zabbix_url": params.ZabbixURL + "/tr_events.php?triggerid=" + params.TriggerID
        }
    };

    // Zabbix alarm durumuna göre durumu eşle (Eğer OK ise çözüldü olarak gönder)
    if (params.TriggerStatus === 'OK') {
        alert["endsAt"] = new Date().toISOString();
    } else {
        alert["startsAt"] = new Date().toISOString();
    }

    payload.push(alert);

    req.addHeader('Content-Type: application/json');
    var response = req.post(params.AlertmanagerURL + '/api/v2/alerts', JSON.stringify(payload));

    if (req.getStatus() !== 200 && req.getStatus() !== 201) {
        throw 'HTTP hatası: ' + req.getStatus() + '\nResponse: ' + response;
    }

    return 'OK';
} catch (error) {
    Zabbix.log(3, 'Alertmanager webhook hatası: ' + error);
    throw error;
}

Bu JS kodu, Zabbix trigger’ı tetiklendiğinde ya da çözüldüğünde (OK durumuna geçtiğinde) durumu RFC3339 formatında zaman damgasıyla birlikte Alertmanager’a iletir. Alertmanager alarmın çözüldüğünü (resolved) anlar ve Slack/PagerDuty üzerindeki açık alarmı otomatik olarak kapatır.

Adım 2: Alertmanager konfigürasyonu (`alertmanager.yml`)

Şimdi Alertmanager tarafında bu alarmları nasıl karşılayacağımızı ve nereye yönlendireceğimizi tanımlayalım. Production ortamlarında genellikle kritik alarmların PagerDuty’ye (dolayısıyla nöbetçi mühendisin telefonuna), uyarı seviyesindeki alarmların ise yalnızca Slack kanalına gitmesini isteriz.

global:
  resolve_timeout: 5m

route:
  group_by: ['alertname', 'instance', 'environment']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'slack-default'
  routes:
    # Kritik üretim alarmları hem Slack'e hem PagerDuty'ye gitsin
    - match:
        severity: 'disaster'
        environment: 'production'
      receiver: 'pagerduty-critical'
      continue: true
    
    # Tüm üretim alarmları Slack kanalına düşsün
    - match:
        environment: 'production'
      receiver: 'slack-production'

receivers:
- name: 'slack-default'
  slack_configs:
  - api_url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
    channel: '#ops-alerts-test'
    send_resolved: true
    text: "Alarm: {{ .CommonAnnotations.summary }}\nSeverity: {{ .CommonLabels.severity }}\nHost: {{ .CommonLabels.instance }}"

- name: 'slack-production'
  slack_configs:
  - api_url: 'https://hooks.slack.com/services/T00000000/B00000000/YYYYYYYYYYYYYYYYYYYYYYYY'
    channel: '#prod-alerts'
    send_resolved: true
    title: "[{{ .Status | toUpper }}] {{ .CommonLabels.alertname }}"
    text: "Host: {{ .CommonLabels.instance }}\nDetay: {{ .CommonAnnotations.summary }}\nZabbix Linki: {{ .CommonAnnotations.zabbix_url }}"

- name: 'pagerduty-critical'
  pagerduty_configs:
  - service_key: 'YOUR_PAGERDUTY_INTEGRATION_KEY_HERE'
    severity: 'critical'
    send_resolved: true
    client: 'Alertmanager'
    client_url: 'https://alertmanager.kertenkerem.net'
    description: "{{ .CommonAnnotations.summary }} - Host: {{ .CommonLabels.instance }}"

Adım 3: PagerDuty’de on-call ve eskalasyon politikaları

Alertmanager entegrasyonu bittikten sonra sıra PagerDuty’de. Orada bir servis (Service) oluşturup entegrasyon tipini “Prometheus/Alertmanager” seçtiğinizde, yukarıdaki YAML dosyasında kullandığımız service_key (Integration Key) değerini alırsınız.

İş yalnızca entegrasyonla bitmiyor. Gerçek bir oncall kültürü için şu üç yapıyı kurmanız gerekir:

1. Schedules (nöbet takvimleri)

Haftalık rotasyonlar tanımlayın. Örneğin her Salı günü saat 09:00’da nöbet bir sonraki mühendise geçsin. PagerDuty’de Primary ve Secondary (yedek) olmak üzere iki ayrı takvim oluşturmak hayat kurtarır. Primary nöbetçisine o an ulaşılamıyorsa (örneğin uçaktaysa) sistem otomatik olarak yedek nöbetçiyi arar.

2. Escalation policies (eskalasyon politikaları)

Alarmların sahipsiz kalmaması için eskalasyon zinciri şart. Örnek bir kurumsal politika şöyle olabilir:

  • Adım 1: Alarm tetiklendiğinde o anki nöbetçiyi (Primary) ara ve SMS gönder. (0. dakika)
  • Adım 2: 10 dakika içinde “Acknowledge” (onay) gelmezse yedek nöbetçiyi (Secondary) ara. (10. dakika)
  • Adım 3: Hâlâ ses çıkmıyorsa tüm DevOps ekibine push notification at ve takım liderini devreye sok. (20. dakika)

3. Slack entegrasyonu ve ChatOps

PagerDuty Slack uygulamasını kurarsanız alarmı Slack kanalından tek tıkla üstlenebilir (Acknowledge) ya da çözebilirsiniz (Resolve). Gece yarısı telefondan PagerDuty uygulamasına girmeye çalışırken harcayacağınız 30 saniyeyi geri kazanırsınız.

Alert fatigue (alarm yorgunluğu) ile savaşmak

Sistemi kurduk, ama her gün 500 defa çalan bir pager, bir süre sonra mühendislerin uyarıları görmezden gelmesine (alert fatigue) yol açar. Bunu önlemek için şu taktikleri uygulayın:

  • PagerDuty’ye yalnızca aksiyon alınabilir alarmları gönderin: “Disk doluluğu %81 oldu” bir PagerDuty alarmı değildir, Slack’e gitmesi yeter. “Disk doluluğu %95 ve 10 dakika içinde tamamen dolacak” alarmı ise nöbetçiyi yataktan kaldırmalıdır.
  • Inhibit rules kullanın: Switch çöktüğünde arkasındaki 30 sunucu için tek tek “ping down” alarmı almamak için Alertmanager inhibit kurallarını tanımlayın.
  • Susturma (silences): Planlı bakım çalışmalarından önce Alertmanager ya da PagerDuty arayüzünden ilgili servisleri mutlaka susturun (Silence).

Özet

Zabbix’in köklü izleme yeteneklerini Alertmanager’ın modern yönlendirme mimarisiyle birleştirmek altyapı yönetiminde çağ atlatır. Production ortamınızdaki anomalileri saniyeler içinde yakalar, ekibinizi de gereksiz gürültülü alarmlardan korumuş olursunuz.

Bir sonraki yazıda Alertmanager’da gelişmiş inhibit_rules yazımını inceleyeceğiz. O zamana kadar alarmınız az, uykunuz bol olsun.