E-posta ve Slack Bildirimleri için Alertmanager Entegrasyonu

Prometheus kurulumunu tamamladınız, metrikler akıyor, Grafana’da güzel dashboardlar oluşturdunuz. Peki bir şeyler ters gittiğinde sizi kim uyaracak? Grafana’yı sürekli açık tutup bekleyemezsiniz tabii. İşte tam bu noktada Alertmanager devreye giriyor. Bu yazıda Alertmanager’ı sıfırdan kurup hem e-posta hem de Slack üzerinden bildirim gönderecek şekilde yapılandıracağız. Gerçek dünya senaryolarıyla birlikte, production ortamında karşılaşabileceğiniz durumları da ele alacağız.

Alertmanager Nedir ve Neden Gerekli?

Prometheus kendi başına alert üretebiliyor, bunu biliyorsunuz. Ama Prometheus’un alert yönetimi konusunda ciddi kısıtları var. Tekrarlayan bildirimleri susturmak, alert gruplamak, farklı kanallar için farklı kurallar tanımlamak gibi şeyleri Prometheus tek başına yapamıyor.

Alertmanager bu boşluğu dolduruyor. Prometheus’dan gelen alertleri alıyor, bunları grupluyor, tekrarlananları filtreleyen silence kuralları uyguluyor ve sonunda doğru kişiye, doğru kanala iletiyor. Database sunucunuz çöktüğünde DBA ekibine Slack, disk dolmaya başladığında sistem ekibine e-posta, kritik bir servis down olduğunda hem PagerDuty hem Slack’e aynı anda bildirim göndermesini sağlayabilirsiniz.

Temel kavramları hızlıca geçelim:

  • Receiver: Bildirimlerin gönderileceği hedef (e-posta, Slack, PagerDuty vs.)
  • Route: Hangi alertin hangi receiver’a gideceğini belirleyen kural seti
  • Inhibition: Bir alert aktifken başka bir alerti susturma kuralı
  • Silence: Belirli bir süre için belirli alertleri susturma
  • Group: Benzer alertleri tek bildirimde toplama

Alertmanager Kurulumu

Önce Alertmanager’ı indirip kuralım. Ben Ubuntu 22.04 üzerinde çalışıyorum ama komutların büyük çoğunluğu diğer dağıtımlarda da benzer şekilde çalışır.

# Son sürümü çekelim
wget https://github.com/prometheus/alertmanager/releases/download/v0.27.0/alertmanager-0.27.0.linux-amd64.tar.gz

# Arşivi açıyoruz
tar xvfz alertmanager-0.27.0.linux-amd64.tar.gz

# Binary'leri taşıyalım
sudo cp alertmanager-0.27.0.linux-amd64/alertmanager /usr/local/bin/
sudo cp alertmanager-0.27.0.linux-amd64/amtool /usr/local/bin/

# Konfigürasyon dizinini oluşturalım
sudo mkdir -p /etc/alertmanager
sudo mkdir -p /var/lib/alertmanager

# Alertmanager için ayrı bir kullanıcı oluşturalım
sudo useradd --no-create-home --shell /bin/false alertmanager

# İzinleri ayarlayalım
sudo chown alertmanager:alertmanager /usr/local/bin/alertmanager
sudo chown alertmanager:alertmanager /usr/local/bin/amtool
sudo chown -R alertmanager:alertmanager /etc/alertmanager
sudo chown -R alertmanager:alertmanager /var/lib/alertmanager

Şimdi systemd servis dosyasını oluşturalım:

sudo nano /etc/systemd/system/alertmanager.service
[Unit]
Description=Alertmanager
Wants=network-online.target
After=network-online.target

