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.
