Grafana Alerting: Panoya Dayalı Uyarı Tanımlama

Üretim ortamında bir servis çöktüğünde ilk öğrenen sen olmak istiyorsun, değil mi? Telefona bakıyorsun, müşteriden şikayet gelmiş, sen hala habersizsin. Bu senaryo sysadmin’lerin kabusu. Grafana Alerting tam bu noktada devreye giriyor ve doğru kurulduğunda seni bu utanç verici durumdan kurtarıyor.

Bu yazıda Grafana’nın panel tabanlı uyarı sistemini sıfırdan nasıl kuracağını, gerçek dünya senaryolarıyla birlikte anlatacağım. Prometheus metrikleriyle çalışan bir ortam varsayıyorum ama konsept diğer veri kaynaklarına da uygulanabilir.

Grafana Alerting Mimarisi Nedir?

Grafana 8.x ile birlikte gelen Unified Alerting sistemi, eski panel bazlı uyarı sisteminin yerini aldı. Eski sistemde her panel için ayrı ayrı uyarı tanımlıyordun ve bu yönetimi zorlaştırıyordu. Yeni sistemde ise merkezi bir uyarı yöneticisi var.

Temel bileşenler şunlar:

  • Alert Rule: Hangi koşulda uyarı tetikleneceğini tanımlar
  • Contact Point: Uyarının gideceği hedef (Slack, email, PagerDuty vb.)
  • Notification Policy: Hangi uyarının hangi contact point’e gideceğini belirler
  • Silences: Belirli uyarıları geçici olarak susturmak için kullanılır
  • Alert Groups: Benzer uyarıları gruplar

Grafana Alerting arka planda Prometheus’un Alertmanager konseptini kullanıyor. Zaten harici Alertmanager ile entegre de çalışabiliyor.

Ön Gereksinimler

Önce ortamın hazır olduğunu doğruyalım. Çalışan bir Prometheus ve Grafana instance’ın olması gerekiyor.

# Prometheus ve Grafana servis durumlarını kontrol et
systemctl status prometheus
systemctl status grafana-server

# Prometheus hedeflerinin çalışıp çalışmadığını kontrol et
curl -s http://localhost:9090/api/v1/targets | python3 -m json.tool | grep "health"

# Grafana API'sinin ayakta olduğunu doğrula
curl -s http://localhost:3000/api/health

Grafana konfigürasyon dosyasında alerting’in aktif olduğundan emin ol:

# /etc/grafana/grafana.ini dosyasını düzenle
sudo nano /etc/grafana/grafana.ini

Şu satırların aktif olduğunu kontrol et:

[unified_alerting]
enabled = true

[alerting]
enabled = false

Dikkat et: Eski [alerting] bölümü false olmalı, [unified_alerting] ise true. İkisi aynı anda aktif olamaz.

Değişiklikten sonra Grafana’yı yeniden başlat:

sudo systemctl restart grafana-server
sudo journalctl -u grafana-server -f --no-pager | tail -20

İlk Contact Point Tanımlama

Uyarı kuralı yazmadan önce uyarıların nereye gideceğini belirlemen gerekiyor. Alerting > Contact Points menüsünden yeni bir contact point ekle.

Slack entegrasyonu için webhook URL’i almanın en pratik yolu Slack’te bir uygulama oluşturmak. Ama daha hızlı test için gelen webhook URL’ini doğrudan kullanabilirsin.

Grafana API üzerinden contact point eklemek istersen:

curl -X POST 
  http://admin:adminpassword@localhost:3000/api/v1/provisioning/contact-points 
  -H 'Content-Type: application/json' 
  -d '{
    "name": "slack-prod-alerts",
    "type": "slack",
    "settings": {
      "url": "https://hooks.slack.com/services/TXXXXXXXX/BXXXXXXXX/XXXXXXXXXXXXXXXX",
      "channel": "#infra-alerts",
      "title": "{{ template "slack.default.title" . }}",
      "text": "{{ template "slack.default.text" . }}"
    }
  }'

Email contact point için SMTP konfigürasyonu da grafana.ini‘ye eklenmeli:

[smtp]
enabled = true
host = smtp.yourcompany.com:587
user = [email protected]
password = your_smtp_password
from_address = [email protected]
from_name = Grafana Alerting
starttls_policy = MandatoryStartTLS

Panel Tabanlı Alert Rule Oluşturma

Şimdi asıl konuya geliyoruz. Mevcut bir Grafana panosundaki bir panelden uyarı tanımlamak için iki yol var: doğrudan panel editöründen veya Alerting menüsünden. Her ikisini de göstereceğim.

CPU Kullanım Uyarısı

En klasik senaryo: CPU kullanımı %85’i geçince uyarı ver. Panel editöründe Alert sekmesine geç ve New alert rule butonuna tıkla.

