Prometheus Alerting Rules ve Recording Rules Yazma Rehberi
Gece saat 03:00. Telefonunuz acı acı çalıyor. Gözlerinizi kırpıştırarak ekrana bakıyorsunuz: “CPU Usage is High!”. Kalbiniz küt küt atarak bilgisayarı açıyor, Kubernetes cluster’ına bağlanıyor ve aslında her şeyin normal olduğunu, yalnızca anlık bir cron job’ın CPU’yu tetiklediğini görüyorsunuz. Tebrikler, “Alert Fatigue” (alarm yorgunluğu) kulübüne hoş geldiniz! DevOps ve SRE’de yanlış yapılandırılmış bir Prometheus ve alerting altyapısı kadar ekipleri yıpratan çok az şey vardır. Gelin uykularınızı kaçırmayacak, gerçekten aksiyon alınabilir alert kuralları yazalım ve recording rules ile Prometheus sunucunuzun CPU’sunu nasıl rahatlatacağımıza bakalım.
1. Alert felsefesi: “semptom” ve “sebep”
Bir alert kuralı yazmadan önce kendimize şunu sormamız gerekir: “Bu alarm çaldığında birinin yataktan kalkıp hemen bir şey yapması gerekiyor mu?” Cevap hayırsa o bir alert değil, yalnızca bir metric veya en fazla bir dashboard grafiğidir.
SRE’de alert’leri ikiye ayırırız:
- Semptom tabanlı (Symptom-based): “Kullanıcılar 500 hatası alıyor.” (Hemen müdahale edilmeli!)
- Sebep tabanlı (Cause-based): “Node CPU kullanımı %92.” (Belki de Kubernetes bunu zaten scale edecek, neden uyandırılıyorum?)
Her zaman semptomlara alert kurmaya çalışın. CPU yükselmesi tek başına bir felaket değildir. Bu durum latency (gecikme) artışına ya da hata oranının (error rate) yükselmesine yol açmıyorsa Prometheus sessizce metric toplamaya devam etsin.
2. Etkin Prometheus alerting rules yazmak
Prometheus üzerinde alert tanımlarken PromQL’in gücünden yararlanırız. Ancak verimsiz yazılan sorgular hem Prometheus’u yorar hem de yanlış alarmlara (false positive) yol açar.
Kötü bir örnek ve analizi
- alert: HighCPUUsage
expr: node_cpu_seconds_total{mode="idle"} < 10
for: 1m
labels:
severity: critical
annotations:
summary: "CPU usage is high on {{ $labels.instance }}"
Bu kuralın sorunları şunlar:
- Çok kısa süre (for: 1m): 1 dakikalık bir CPU yükselmesi geçici bir spike (anlık sıçrama) olabilir. Hemen alarm tetiklemek anlamsızdır.
- Ham metric kullanımı: `node_cpu_seconds_total` doğrudan kullanılmamalı, rate() veya irate() fonksiyonlarıyla normalize edilmelidir.
- Aksiyon yok: “CPU yüksek” bilgisini alan bir mühendis ne yapmalı? Annotation içinde bir runbook linki yok.
Daha iyi bir yaklaşım
- alert: NodeCPUUtilizationHigh
expr: (100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)) > 85
for: 15m
labels:
severity: warning
team: platform
annotations:
summary: "Node {{ $labels.instance }} CPU utilization is above 85% for 15 minutes."
description: "High CPU might impact application performance. Check Pod distribution."
runbook_url: "https://wiki.kertenkerem.net/ops/runbooks/high-node-cpu"
Sorguyu 5 dakikalık pencerelerde `rate` alacak şekilde optimize ettik, bekleme süresini (`for`) 15 dakikaya çıkararak geçici spike’ları eledik ve en önemlisi alarmı alan mühendis için bir `runbook_url` ekledik.
3. Prometheus’u coşturmak: recording rules
Prometheus her `evaluation_interval` süresinde (genelde 15-30 saniye) tüm alert kurallarını sıfırdan hesaplar. Yukarıdaki gibi ağır matematiksel işlemler içeren yüzlerce kuralınız ve binlerce node/pod içeren bir cluster’ınız varsa Prometheus sunucunuzun CPU ve Memory kullanımı tavan yapar. Sahneye burada recording rules çıkıyor.
Recording rules, karmaşık ve sık çalıştırılan PromQL sorgularının sonuçlarını önceden hesaplayıp yeni bir metric olarak kaydetmenizi sağlar. Böylece alert kuralları veya Grafana dashboard’ları bu karmaşık sorguyu her seferinde çalıştırmak yerine önceden hesaplanmış hazır veriyi okur.
Yavaş sorgu örneği (Kubernetes Pod CPU Utilization)
Grafana dashboard’unuzda veya alert kuralınızda her 15 saniyede bir şu sorgunun çalıştığını hayal edin:
sum by (namespace, pod) (rate(container_cpu_usage_seconds_total{container!=""}[5m]))
Bunu optimize etmek için bir recording rule tanımlayalım:
groups:
- name: kertenkerem.cpu.rules
rules:
- record: namespace_pod:container_cpu_usage:rate5m
expr: sum by (namespace, pod) (rate(container_cpu_usage_seconds_total{container!=""}[5m]))
Artık Prometheus arkada bu sorguyu sessizce çalıştırıp sonucu `namespace_pod:container_cpu_usage:rate5m` adlı yeni ve temiz bir metric olarak kaydedecek. Şimdi alert kuralımızı bu yeni metric üzerinden yazalım:
- alert: PodCPULimitApproaching
expr: namespace_pod:container_cpu_usage:rate5m > 0.90
for: 10m
labels:
severity: warning
Prometheus artık her sorgulamada diskten gigabaytlarca veri okuyup CPU hesaplaması yapmak zorunda kalmayacak. Doğrudan hazır hesaplanmış tek bir metric değerine bakacak. Disk I/O ve CPU tüketiminizde ciddi bir düşüş göreceksiniz.
4. Alertmanager ile gürültüyü engelleme: inhibition ve silence
Prometheus alert’i üretir, bu alert’lerin nereye (Slack, PagerDuty, Webhook) ve nasıl gideceğini ise Alertmanager yönetir. Alert gürültüsünü kesmek için elimizde iki araç var: Inhibition Rules ve Silences.
Inhibition rules (engelleme kuralları)
Bir veri merkezindeki tüm sunucuların bağlı olduğu ana switch çöktüğünde ne olur? Muhtemelen o switch’in arkasındaki 50 sunucu ve üzerindeki 500 pod için ayrı ayrı “Node Down” ve “Pod Down” alarmı alırsınız. Telefonunuz bildirim yağmurundan kilitlenir.
Inhibition rules, belirli bir ana alarm aktifken onunla ilişkili alt alarmların susturulmasını sağlar. Klasik bir Alertmanager konfigürasyon örneği:
inhibit_rules:
- source_matchers: [alertname="NodeNetworkDown"]
target_matchers: [alertname="InstanceDown"]
equal: ['node', 'instance']
Yukarıdaki kural şunu söylüyor: Bir node için `NodeNetworkDown` alarmı zaten tetiklendiyse aynı node üzerindeki servisler için `InstanceDown` (servis ulaşılamaz) alarmı gönderme, onu block’la. Mühendis ağın gittiğini zaten biliyor. Servislerin de gitmiş olacağını tahmin etmek için dahi olmaya gerek yok.
Silencing (susturma) ve maintenance
Planlı bir bakım çalışması (maintenance window) yapıyorsunuz ve Kubernetes cluster’ındaki bazı node’ları restart edeceksiniz. Bu sırada Slack kanalınızın “CRITICAL” loglarıyla dolmasını istemezsiniz.
Bunun için Alertmanager UI üzerinden ya da `amtool` CLI aracıyla hızlıca geçici “silence” tanımları yapabilirsiniz:
amtool silence add alertname="NodeCPUUtilizationHigh" node="node-01" --duration=2h --comment="Planli kernel upgrade calismasi"
Bu komut, `node-01` üzerindeki yüksek CPU alarmlarını 2 saat boyunca askıya alır. Bakım bittiğinde sistem otomatik olarak normale döner.
Sonuç: temiz alarmlar, huzurlu geceler
Prometheus ile monitoring kurmak kolaydır. Akıllıca tasarlanmış bir alarm yapısı kurmak ise gerçek bir mühendislik disiplini gerektirir. Toparlarsak:
- Yalnızca aksiyon almanız gereken durumlarda telefonunuzu çaldırın.
- Ağır PromQL sorgularınızı recording rules ile önceden hesaplayarak Prometheus’u rahatlatın.
- Alertmanager’ın inhibition kurallarını kullanarak kriz anlarında alarm bombardımanına tutulmaktan kaçının.
Bir sonraki yazımızda görüşmek üzere, metrics’iniz bol, geceleriniz sessiz olsun!