İçeriğe Atla
Mustafa Erbay
Yaşam · 10 dk okuma · görüntülenme Read in English

Observability'de Kardinalite Yönetimi: Maliyeti Düşürmenin 3 Yolu

Observability metriklerinizde yüksek kardinalite sorununu çözmek ve maliyetleri düşürmek için 3 pratik yolu keşfedin. Gerçek senaryolar ve somut örneklerle…

100%

Observability metriklerinizde yüksek kardinalite sorunuyla boğuşuyor, veri depolama ve sorgulama maliyetlerinin kontrolsüzce arttığını mı görüyorsunuz? Bu durum, sistemlerinizin sağlığını anlamak için topladığınız değerli verileri kullanılamaz hale getirebilir. Ben de bu sorunu hem kendi projelerimde hem de üzerinde çalıştığım kurumsal sistemlerde defalarca deneyimledim. Yüksek kardinalite, basitçe, bir metrik için çok fazla benzersiz etiket (label) kombinasyonu olması anlamına gelir. Bu durum, veritabanlarının aşırı yüklenmesine, sorgu sürelerinin uzamasına ve sonuç olarak faturaların şişmesine yol açar. Bu yazıda, bu can sıkıcı sorunu çözmek ve maliyetleri düşürmek için uyguladığım üç temel yöntemi, somut örneklerle paylaşacağım.

Bu sorunla ilk karşılaştığımda, bir e-ticaret platformunun sipariş işleme akışını izliyorduk. Her sipariş için customer_id, product_id, order_id gibi benzersiz tanımlayıcıları etiket olarak kullanıyorduk. Kısa sürede, çok sayıda farklı etiket kombinasyonu oluştu ve Prometheus’umuzun depolama alanı hızla doldu. Sorgular dakikalarca sürmeye başladı. Bu, “observability”nin bize yardımcı olmaktan çıkıp köstek olduğu anlardan biriydi. İşte bu deneyimlerden yola çıkarak, yüksek kardinaliteyi yönetmenin yollarını öğrendim.

Metrikleri Daraltmak: Etiketlerinizi Akıllıca Seçin

Yüksek kardinalitenin temel nedeni, gereksiz yere çok fazla ve çok spesifik etiket kullanmaktır. Bir metriği izlerken, gerçekten neyi bilmemiz gerektiğini sorgulamak ilk adımdır. Örneğin, bir API isteğinin gecikmesini izlerken, request_id veya trace_id gibi her istek için benzersiz olan etiketleri kullanmak genellikle mantıklı değildir. Bu tür bilgileri toplamak için distributed tracing sistemleri (örneğin Jaeger veya Tempo) çok daha uygundur. Metrikler, genellikle daha genel eğilimleri ve sistemin genel sağlığını anlamak için kullanılır.

Sunucu bazında CPU kullanımını izlerken sık görülen bir hata, server_name, datacenter, rack_number, os_version, kernel_version, cpu_model gibi çok sayıda etiketi birlikte kullanmaktır. Bu, sunucu sayısı arttıkça kardinaliteyi astronomik seviyelere taşır. Çoğu zaman temel izleme ihtiyaçları için sadece server_name ve datacenter etiketleri yeterlidir; cpu_model gibi bilgiler nadiren gerekir ve bu tür detaylar için daha spesifik sistem araçlarına başvurmak daha doğrudur. Gereksiz etiketleri ayıkladığınızda metriğin kardinalite sayısı büyük ölçüde azalır.

Bu daraltma stratejisi, sadece depolama maliyetlerini düşürmekle kalmaz, aynı zamanda sorgu performansını da inanılmaz derecede artırır. Az sayıda etiketle yapılan sorgular, veritabanı üzerinde çok daha az işlem gücü gerektirir. Bu, özellikle Prometheus gibi zaman serisi veritabanlarında, sorguların milisaniyeler içinde dönmesini sağlar.

Gerçek Dünya Örneği: customer_id vs. customer_segment

Bir SaaS platformunda, kullanıcı başına düşen API çağrılarını izliyorduk. Başlangıçta customer_id etiketini kullanıyorduk. Bu, her müşteri için ayrı bir zaman serisi anlamına geliyordu. Müşteri sayısı arttıkça, kardinalite hızla yükseliyordu.