Prometheus sorgusu şöyle olmalı:

# Panel query olarak bu PromQL'i gir
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# Bu sorgu her instance için CPU kullanım yüzdesini döndürür
# "by (instance)" etiketi sayesinde her sunucu ayrı ayrı değerlendirilir

Alert rule konfigürasyonu:

  • Rule name: high-cpu-usage
  • Folder: Infrastructure
  • Evaluation group: linux-servers (15s interval)
  • Pending period: 5m (5 dakika boyunca koşul sağlanırsa uyarı gönder)

Threshold kısmında:

  • Condition: IS ABOVE 85
  • For: 5m

Pending period çok önemli. Bunu 0 yaparsan anlık spike’larda sürekli uyarı alırsın. 5 dakika koymak, geçici yüklenmeleri filtreler.

Disk Doluluk Uyarısı

Disk %90’ı dolduğunda uyarı almak istiyorsun. Bu sefer birden fazla threshold kuralı ekleyelim.

# Grafana panel sorgusu
(node_filesystem_avail_bytes{fstype!~"tmpfs|fuse.lxcfs|squashfs",mountpoint!="/"} 
/ node_filesystem_size_bytes{fstype!~"tmpfs|fuse.lxcfs|squashfs",mountpoint!="/"}) 
* 100 < 100

Daha temiz bir sorgu için etiket filtrelerini iyi ayarla. tmpfs ve squashfs filesystem’larını dışarda bırakmak gereksiz gürültüyü önler.

İki aşamalı uyarı için iki ayrı kural tanımlayabilirsin:

# Uyarı seviyesi - disk %80 doldu
(1 - (node_filesystem_avail_bytes / node_filesystem_size_bytes)) * 100 > 80

# Kritik seviye - disk %90 doldu  
(1 - (node_filesystem_avail_bytes / node_filesystem_size_bytes)) * 100 > 90

Servis Availability Uyarısı

Bir web servisinin up/down durumunu izlemek için Blackbox Exporter kullanıyorsan:

# HTTP endpoint kontrolü - 0 değeri servisin down olduğu anlamına gelir
probe_success{job="blackbox-http"} == 0

# Daha spesifik - belirli bir URL için
probe_success{instance="https://api.yoursite.com/health"} == 0

Bu senaryoda pending period’u düşük tut. Servis gerçekten düştüyse 1 dakika bile uzun sürebilir:

  • Pending period: 2m
  • Condition: IS BELOW 1

Alert Rule API ile Toplu Tanımlama

Onlarca sunucu yönetiyorsan tek tek GUI’den kural eklemek saçmalık. Provisioning dosyaları veya API kullan.

# YAML provisioning dosyası oluştur
sudo nano /etc/grafana/provisioning/alerting/linux-servers.yaml
apiVersion: 1

groups:
  - orgId: 1
    name: linux-servers
    folder: Infrastructure
    interval: 1m
    rules:
      - uid: linux-cpu-alert-001
        title: High CPU Usage
        condition: C
        data:
          - refId: A
            queryType: ''
            relativeTimeRange:
              from: 600
              to: 0
            datasourceUid: prometheus-uid
            model:
              expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
              intervalMs: 1000
              maxDataPoints: 43200
              refId: A
          - refId: C
            queryType: ''
            relativeTimeRange:
              from: 0
              to: 0
            datasourceUid: __expr__
            model:
              conditions:
                - evaluator:
                    params:
                      - 85
                    type: gt
                  operator:
                    type: and
                  query:
                    params:
                      - A
                  reducer:
                    type: last
              refId: C
              type: classic_conditions
        noDataState: NoData
        execErrState: Error
        for: 5m
        annotations:
          description: "CPU kullanimi {{ $labels.instance }} sunucusunda %{{ $values.A | printf "%.1f" }} seviyesine ulasti."
          summary: "Yuksek CPU kullanimi tespit edildi"
        labels:
          severity: warning
          team: infra

Dosyayı kaydedip Grafana’yı yeniden başlattığında kurallar otomatik yükleniyor:

sudo systemctl reload grafana-server
# veya
sudo systemctl restart grafana-server

# Kuralların yüklendiğini kontrol et
curl -s http://admin:adminpassword@localhost:3000/api/ruler/grafana/api/v1/rules | python3 -m json.tool

Notification Policy Yapılandırması

Contact point tanımladın, kural yazdın. Şimdi hangisinin nereye gideceğini belirlemelisin. Alerting > Notification Policies menüsüne git.

Default policy her şeyi yakalar. Ama production’da severity ve team etiketlerine göre yönlendirme yapmak çok daha mantıklı.

