Kasım 1 2024

SLO/SLI/SLA: DevOps Ekiplerine Güvenilirlik Mühendisliği Rehberi

Gecenin 3’ünde, sırf bir API gateway endpoint’i anlık olarak 500ms yavaş yanıt verdi diye PagerDuty alarmıyla uyanıp monitöre boş gözlerle baktıysanız, tebrikler: Yanlış kurgulanmış bir alarm stratejisinin kurbanı oldunuz. Modern mikroservis mimarilerinde sistemlerin kararlılığını ve reliability (güvenilirlik) seviyesini ölçmek, her saniye CPU veya memory değerlerini izleyip eşik değer aşılınca ortalığı ayağa kaldırmakla olmaz. Modern sre (Site Reliability Engineering) dünyasında, sistem sağlığını ve mühendislik eforumuzu yönetmek için kullandığımız üç kutsal kısaltmamız var: sli, slo ve sla. Bu yazıda teorik tanımların ötesine geçecek, production ortamında işinize yarayacak gerçekçi error budget hesaplamalarını ve Prometheus üzerinde burn rate tabanlı dinamik alarmları nasıl kuracağımızı öğreneceğiz.

Kavram Karmaşasını Çözelim: SLI vs. SLO vs. SLA

Bu üç kavram genellikle birbirine karıştırılır veya aynı şeymiş gibi kullanılır. İşleri basitleştirmek için aralarındaki ilişkiyi netleştirelim:

  • SLI (Service Level Indicator): “Sistemimiz şu an ne kadar iyi çalışıyor?” sorusunun cevabıdır. Doğrudan ölçülebilir, anlık teknik metriklerdir. Örneğin; “Son 5 dakikadaki başarılı HTTP isteklerinin (2xx/3xx/4xx), toplam isteklere oranı.”
  • SLO (Service Level Objective): “Sistemin ne kadar iyi çalışmasını hedefliyoruz?” sorusunun yanıtıdır. SLI metriğine bağlı bir hedef ve zaman aralığı tanımlar. Örneğin; “Gelen tüm isteklerin %99.9’u, 30 günlük kayan pencerede (rolling window) 200ms’in altında yanıt vermelidir.”
  • SLA (Service Level Agreement): “Eğer sistemi hedeflediğimiz kadar ayakta tutamazsak ne kadar ceza ödeyeceğiz?” sorusunun ticari ve hukuki cevabıdır. Mühendislerden ziyade hukuk, ürün yönetimi (Product Management) ve müşterileri ilgilendirir. Genellikle SLO değerinden daha düşük bir taahhüt içerir (örneğin SLO %99.9 ise, SLA %99.5 olabilir).

Kısacası: SLI ölçer, SLO hedefler, SLA ise patlarsa fatura keser.

Hata Bütçesi (Error Budget): Neden Kusursuzluk Aramıyoruz?

SRE felsefesinin en büyük kabullerinden biri şudur: %100 güvenilirlik (reliability) yanlış bir hedeftir. Kullanıcılarınızın internet bağlantısı bile %100 kesintisiz değilken, altyapınız için %100 uptime hedeflemek sadece bütçenizi tüketir ve ekibin hızını (velocity) sıfırlar.

Bunun yerine Error Budget kavramını kullanırız. Formül oldukça basittir:

Error Budget = 100% - SLO%

Eğer bir servis için 30 günlük SLO hedefimizi %99.9 olarak belirlediysek, bu bizim 30 günde %0.1 oranında hata yapma veya kesinti yaşama hakkımız olduğu anlamına gelir. 30 günün saniye karşılığı 2.592.000 saniyedir. Bu durumda hata bütçemiz tam olarak 2.592 saniye, yani yaklaşık 43.2 dakikadır.

Bu bütçe sadece sistemin çökmesiyle tükenmez; yeni deployment’lar sırasındaki yavaşlıklar, geçici veritabanı bağlantı kayıpları da bu bütçeden yer. Eğer ay sonuna doğru hata bütçeniz duruyorsa, production ortamına korkusuzca riskli güncellemeler (feature deployment) gönderebilirsiniz. Bütçe tükendiyse, yeni deployment’ları durdurur ve sadece reliability/bug-fix işlerine odaklanırsınız.