Sorunu çözmek için, her müşterinin ait olduğu segmenti (örneğin, free, premium, enterprise) belirleyip, customer_id yerine customer_segment etiketini kullanmaya başladık. Bu basit değişiklik, kardinaliteyi dramatik şekilde azalttı. Artık genel eğilimleri premium segmentindeki kullanıcıların API çağrıları hakkında bilgi edinebiliyorduk. Bireysel müşteri bazında detaylı analiz yapmak istediğimizde ise, bu bilgiyi doğrudan metriklerden değil, loglar veya tracing sistemlerinden temin ediyorduk.

# Eski metrik tanımı (yüksek kardinaliteye neden olur)
http_requests_total{method="GET", path="/api/v1/users", status="200", customer_id="cust_abc123xyz"} 1

# Yeni metrik tanımı (daha düşük kardinalite)
http_requests_total{method="GET", path="/api/v1/users", status="200", customer_segment="premium"} 1

Bu strateji, metriklerinizi daha iyi gruplandırmanıza ve anlamsız yere veri yığınları oluşturmaktan kaçınmanıza yardımcı olur. Unutmayın, observability’nin amacı genel resmi görmek ve anormallikleri tespit etmektir; her bireysel olayı metriklerle kaydetmek genellikle verimsizdir.

Özetleme ve Birleştirme (Aggregation) Stratejileri

Yüksek kardinaliteyi yönetmenin bir diğer etkili yolu, verileri toplama (ingest) anında veya belirli aralıklarla özetlemektir. Bu, ham veriyi daha anlamlı ve daha az kardinaliteye sahip özet metriklerine dönüştürmeyi içerir. Özellikle uzun süre saklanması gereken veya nadiren sorgulanan veriler için bu yaklaşım maliyetleri ciddi şekilde düşürebilir.

İşlem yoğun sistemlerde her işlem için işlem türü, müşteri ID’si, işlem tutarı gibi birçok bilgiyi içeren detaylı loglar tutmak, zamanla logların boyutunu ve sayısını arama yapılamaz hale getirir. Tipik çözüm, belirli zaman aralıkları (örneğin 1 saatlik periyotlar) için müşteri segmenti ve işlem türüne göre toplam işlem sayısı ve ortalama işlem tutarı gibi özet metrikler üretmektir. Bu özet metrikler genel trendleri anlamak için çoğu zaman yeterlidir ve ham loglara olan ihtiyacı azaltır.

Özetleme stratejileri, genellikle bir “pre-aggregation” veya “roll-up” süreci olarak uygulanır. Bu, veri toplama aracınızın (örneğin Prometheus’un rules.yml dosyası veya VictoriaMetrics’in vmctl araçları) bir parçası olabilir. Bu kurallar, belirli metrikleri alıp, etiketlere göre gruplayarak yeni özet metrikler üretir.

Gerçek Dünya Örneği: Günlük Raporlar İçin Toplanan Veriler

Bir üretim tesisinin ERP sistemi için günlük raporlar hazırlıyorduk. Bu raporlar, her bir makinenin ürettiği parça sayısı, hata oranları ve duruş süreleri gibi bilgileri içeriyordu. Başlangıçta her makinenin her dakika ürettiği veriyi kaydediyorduk. Bu, her gün çok büyük hacimde veri anlamına geliyordu.

Sorunu çözmek için, her saat sonunda, her makine için toplam üretilen parça sayısı, toplam hata sayısı ve toplam duruş süresi gibi özet değerleri hesaplayan bir iş akışı geliştirdik. Bu özet değerler, daha az sayıda etiketle (makine adı, vardiya gibi) saklanıyordu. Günlük raporlar artık bu özet veriler üzerinden oluşturuluyordu. Bu sayede, veri saklama ihtiyacımız büyük ölçüde azaldı ve raporlama süreleri belirgin şekilde kısaldı.

# Prometheus rules.yml örneği
groups:
- name: aggregation_rules
  rules:
  - record: job:http_requests_total:sum_by_status_path
    expr: sum by (path, status) (rate(http_requests_total[5m]))

  - record: job:machine_production_total:sum_by_machine_shift
    expr: sum by (machine_id, shift) (increase(machine_production_counter[1h]))

Bu tür özetleme kuralları, hem maliyetleri düşürmek hem de performansı artırmak için kritik öneme sahiptir. Özellikle uzun vadeli analizler için ham veriye sürekli erişim ihtiyacınız yoksa, özetlenmiş veriler çoğu zaman yeterli olacaktır.

Veri Saklama Süresini (Retention Period) Optimize Etmek

Observability verilerinin maliyetini düşürmenin en doğrudan yollarından biri, veri saklama sürelerini optimize etmektir. Her metriğin ne kadar süreyle saklanması gerektiği, iş ihtiyaçlarına ve yasal düzenlemelere göre belirlenmelidir. Her veriyi sonsuza dek saklamak, hem maliyetli hem de gereksizdir.