# API ile notification policy güncelleme
curl -X PUT 
  http://admin:adminpassword@localhost:3000/api/v1/provisioning/policies 
  -H 'Content-Type: application/json' 
  -d '{
    "receiver": "default-email",
    "group_by": ["grafana_folder", "alertname"],
    "group_wait": "30s",
    "group_interval": "5m",
    "repeat_interval": "4h",
    "routes": [
      {
        "receiver": "slack-prod-alerts",
        "matchers": ["severity = critical"],
        "group_wait": "10s",
        "group_interval": "1m",
        "repeat_interval": "1h"
      },
      {
        "receiver": "slack-infra-channel",
        "matchers": ["team = infra"],
        "continue": true
      },
      {
        "receiver": "pagerduty-oncall",
        "matchers": ["severity = critical", "env = production"],
        "group_wait": "0s"
      }
    ]
  }'

Önemli parametreler:

  • group_wait: İlk uyarıdan önce bekleme süresi. Başka uyarılar gruba dahil edilir.
  • group_interval: Aynı gruptaki yeni uyarılar için bekleme
  • repeat_interval: Çözülmemiş uyarı için tekrar bildirim süresi
  • continue: true olunca eşleşme sonrası diğer route’lara da bakar

Uyarı Template’leri Özelleştirme

Varsayılan uyarı mesajları genelde yeterli bilgi içermiyor. Go template sistemiyle mesajları zenginleştirebilirsin.

# /etc/grafana/provisioning/alerting/templates.yaml
apiVersion: 1

templates:
  - name: slack-message
    template: |
      {{ define "slack.custom.title" }}
      [{{ .Status | toUpper }}{{ if eq .Status "firing" }}:{{ .Alerts.Firing | len }}{{ end }}] {{ .CommonLabels.alertname }}
      {{ end }}
      
      {{ define "slack.custom.text" }}
      {{ range .Alerts }}
      *Sunucu:* {{ .Labels.instance }}
      *Servis:* {{ .Labels.job }}
      *Onem:* {{ .Labels.severity }}
      *Aciklama:* {{ .Annotations.description }}
      *Baslangic:* {{ .StartsAt.Format "2006-01-02 15:04:05" }}
      {{ if .GeneratorURL }}*Grafana Link:* {{ .GeneratorURL }}{{ end }}
      {{ end }}
      {{ end }}

Pratik Senaryo: E-ticaret Sitesi İzleme

Diyelim ki bir e-ticaret platformu yönetiyorsun. Kargo saat 18:00’de kapanıyor ve öncesinde yoğunluk oluyor. Bu saatte CPU uyarılarının gelmesi normal. Ama gece 02:00’de aynı uyarı ciddi bir sorun işareti.

Zaman bazlı Silence kullanarak mesai saatlerindeki beklenen yüklenmeleri susturabilirsin:

# API ile silence oluştur - her gün 17:00-19:00 arası CPU uyarılarını sustur
curl -X POST 
  http://admin:adminpassword@localhost:3000/api/alertmanager/grafana/api/v2/silences 
  -H 'Content-Type: application/json' 
  -d '{
    "matchers": [
      {
        "name": "alertname",
        "value": "High CPU Usage",
        "isRegex": false
      },
      {
        "name": "severity",
        "value": "warning",
        "isRegex": false
      }
    ],
    "startsAt": "2024-01-15T17:00:00Z",
    "endsAt": "2024-01-15T19:00:00Z",
    "comment": "Aksam yuklenme donemi - beklenen davranis",
    "createdBy": "admin"
  }'

Aynı sitenin ödeme servisi için SLA uyarısı eklemek istiyorsun. Ödeme başarı oranı %95’in altına düşerse anında bildirim:

# Prometheus sorgusu - son 5 dakikadaki başarısız ödeme oranı
(
  sum(rate(payment_requests_total{status="failed"}[5m])) 
  / 
  sum(rate(payment_requests_total[5m]))
) * 100 > 5

Bu kural için pending period’u sıfır yap ve PagerDuty’e yönlendir. Ödeme sisteminde 1 dakika bile çok para demek.

Uyarı Durumlarını Anlamak

Grafana’da bir alert rule’un alabileceği durumlar:

  • Normal: Hiçbir koşul sağlanmıyor
  • Pending: Koşul sağlandı ama for süresi henüz dolmadı
  • Firing: Koşul sağlandı ve for süresi geçti, uyarı gönderildi
  • NoData: Sorgu veri döndürmüyor
  • Error: Sorgu çalıştırılırken hata oluştu

NoData durumu için ne yapılacağını mutlaka belirle. Exporter çöktüyse veri gelmiyor ve bu da kritik bir durum olabilir.

# noDataState seçenekleri:
# NoData - sadece NoData uyarısı gönder
# Alerting - sanki kural ateşlenmiş gibi davran
# OK - her şey yolunda say (tehlikeli!)
# KeepLast - son bilinen durumu koru