Prometheus ile SLI Tanımlama (Pratik Uygulama)

İşleri biraz daha pratikleştirelim. Elimizde Prometheus tarafından scrape edilen bir HTTP servisinin metrikleri olduğunu varsayalım. En popüler SLI türlerinden biri olan Availability (Kullanılabilirlik) metriğini hesaplayalım.

Burada kritik bir SRE detayı var: Genellikle 5xx durum kodlarını sunucu hatası (unavailability) kabul ederken, 4xx durum kodlarını (örneğin 404 veya 401) kullanıcı hatası olarak kabul eder ve sistemin sağlığını bozmadığı için SLI hesabına dahil etmeyiz (tabii 4xx’ler aniden tavan yapmadıysa).

Yazacağımız PromQL sorgusu şu şekildedir:

sum(rate(http_requests_total{job="my-service", status!~"5.."}[5m]))
/
sum(rate(http_requests_total{job="my-service"}[5m]))

Bu sorgu, son 5 dakika içinde 5xx dışındaki isteklerin, toplam isteklere oranını verir. Çıktı 0 ile 1 arasında olacaktır (örneğin 0.9995, yani %99.95 başarı).

Burn Rate Alerts: CPU Alarmlarını Çöpe Atın

Geleneksel alert mekanizmaları genellikle “Anlık CPU %90’ı geçerse Slack’e mesaj at” veya “Hata oranı %1’i geçerse nöbetçiyi ara” şeklindedir. Bu yaklaşımlar iki büyük sorun yaratır:

  1. Gürültü (Alert Fatigue): Anlık bir trafik spike’ı nedeniyle hata oranı 1 dakikalığına %2’ye çıkabilir ve kendi kendine düzelir. Boşu boşuna uykunuz bölünür.
  2. Yavaş Ölümler (Slow Burns): Hata oranınız saatlerce %0.2’de kalabilir. Bu oran geleneksel alarmları tetiklemez ancak 30 günlük %99.9’luk SLO bütçenizi sinsice sıfırlar.

SRE pratikleri bu sorunu Burn Rate (Tüketim Hızı) alarmları ile çözer. Burn rate, hata bütçenizi ne kadar hızlı tükettiğinizi gösteren katsayıdır.

  • Burn Rate = 1: Bütçeniz tam olarak planlanan sürede (örneğin 30 günde) tükenecek demektir.
  • Burn Rate = 14.4: Bütçenizin %2’sini sadece 1 saat içinde tüketeceğiniz anlamına gelir. Acil müdahale (Pager) gerekir!
  • Burn Rate = 2.9: Bütçenizin %5’ini 6 saatte tüketeceksiniz demektir. Bu durumda bilet (Jira ticket) açılması yeterlidir.

Prometheus Kural Dosyası (Prometheus Alert Rules)

Aşağıdaki konfigürasyon bloğu, Google SRE Workbook standartlarına uygun olarak yazılmış, çoklu zaman pencereli (multi-window, multi-burn-rate) bir alert kuralı örneğidir. Hem anlık gürültüleri engeller hem de yavaş bütçe tüketimlerini kaçırmaz.

groups:
  - name: service-slo-alerts
    rules:
      # Critical Alert: 1 saatlik burn rate > 14.4 VE son 5 dakikada da bu eğilim devam ediyorsa
      - alert: ServiceAvailabilityCriticalBurnRate
        expr: |
          (
            sum(rate(http_requests_total{status=~"5.."}[1h]))
            /
            sum(rate(http_requests_total}[1h]))
          ) > (1 - 0.999) * 14.4
          and
          (
            sum(rate(http_requests_total{status=~"5.."}[5m]))
            /
            sum(rate(http_requests_total}[5m]))
          ) > (1 - 0.999) * 14.4
        for: 2m
        labels:
          severity: critical
          tier: platform
        annotations:
          summary: "Hızlı Hata Bütçesi Tüketimi (Burn Rate 14.4x)"
          description: "Hata bütçesi son 1 saatte çok hızlı tükeniyor! Current error rate: {{ $value | humanizePercentage }}"

      # Warning Alert: 6 saatlik burn rate > 6 (Bütçenin %5'i 6 saatte bitiyor)
      - alert: ServiceAvailabilityWarningBurnRate
        expr: |
          (
            sum(rate(http_requests_total{status=~"5.."}[6h]))
            /
            sum(rate(http_requests_total}[6h]))
          ) > (1 - 0.999) * 6
          and
          (
            sum(rate(http_requests_total{status=~"5.."}[30m]))
            /
            sum(rate(http_requests_total}[30m]))
          ) > (1 - 0.999) * 6
        for: 15m
        labels:
          severity: warning
        annotations:
          summary: "Yavaş Hata Bütçesi Tüketimi (Burn Rate 6x)"
          description: "Son 6 saattir hata bütçesi eriyor. Nöbetçi ekibin mesai saatlerinde incelemesi önerilir."