Pratikte sık karşılaşılan bir durum, tüm olayların uzun bir varsayılan süre boyunca (örneğin 30 gün) saklanması; oysa bir analiz yapıldığında çoğu zaman birkaç günden eski verilere neredeyse hiç bakılmadığı görülür. Saklama süresini gerçekte kullanılan pencereye indirmek, depolama maliyetlerinde kayda değer bir düşüş sağlar.

Çoğu observability aracı (Prometheus, Grafana Loki, Elasticsearch vb.), farklı metrik türleri veya etiketlere göre farklı saklama politikaları belirlemenize olanak tanır. Örneğin, kritik sistem metriklerini 30 gün, daha az kritik olanları 7 gün, hata loglarını ise sadece 2 gün saklayabilirsiniz. Bu esneklik, kaynakları daha verimli kullanmanızı sağlar.

Gerçek Dünya Örneği: Yasal Uyumluluk ve Anomali Tespiti

Finansal teknoloji (FinTech) gibi alanlarda, yasal uyumluluk gereği bazı işlem detaylarını en az 1 yıl boyunca saklamak zorunlu olabilir. Ancak gerçek zamanlı anomali tespiti ve kısa vadeli performans analizi için bu kadar uzun süreye ihtiyaç yoktur. Bu durumda işe yarayan yaklaşım, farklı saklama politikalarını katmanlamaktır:

  • Kritik işlem detayları (raw logs): Yasal uyumluluk için 1 yıl saklandı.
  • İşlem sayısı ve işlem hacmi gibi özet metrikler: 30 gün boyunca yüksek çözünürlükte, ardından 1 yıl boyunca düşük çözünürlükte (daha az sıklıkla toplanan veriler) saklandı.
  • Kısa süreli anomali tespiti için kullanılan metrikler: Sadece 7 gün boyunca saklandı.

Bu çok katmanlı saklama stratejisi, hem yasal gereklilikleri karşılamayı sağlar hem de kısa vadeli operasyonel ihtiyaçlar için maliyetleri önemli ölçüde düşürür. Veri saklama süresini katmanlı şekilde optimize etmek, depolama maliyetlerinde belirgin tasarruf getirir.