[Service]
User=alertmanager
Group=alertmanager
Type=simple
ExecStart=/usr/local/bin/alertmanager 
  --config.file=/etc/alertmanager/alertmanager.yml 
  --storage.path=/var/lib/alertmanager 
  --web.listen-address=0.0.0.0:9093 
  --web.external-url=http://alertmanager.sirketiniz.com:9093

Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Servisi aktifleştirelim ama henüz başlatmayalım, önce konfigürasyonu yazalım.

Temel Alertmanager Konfigürasyonu

/etc/alertmanager/alertmanager.yml dosyasını oluşturuyoruz. Bu dosya Alertmanager’ın kalbi. Hem e-posta hem Slack için temel bir yapı kuralım:

sudo nano /etc/alertmanager/alertmanager.yml
global:
  # E-posta için SMTP ayarları
  smtp_smarthost: 'smtp.gmail.com:587'
  smtp_from: '[email protected]'
  smtp_auth_username: '[email protected]'
  smtp_auth_password: 'uygulama-sifreniz-buraya'
  smtp_require_tls: true

  # Slack için global API URL (opsiyonel, receiver'da da tanımlayabilirsiniz)
  slack_api_url: 'https://hooks.slack.com/services/TXXXXXXXX/BXXXXXXXX/xxxxxxxxxxxxxxxxxxxxxxxx'

  # Bir alert tekrar bildirim göndermeden önce ne kadar beklesin
  resolve_timeout: 5m

# Routing kuralları
route:
  # Varsayılan receiver
  receiver: 'email-ekip'
  
  # Aynı label'lara sahip alertleri grupla
  group_by: ['alertname', 'cluster', 'service']
  
  # İlk bildirimden önce ne kadar bekle (aynı grupta başka alert gelirse birleştirelim)
  group_wait: 30s
  
  # Aynı gruba yeni alert eklendiğinde ne kadar bekle
  group_interval: 5m
  
  # Aynı alert için tekrar bildirim göndermeden önce ne kadar bekle
  repeat_interval: 4h

  routes:
    # Kritik alertler hem e-posta hem Slack'e gitsin
    - match:
        severity: critical
      receiver: 'kritik-kanal'
      continue: true
    
    # Database alertleri DBA kanalına gitsin
    - match_re:
        alertname: '^(MySQL|PostgreSQL|Redis).*'
      receiver: 'dba-ekibi'
    
    # Warning seviyesi sadece Slack'e gitsin
    - match:
        severity: warning
      receiver: 'slack-genel'

# Receiver tanımları
receivers:
  - name: 'email-ekip'
    email_configs:
      - to: '[email protected]'
        send_resolved: true
        headers:
          Subject: '[{{ .Status | toUpper }}] {{ .GroupLabels.alertname }} - {{ .CommonAnnotations.summary }}'

  - name: 'slack-genel'
    slack_configs:
      - channel: '#alerts'
        send_resolved: true
        title: '{{ template "slack.default.title" . }}'
        text: '{{ template "slack.default.text" . }}'

  - name: 'kritik-kanal'
    email_configs:
      - to: '[email protected], [email protected]'
        send_resolved: true
    slack_configs:
      - channel: '#kritik-alertler'
        send_resolved: true
        username: 'AlertBot'
        icon_emoji: ':fire:'

  - name: 'dba-ekibi'
    email_configs:
      - to: '[email protected]'
        send_resolved: true
    slack_configs:
      - channel: '#dba-alerts'
        send_resolved: true

# Inhibition kuralları
inhibit_rules:
  # Kritik bir alert varsa aynı instance için warning alertleri sustur
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'instance']

Slack Entegrasyonu Detayları

Slack webhook URL’ini almak için birkaç adım gerekiyor. Slack workspace’inizde bir app oluşturmanız ve Incoming Webhooks özelliğini aktifleştirmeniz lazım.

Slack API’den webhook aldıktan sonra mesajların görünümünü özelleştirelim. Alertmanager Go template sistemi kullanıyor, bu sayede çok zengin mesaj formatları oluşturabiliyorsunuz.