Yukarıdaki kurallarda dikkat ederseniz (1 - 0.999) * 14.4 gibi dinamik bir matematiksel formül kullandık. Buradaki 0.999 bizim SLO hedefimiz olan %99.9’dur. Eğer yarın bir gün bu hedefi %99.5’e çekmek isterseniz sadece bu katsayıları değiştirmeniz yeterli olacaktır.

Bu Yapıyı Kurduktan Sonra Sizi Ne Bekliyor?

Bu sisteme geçiş yapmak sadece teknik bir araç değişimi değil, ciddi bir kültürel dönüşümdür. Burn rate alarmlarına geçtiğinizde:

  • Gecenin yarısında uyanma oranınız (false-positive paging) dramatik şekilde düşecek.
  • Ekipler “Bu hafta çok downtime oldu, deployment yapmayalım” kararını hissiyatla değil, doğrudan Grafana paneline bakarak somut verilerle (Error Budget Dashboard) verecek.
  • Yazılım geliştiriciler ve sistem yöneticileri aynı dile konuşmaya başlayacak: “Hata bütçemiz ne kadar kaldı?”

Kendi sistemlerinizde bu dönüşümü başlatmak için ilk adım olarak en kritik 3 servisinizi belirleyin, basit birer kullanılabilirlik SLI’ı yazın ve error budget grafiğinizi oluşturun. Unutmayın, mükemmel bir sistem kesintisiz çalışan sistem değil, ne zaman ve ne kadar hata yapabileceğini bilen ve bunu kontrol altında tutan sistemdir.

Category: Genel | LEAVE A COMMENT
Eylül 27 2024

Linux Sistem Performans Analizi: perf, strace ve eBPF Araçları

Bir sabah Slack’ten gelen o korkunç alarm sesiyle uyandınız: “Production veritabanı sunucusunda latency uçtu, CPU %99!” Hemen sunucuya SSH ile bağlandınız, top komutunu çalıştırdınız ve evet, CPU gerçekten can çekişiyor. Ancak top veya htop gibi geleneksel araçlar size sadece “yangın olduğunu” söyler; yangının hangi odada, hangi kibritle başladığını göstermez. İşte bu noktada modern bir SRE (Site Reliability Engineer) gibi düşünmeli ve linux çekirdeğinin (kernel) derinliklerine inmeliyiz. Bu yazıda, modern altyapılarda performance sorunlarını iğne deliğinden geçirir gibi analiz etmenizi sağlayacak üç silahşörü inceleyeceğiz: perf, strace ve devrim niteliğindeki ebpf tabanlı bpftrace.

1. Donanımın Nabzını Tutmak: perf (CPU & Hardware Profiling)

perf, Linux çekirdeği ile doğrudan entegre çalışan inanılmaz güçlü bir profil çıkarma (profiling) aracıdır. CPU döngülerini (cycles), cache miss (önbellek kaçırma) oranlarını ve CPU talimatlarını (instructions) donanımsal sayaçları (PMU – Performance Monitoring Unit) kullanarak analiz eder.

Neden Sadece CPU Yüzdesine Bakmak Yanıltıcıdır?