# Prometheus yapılandırması (prometheus.yml örneği)
storage:
  rules:
    external_rules:
      - /etc/prometheus/rules/*.yml
  tsdb:
    retention.time: 7d # Varsayılan olarak 7 gün
    retention.size: 0  # Boyut limitini kapat (zaman bazlı çalışır)

# Farklı saklama süreleri için farklı depolama bölgeleri veya araçlar kullanılabilir.
# Örneğin, Loki için farklı saklama süreleri ayarlanabilir.

Veri saklama süresini belirlerken, “ne kadar süreyle ihtiyacımız olabilir?” sorusunu sormak yerine, “ne kadar süreyle kesinlikle ihtiyacımız var?” sorusunu sormak daha pragmatik bir yaklaşımdır. Bu, gereksiz veri birikimini önler ve observability sisteminizin daha verimli çalışmasını sağlar.

Observability, sistemlerimizin görünürlüğünü artıran güçlü bir araçtır. Ancak, bu gücü kontrolsüz bir maliyet artışına dönüştürmemek önemlidir. Yüksek kardinaliteyi yönetmek, metrikleri akıllıca seçmek, verileri özetlemek ve saklama sürelerini optimize etmek, hem maliyetleri düşürmenize hem de observability sisteminizin etkinliğini artırmanıza yardımcı olacaktır. Bu üç yöntemi uygulayarak, observability yatırımlarınızdan en iyi şekilde yararlanabilirsiniz.

Paylaş:

Bu yazı faydalı oldu mu?

Yükleniyor...

Bu yazı nasıldı?

Sıkça Sorulanlar

Bu makale ile ilgili okurların sorduğu yaygın sorular.

Yüksek kardinaliteyi azaltmak için mevcut metriği nasıl daraltmaya başlayabilirim?
İlk adımda ben, metriğin etiketlerini en az bir haftalık veri setiyle export edip bir spreadsheet’e aktarıyorum. Ardından "label cardinality" sütununu sıralayarak en çok benzersiz kombinasyona sahip etiketleri belirliyorum. Örneğin, sipariş akışı izlerken `request_id` ve `trace_id` gibi her çağrı için tekil olan etiketleri kaldırıyorum; bunun yerine sadece `service` ve `endpoint` gibi daha genel etiketleri tutuyorum. Bu değişikliği bir staging ortamında uygulayıp cardinality'nin belirgin şekilde azaldığını ve depolama maliyetinin gözle görülür düştüğünü gözlemledim. Böyle bir adım, sorunun kök nedenini netleştirerek daha hedefli optimizasyon yapmamı sağladı.
Prometheus'ta etiketleri yeniden tasarlarken hangi araçları veya sorguları kullandım ve bunların avantajları nelerdir?
Ben, etiket yeniden tasarımı sırasında `promtool` ile metric validation ve `prometheus --storage.tsdb.retention.time` ayarlarını kontrol ediyorum. Etiketleri filtrelemek için `metric_relabel_configs` içinde regex bazlı kurallar tanımladım; bu sayede `customer_id` gibi yüksek kardinaliteye sahip etiketleri sadece belirli bir segmentte (örneğin, VIP müşteriler) tutabiliyorum. Ayrıca, `recording rules` yazarak sık kullanılan sorguları önceden hesaplatıp yeni düşük kardinaliteli serilere yönlendiriyorum. Bu yaklaşım, sorgu süresini belirgin şekilde kısaltırken, veri saklama maliyetinde de ciddi tasarruf sağladı.
Etiketleri kaldırdıktan sonra beklenmeden veri kaybı ya da sorgu hatası alırsam ne yapmalıyım?
Böyle bir durumda ben, önce değişikliği bir canary deployment ile sınırlı bir pod setine uyguluyorum ve `prometheus_tsdb_head_series` metriğini izleyerek yeni seri sayısındaki ani düşüşleri tespit ediyorum. Eğer kritik bir metric kaybolmuşsa, eski `relabel_config` dosyasını geri alıp bir geçiş süresi tanımlıyorum; aynı zamanda `recording rules` ile eski etiketli veriyi yeni seriye kopyalayan bir migration job çalıştırıyorum. Loglarda `label mismatch` uyarılarını kontrol edip, hatalı regex’i düzeltiyorum. Bu geri dönüş stratejisi, veri bütünlüğünü korurken değişiklikleri güvenli bir şekilde test etmeme olanak tanıdı.
Kardinaliteyi düşük tutmak için "her istek için trace_id etiketi eklemek" yaygın bir uygulama mı, bu doğru mu?
Genel kanı doğru değil; ben bu mit’i defalarca gördüm ve projelerimde denedim, sonuçta cardinality katlanarak artıyor ve sorgular kullanılamaz hale geliyordu. Trace bilgisi zaten dağıtık izleme sistemleri (Jaeger, Zipkin) tarafından ayrı bir veri akışı olarak saklanıyor; metriklerde `trace_id` tutmak sadece tekrar eden veri yaratır. Bunun yerine, metriklerde sadece `service` ve `operation` gibi sabit etiketleri tutup, detaylı izleme ihtiyacını ayrı bir tracing pipeline'ına yönlendiriyorum. Bu strateji, hem maliyetleri düşürüyor hem de observability stack'inin ölçeklenebilirliğini koruyor.
ME

Mustafa Erbay

Sistem Mimarisi · Network Uzmanı · Altyapı, Güvenlik ve Yazılım

2006'dan bu yana sistem mimarisi, network, sunucu altyapıları, büyük yapıların kurulumu, yazılım ve sistem güvenliği ekseninde çalışıyorum. Bu blogda sahada karşılığı olan teknik deneyimlerimi paylaşıyorum.

Kişisel Notlar

Bu notlar sadece sizde saklanır. Tarayıcınızda yerel olarak tutulur.

Hazır 0 karakter

Yorumlar

Sunucu Taraflı AI Moderasyon

Yorumlar sunucuda yapay zeka ile denetlenir ve kalıcı olarak saklanır.

?
0/2000

Sunucu taraflı AI denetim

✉️ Ücretsiz · Spam yok · İstediğin an çık

Yeni yazılardan haberdar olun

Yeni içerikler ve teknik notlar e-postanıza gelsin.

  • 📌
    Haftanın en iyisi Sadece okumaya değer tek yazı
  • 🔧
    Alet çantası Bu hafta kullandığım araçlar
  • 🧠
    Perde arkası Blog'a girmeyen notlar

Spam yapmıyoruz. İstediğiniz zaman ayrılabilirsiniz. · Sadece Umami (self-hosted, Google yok) ile takip.

Okuma İstatistikleriniz

0

Yazı Okundu

0dk

Okuma Süresi

0

Gün Serisi

-

Favori Kategori

İlgili Yazılar