/etc/alertmanager/templates/slack.tmpl dosyasını oluşturalım:

sudo mkdir -p /etc/alertmanager/templates
sudo nano /etc/alertmanager/templates/slack.tmpl
{{ define "slack.custom.title" }}
{{ if eq .Status "firing" }}:red_circle:{{ else }}:large_green_circle:{{ end }}
[{{ .Status | toUpper }}{{ if eq .Status "firing" }} - {{ .Alerts.Firing | len }} alert(s){{ end }}]
{{ .GroupLabels.SortedPairs.Values | join " " }}
{{ end }}

{{ define "slack.custom.text" }}
{{ range .Alerts }}
*Alert:* {{ .Annotations.summary }}{{ if .Labels.severity }} - `{{ .Labels.severity }}`{{ end }}
*Aciklama:* {{ .Annotations.description }}
*Baslangic:* {{ .StartsAt | since }}
*Sunucu:* {{ .Labels.instance }}
*Detay:* {{ .GeneratorURL }}
{{ end }}
{{ end }}

Template dosyasını Alertmanager’a bildirmemiz gerekiyor, alertmanager.yml dosyasının başına şunu ekleyelim:

global:
  # ... diğer global ayarlar

templates:
  - '/etc/alertmanager/templates/*.tmpl'

E-posta Bildirimlerini Özelleştirme

Gmail yerine kurumsal SMTP kullanıyorsanız veya daha detaylı e-posta şablonları istiyorsanız, şu şekilde yapılandırabilirsiniz. Önce HTML e-posta şablonu oluşturalım:

sudo nano /etc/alertmanager/templates/email.tmpl
{{ define "email.custom.html" }}
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>{{ template "email.default.subject" . }}</title>
</head>
<body style="font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f4f4f4;">
  <div style="max-width: 600px; margin: 0 auto; background-color: white; padding: 20px; border-radius: 5px;">
    
    {{ if eq .Status "firing" }}
    <div style="background-color: #d9534f; color: white; padding: 10px; border-radius: 3px; margin-bottom: 20px;">
      <h2 style="margin: 0;">KRITIK ALERT - Hemen Mudahale Gerekiyor</h2>
    </div>
    {{ else }}
    <div style="background-color: #5cb85c; color: white; padding: 10px; border-radius: 3px; margin-bottom: 20px;">
      <h2 style="margin: 0;">COZULDU - Alert Temizlendi</h2>
    </div>
    {{ end }}

    {{ range .Alerts }}
    <div style="border: 1px solid #ddd; padding: 15px; margin-bottom: 15px; border-radius: 3px;">
      <h3>{{ .Annotations.summary }}</h3>
      <p>{{ .Annotations.description }}</p>
      <p><strong>Sunucu:</strong> {{ .Labels.instance }}</p>
      <p><strong>Servis:</strong> {{ .Labels.job }}</p>
      <p><strong>Onem:</strong> {{ .Labels.severity }}</p>
      <p><strong>Baslangic:</strong> {{ .StartsAt }}</p>
      <a href="{{ .GeneratorURL }}" style="background-color: #337ab7; color: white; padding: 8px 15px; text-decoration: none; border-radius: 3px;">
        Prometheus'ta Goster
      </a>
    </div>
    {{ end }}
    
    <p style="color: #666; font-size: 12px; margin-top: 20px;">
      Bu bildirim otomatik olarak gonderilmistir. Alertmanager tarafindan uretildi.
    </p>
  </div>
</body>
</html>
{{ end }}

E-posta receiver’ında bu şablonu kullanalım:

receivers:
  - name: 'email-ekip'
    email_configs:
      - to: '[email protected]'
        send_resolved: true
        html: '{{ template "email.custom.html" . }}'
        headers:
          Subject: >-
            [{{ .Status | toUpper }}] {{ .GroupLabels.alertname }}
            Sunucu: {{ .CommonLabels.instance }}