Çoğu mühendis CPU %100 olduğunda uygulamanın çok yoğun hesaplama yaptığını düşünür. Ancak durum her zaman bu değildir. CPU, RAM’den veri beklerken de (stall cycles) %100 meşgul görünebilir. Biz buna Memory-Bound (bellek sınırlandırılmış) deriz. Eğer CPU gerçekten matematiksel işlemler yapıyorsa buna da Compute-Bound denir.

Bu ayrımı görmek için ilk yapmamız gereken şey perf stat komutunu çalıştırmaktır:

# Belirli bir PID'yi 5 saniye boyunca analiz edelim
perf stat -p 1234 sleep 5

Karşımıza şöyle bir çıktı gelecektir:

 Performance counter stats for process id '1234':

       2001.45 msec task-clock                #    0.400 CPUs utilized          
              1234  context-switches          #    0.617 K/sec                  
                45  cpu-migrations            #    0.022 K/sec                  
               105  page-faults               #    0.052 K/sec                  
        4002938102  cycles                    #    2.000 GHz                    
        2001467291  instructions              #    0.50  insn per cycle         
         120495839  branches                  #   60.204 M/sec                  
           4958102  branch-misses             #    4.11% of all branches        

       5.002345123 seconds time elapsed

Burada odaklanmamız gereken en kritik metrik insn per cycle (IPC) değeridir. IPC (Instructions Per Cycle), CPU’nun her döngüde kaç talimat çalıştırdığını gösterir.

  • IPC < 1.0 ise: Uygulamanız muhtemelen I/O veya memory erişimi bekliyor (Memory-Bound). CPU boşta (stall) bekliyor demektir.
  • IPC > 1.5 ise: CPU gerçekten yoğun şekilde kodunuzu çalıştırıyor demektir (Compute-Bound).

Sıcak Noktaları Bulmak: perf record ve perf report

Uygulamanın tam olarak hangi fonksiyonunun CPU’yu sömürdüğünü bulmak için örnekleme (sampling) yapmamız gerekir. Bu işlem production ortamlarında genellikle %1 ila %5 arasında çok düşük bir overhead (ek yük) ile yapılabilir.

# Saniyede 99 frekansla (overkill olmaması için idealdir) 10 saniye boyunca kayıt alalım
# -g parametresi call-graph (çağrı ağacı) kaydetmesini sağlar
perf record -F 99 -p 1234 -g -- sleep 10

Bu komut geçerli dizinde perf.data adında bir dosya oluşturur. Bu dosyayı analiz etmek için terminalden şu komutu veririz:

perf report -n --stdio

Karşınıza çıkan interaktif arayüzde hangi fonksiyonun (sembolün) CPU döngülerinin yüzde kaçını harcadığını hiyerarşik bir şekilde görebilirsiniz. Eğer fonksiyon isimleri yerine [hexadecimal] adresler görüyorsanız, uygulamanızın “debug symbols” (hata ayıklama sembolleri) eksiktir demektir. Go kullanıyorsanız binary’nizi strip etmeyin, C++/Rust kullanıyorsanız -g flag’i ile derlediğinizden emin olun.

2. Karanlıkta Kalan Sistem Çağrıları: strace

Uygulamanız çalışıyor ama hiçbir şey yapmıyor gibi mi görünüyor? Dosya okumaya çalışırken kilitlenmiş olabilir mi? Yoksa DNS çözümlemesi yaparken timeout mu yaşıyor? Bu gibi durumlarda, uygulamanın kernel ile olan iletişimini yani System Calls (syscalls) trafiğini izlememiz gerekir.

İşte strace bu işin mutfağıdır.

Production Uyarısı: strace’i Dikkatli Kullanın!

Geliştirme ortamında strace my_app yazıp geçmek harikadır ancak bunu canlı production ortamında sakın yapmayın! strace, izlediği process’in her syscall yaptığında durdurulmasını (ptrace ile) sağlar. Bu durum, uygulamanın performansını %100 ila %1000 oranında düşürebilir.

Bunun yerine, production dostu parametrelerle nokta atışı yapmalıyız:

# Uygulamanın en çok hangi sistem çağrısında ne kadar zaman harcadığını özetleyelim
# Bu işlem ham log akıtmaya göre çok daha az overhead yaratır
strace -c -p 1234