Alerting Kurallarını Test Etme

Kural yazdın ama doğru çalışıyor mu? Prometheus’ta test sorgusu çalıştır:

# Prometheus query API ile sorguyu test et
curl -s "http://localhost:9090/api/v1/query?query=100%20-%20(avg%20by%20(instance)%20(rate(node_cpu_seconds_total%7Bmode%3D%22idle%22%7D%5B5m%5D))%20*%20100)" 
  | python3 -m json.tool

# Belirli bir zaman aralığında sorgu
curl -s "http://localhost:9090/api/v1/query_range?query=up&start=2024-01-15T10:00:00Z&end=2024-01-15T11:00:00Z&step=60" 
  | python3 -m json.tool

Grafana API üzerinden mevcut uyarı durumlarını kontrol et:

# Tüm firing alert'leri listele
curl -s http://admin:adminpassword@localhost:3000/api/alertmanager/grafana/api/v2/alerts 
  | python3 -m json.tool | grep -A 5 '"status"'

# Belirli bir kural grubunun durumunu kontrol et
curl -s "http://admin:adminpassword@localhost:3000/api/ruler/grafana/api/v1/rules/Infrastructure/linux-servers" 
  | python3 -m json.tool

Yaygın Sorunlar ve Çözümleri

Çok fazla uyarı geliyor, alarm yorgunluğu var: Pending period değerini artır, daha iyi threshold’lar belirle ve severity etiketlerini doğru kullan. Gereksiz metrikleri filtrele.

NoData uyarıları sürekli geliyor: Exporter’ların çalışıp çalışmadığını kontrol et. Prometheus scrape interval’ini ve Grafana evaluation interval’ini hizala. Çok dar zaman penceresi seçmişsin olabilirsin.

Uyarı geliyor ama Slack’e gitmiyor: Contact point’i test butonuyla test et. SMTP veya webhook bağlantısını doğrula. Notification policy matcher’larının doğru etiketleri hedef aldığından emin ol.

# Grafana log'larında alerting hatalarını ara
sudo journalctl -u grafana-server | grep -i "alerting|alert|notification" | tail -50

# Daha detaylı log için grafana.ini'de log level'ı düşür
[log]
level = debug
filters = alerting:debug

Aynı uyarı sürekli tekrar ediyor: repeat_interval değerini kontrol et. Varsayılan genelde 4 saat. Çözülmüş uyarıların resolve bildirimi gelmiyor olabilir, bu durumda contact point konfigürasyonunu gözden geçir.

Backup ve Versiyon Kontrolü

Tüm alerting konfigürasyonunu Git’e almak iyi bir pratik. Grafana’nın SQLite veritabanına bağlı olmak yerine YAML provisioning tercih et.

# Mevcut kuralları export et
curl -s http://admin:adminpassword@localhost:3000/api/v1/provisioning/alert-rules 
  > /opt/grafana-backup/alert-rules-$(date +%Y%m%d).json

# Contact points export
curl -s http://admin:adminpassword@localhost:3000/api/v1/provisioning/contact-points 
  > /opt/grafana-backup/contact-points-$(date +%Y%m%d).json

# Notification policy export
curl -s http://admin:adminpassword@localhost:3000/api/v1/provisioning/policies 
  > /opt/grafana-backup/policies-$(date +%Y%m%d).json

# Bunları cron'a al
echo "0 2 * * * root /opt/scripts/grafana-backup.sh" >> /etc/cron.d/grafana-backup

Sonuç

Grafana Alerting sistemi doğru kurulduğunda gerçek bir güvenlik ağı oluşturuyor. Ama dikkat etmezsen tam tersine alarm yorgunluğu yaratıp önemli uyarıları gözden kaçırmana sebep oluyor.

Önceliklerin şunlar olmalı: Önce contact point’leri test et, production’da kullanmadan önce her kanalın çalıştığını doğrula. Anlamlı threshold’lar belirle, her şeye varsayılan %80 koyma, gerçek kapasite planlamasına bak. Pending period’u iyi ayarla, anlık spike’ların gürültü yaratmasını önle. Silence’ları stratejik kullan, planlı bakım ve beklenen yüklenme dönemleri için. YAML provisioning kullan, GUI’den yaptıklarını Git’te versiyonlayamazsın.

En önemli tavsiyem: Uyarı kurallarını bir kere kurup unutma. Ayda bir gözden geçir, hangi uyarıların aksiyona yol açtığını, hangilerinin gürültü olduğunu analiz et ve buna göre optimize et. Monitoring sistemi canlı bir organizma, düzenli bakım ister.

Benzer Konular

Bir yanıt yazın

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