Prometheus’ta Alert Kuralları Tanımlama

Alertmanager tek başına hiçbir şey yapmaz, Prometheus’tan alert alması gerekiyor. Birkaç gerçek dünya senaryosu için alert kuralları yazalım:

sudo nano /etc/prometheus/rules/sunucu-alertleri.yml
groups:
  - name: sunucu.rules
    interval: 30s
    rules:
      # Disk doluluk uyarısı
      - alert: DiskDolmakUzere
        expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 20
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Disk dolmak uzere: {{ $labels.instance }}"
          description: "{{ $labels.instance }} sunucusunda {{ $labels.mountpoint }} mount point icin disk dolulugu %80'i gecti. Mevcut bos alan: {{ $value | printf "%.2f" }}%"

      - alert: DiskKritikSeviye
        expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 10
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "KRITIK: Disk neredeyse dolu - {{ $labels.instance }}"
          description: "{{ $labels.instance }} sunucusunda disk dolulugu kritik seviyeye ulasti. Bos alan: {{ $value | printf "%.2f" }}%"

      # Yuksek CPU kullanimi
      - alert: YuksekCPUKullanimi
        expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Yuksek CPU kullanimi: {{ $labels.instance }}"
          description: "{{ $labels.instance }} sunucusunda CPU kullanimi son 10 dakikadır {{ $value | printf "%.1f" }}% seviyesinde"

      # Sunucu erişilemez
      - alert: SunucuUlasılamaz
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Sunucuya ulasilamiyor: {{ $labels.instance }}"
          description: "{{ $labels.instance }} sunucusu 1 dakikadır down durumda"

      # Yüksek bellek kullanımı
      - alert: YuksekBellekKullanimi
        expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Bellek kullanimi yuksek: {{ $labels.instance }}"
          description: "{{ $labels.instance }} sunucusunda bellek kullanimi {{ $value | printf "%.1f" }}% seviyesinde"

Prometheus konfigürasyonunda bu rule dosyasını belirtmeyi unutmayın:

# /etc/prometheus/prometheus.yml icinde
rule_files:
  - "/etc/prometheus/rules/*.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - localhost:9093

Alertmanager’ı Başlatma ve Test

Konfigürasyonu doğrulayalım ve servisi başlatalım:

# Konfigürasyon syntax kontrolü
/usr/local/bin/amtool check-config /etc/alertmanager/alertmanager.yml

# Prometheus rule dosyalarını kontrol et
/usr/local/bin/promtool check rules /etc/prometheus/rules/sunucu-alertleri.yml

# Servisleri başlat
sudo systemctl daemon-reload
sudo systemctl enable alertmanager
sudo systemctl start alertmanager
sudo systemctl restart prometheus

# Durumları kontrol et
sudo systemctl status alertmanager
sudo systemctl status prometheus

Test bildirimi göndermek için amtool kullanabiliriz:

# Alertmanager'a bağlan
export ALERTMANAGER_URL=http://localhost:9093

# Test alert gonder
amtool alert add alertname="TestAlert" severity="warning" instance="test-server-01" 
  --annotation=summary="Bu bir test altidir" 
  --annotation=description="Alertmanager entegrasyonunu test ediyoruz"

# Aktif alertleri listele
amtool alert query

# Alerti kapat (çözüldü olarak işaretle)
amtool alert query alertname="TestAlert"

Silence Kuralları ve Bakım Penceresi

Production ortamında planlı bakım sırasında alert yağmuruna maruz kalmamak için silence kullanıyoruz. Bunu hem web arayüzünden hem de amtool ile yapabilirsiniz:

# Belirli bir sunucu için 2 saatlik silence oluştur
amtool silence add instance="web-server-01" 
  --duration=2h 
  --comment="Planlı bakım - kernel güncellemesi" 
  --author="sysadmin"