Çıktı bize muhteşem bir özet sunacaktır:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 89.45    1.204958         120     10041           read
 10.12    0.136120          13     10200      1050 openat
  0.43    0.005789          11       500           write
------ ----------- ----------- --------- --------- ----------------
100.00    1.346867                 20741      1050 total

Yukarıdaki tabloda net bir şekilde görüyoruz ki, uygulama zamanının %89’unu read sistem çağrısında harcıyor ve ciddi miktarda openat (dosya açma hatası) alıyor. Hangi dosyayı açamadığını bulmak için sadece hatalı çağrıları filtreleyebiliriz:

# Sadece başarısız olan (errors) openat çağrılarını göster
strace -e trace=openat -Z -p 1234

3. Modern Çağın Sihirli Değneği: eBPF ve bpftrace

Geleneksel araçların kısıtlamalarından sıkıldıysanız, sahneye eBPF (Extended Berkeley Packet Filter) çıkıyor. eBPF, Linux çekirdeğinin kodunu değiştirmeden veya kernel modülü yüklemeden, güvenli sandbox’lar içinde doğrudan çekirdekte kod çalıştırmamızı sağlar.

bpftrace ise eBPF dünyasının “awk” dilidir. Son derece hafif, pratik ve neredeyse sıfır overhead ile çalışan tek satırlık (one-liners) script’ler yazmamıza olanak tanır.

Örnek 1: Disk I/O Latency Analizi (Biolatency)

Diskinizin yavaş olduğunu düşünüyorsunuz ama hangi process’in ne kadarlık bir gecikmeye sebep olduğunu bulamıyorsunuz. Geleneksel iostat size sadece ortalama değerler verir. bpftrace ile gerçek zamanlı bir histogram çizelim:

# Disk I/O tamamlanma sürelerini mikrosaniye cinsinden histogram olarak gösterir
bpftrace -e '
kprobe:vfs_read { @start[tid] = nsecs; } 
kretprobe:vfs_read /@start[tid]/ { 
    @latency = hist((nsecs - @start[tid]) / 1000); 
    delete(@start[tid]); 
}'

Bu script, her vfs_read (sanal dosya sistemi okuma) başladığında bir zaman damgası alır ve bittiğinde aradaki farkı hesaplayıp logaritmik bir grafik çizer:

@latency: 
[2, 4)                12 |@@@@                                        |
[4, 8)                85 |@@@@@@@@@@@@@@@@@@@@@@@@                    |
[8, 16)              142 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16, 32)              45 |@@@@@@@@@@@@                                |
[32, 64)               8 |@@                                          |

Bu grafiğe bakarak, okuma işlemlerinin büyük çoğunluğunun 8-16 mikrosaniye arasında tamamlandığını, yani diskimizin sağlıklı çalıştığını saniyeler içinde anlayabiliriz.

Örnek 2: Bellek Sızıntısı (Memory Leak) Avı

Sisteminizde gizemli bir bellek şişmesi var. Hangi uygulamanın sürekli malloc çağırıp free etmediğini bulmak istiyorsunuz. eBPF ile kullanıcı alanındaki (user-space) bellek allocation çağrılarını takip edebiliriz:

# libc içindeki malloc çağrılarının byte boyutlarına göre dağılımını izleyelim
bpftrace -e 'usdt:/lib/x86_64-linux-gnu/libc.so.6:libc:memory_malloc_retry { @[arg0] = count(); }'

Bu sayede production ortamında çalışan uygulamanıza hiçbir kütüphane enjekte etmeden veya onu durdurmadan bellek tüketim kalıplarını yakalayabilirsiniz.

Özet ve Doğru Aracı Seçme Rehberi

Sistem tıkandığında hangi aracı ne zaman kullanacağınıza karar vermek, tecrübeli bir mühendisi amatörden ayıran en önemli özelliktir. İşte size pratik bir başucu tablosu:

Senaryo / Belirti Kullanılacak Araç Neden?
Yüksek CPU kullanımı var, hangi kod satırının yavaş olduğunu bulmak istiyorum. perf record / report Düşük overhead ile CPU çağrı ağacını (call graph) çıkarır.
Uygulama kilitlendi (stuck), log üretmiyor, ne yaptığını göremiyorum. strace -p <PID> Çekirdeğe gönderdiği sistem çağrılarını (network, dosya erişimi) anlık listeler.
Disk performansından şüpheleniyorum ama genel istatistikler yetersiz kalıyor. bpftrace (eBPF) Kernel seviyesinde I/O kuyruk gecikmesini histogram olarak gösterir.
Sistemin donanımsal düzeyde (L1/L2 Cache, CPU Cycles) analizine ihtiyacım var. perf stat İşlemcinin donanımsal sayaçlarına doğrudan erişim sağlar.

Performans analizi yaparken her zaman en az invaziv (sisteme en az müdahale eden) yöntemden başlayın. Önce perf stat ve bpftrace ile genel resmi görün, gerekirse ve güvenliyse strace ile derinlemesine inceleme yapın. Unutmayın, iyi bir SRE sadece sorunu çözen değil, sorunu çözerken production sistemini ayakta tutabilen kişidir!

Category: Genel | LEAVE A COMMENT
Ağustos 16 2024

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, sadece anlık bir cron job’ın CPU’yu tetiklediğini görüyorsunuz. Tebrikler, “Alert Fatigue” (alarm yorgunluğu) kulübüne hoş geldiniz! Modern devops ve sre dünyasında, yanlış yapılandırılmış bir prometheus ve alerting altyapısı kadar ekipleri yıpratan çok az şey vardır. Bu rehberde, uykularınızı kaçırmayacak, gerçekten aksiyon alınabilir alert kuralları yazmayı ve recording rules kullanarak Prometheus sunucunuzun CPU’sunu nasıl rahatlatacağınızı konuşacağız.

1. Alert Felsefesi: “Semptom” vs. “Sebep”

Bir alert kuralı yazmadan önce kendimize sormamız gereken ilk soru şudur: “Bu alarm çaldığında birinin yataktan kalkıp hemen bir şey yapması gerekiyor mu?” Cevap hayır ise, o bir alert değil, sadece bir metric veya en fazla bir dashboard grafiğidir.

SRE dünyasında 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; eğer bu durum latency (gecikme) artışına veya hata oranının (error rate) yükselmesine sebep olmuyorsa, bırakın Prometheus sessizce metric toplamaya devam etsin.

2. Etkin Prometheus Alerting Rules Yazmak

Prometheus üzerinde alert tanımlarken PromQL dilinin gücünden faydalanı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 neden kötü?

  1. Ç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.
  2. Ham metric kullanımı: `node_cpu_seconds_total` doğrudan kullanılmamalı, rate() veya irate() fonksiyonları ile normalize edilmelidir.
  3. Aksiyon yok: “CPU yüksek” bilgisini alan bir mühendis ne yapmalı? Annotation içinde bir runbook linki yok.

Daha İyi 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"

Burada neyi değiştirdik? 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. Eğer 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 yapacaktır. İşte burada sahneye 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` isimli yeni ve tertemiz 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 inanılmaz bir düşüş göreceksiniz.

4. Alertmanager ile Gürültüyü Engelleme: Inhibition ve Silence

Prometheus alert’i üretir, ancak bu alert’lerin nereye (Slack, PagerDuty, Webhook) nasıl gideceğini yöneten yer Alertmanager bileşenidir. Alert gürültüsünü kesmek için iki can kurtaran silahımız 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 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 der ki: Eğer 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 zaten ağın gittiğini 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 veya `amtool` CLI aracını kullanarak 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 normal haline döner.

Sonuç: Temiz Alarmlar, Huzurlu Geceler

Prometheus ile monitoring kurmak kolaydır; ancak akıllıca tasarlanmış bir alarm yapısı kurmak gerçek bir mühendislik disiplini gerektirir. Özetlemek gerekirse:

  1. Sadece aksiyon almanız gereken durumlarda telefonunuzu çaldırın.
  2. Ağır PromQL sorgularınızı recording rules ile önceden hesaplayarak Prometheus’u rahatlatın.
  3. 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!

Category: Genel | LEAVE A COMMENT