# Tüm warning alertleri gece boyunca sustur
amtool silence add severity="warning" 
  --start="2024-01-15T23:00:00" 
  --end="2024-01-16T07:00:00" 
  --comment="Gece bakım penceresi" 
  --author="ops-team"

# Aktif silence'ları listele
amtool silence query

# Silence'ı iptal et (ID'yi listeden alın)
amtool silence expire <silence-id>

Güvenlik ve Production Önerileri

Canlı ortamda birkaç önemli nokta var. SMTP şifresi gibi hassas bilgileri doğrudan YAML’a yazmak yerine environment variable kullanın:

# /etc/systemd/system/alertmanager.service dosyasına ekleyin
[Service]
EnvironmentFile=/etc/alertmanager/alertmanager.env
ExecStart=/usr/local/bin/alertmanager 
  --config.file=/etc/alertmanager/alertmanager.yml 
  ...
# /etc/alertmanager/alertmanager.env
ALERTMANAGER_SMTP_PASSWORD=gercek-sifreniz
ALERTMANAGER_SLACK_WEBHOOK=https://hooks.slack.com/...
# Bu dosyanın izinlerini kısıtlayın
sudo chmod 600 /etc/alertmanager/alertmanager.env
sudo chown alertmanager:alertmanager /etc/alertmanager/alertmanager.env

Alertmanager web arayüzünü internete açmak zorundaysanız nginx reverse proxy arkasına alın ve basic auth ekleyin:

# Nginx konfigürasyonu
server {
    listen 443 ssl;
    server_name alertmanager.sirketiniz.com;

    ssl_certificate /etc/ssl/certs/alertmanager.crt;
    ssl_certificate_key /etc/ssl/private/alertmanager.key;

    location / {
        auth_basic "Alertmanager";
        auth_basic_user_file /etc/nginx/.alertmanager_htpasswd;
        proxy_pass http://localhost:9093;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Sık Karşılaşılan Sorunlar

E-posta gitmiyor: Gmail kullanıyorsanız “Less secure apps” yerine mutlaka “App Password” oluşturun, 2FA aktifse normal şifreniz çalışmaz.

Slack webhook 403 veriyor: Webhook URL’nin doğru kanalı işaret ettiğinden emin olun. Slack workspace ayarlarından webhook’u yeniden oluşturmayı deneyin.

Alertler tekrarlanıyor: repeat_interval değerini artırın. Production’da genellikle 12h veya 24h mantıklı.

Alert gelmiyor ama Prometheus’ta görünüyor: Prometheus’un alertmanagers konfigürasyonunu kontrol edin, amtool alert query ile Alertmanager’ın alerti alıp almadığını doğrulayın.

Grouping beklendiği gibi çalışmıyor: group_by alanındaki label’ların alert tanımlarınızda mevcut olduğundan emin olun.

Sonuç

Alertmanager, Prometheus ekosisteminin en kritik parçalarından biri. Düzgün yapılandırıldığında alert yorgunluğunu önlüyor, doğru kişiye doğru zamanda ulaşıyor ve ekiplerin olaylara hızlı müdahale etmesini sağlıyor. Bu yazıda temel kurulumdan özel şablonlara, silence yönetiminden güvenlik önlemlerine kadar ihtiyaç duyacağınız büyük çoğunluğu anlattık.

Bir sonraki adım olarak PagerDuty veya OpsGenie gibi on-call yönetim araçlarını entegre etmeyi düşünebilirsiniz. Ayrıca Grafana’nın kendi alert sistemini de Alertmanager’a bağlayabilirsiniz, bu sayede hem Prometheus metrik alertleri hem de Grafana dashboard alertleri aynı kanaldan akabilir. Alert kurallarınızı git’te versiyonlamayı da ihmal etmeyin, üç ay sonra “bu kuralı neden yazdım” sorusuna cevap bulamamak can sıkıcı oluyor.

Benzer Konular

Bir yanıt yazın

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