Dört Altın Sinyal Öldü Mü? Determinimistik Olmayan Altyapılarda Yeni Nesil Telemetri Tasarımı
Google SRE Book hayatımıza girdiğinden beri latency, traffic, errors ve saturation dörtlüsünü (yani golden signals) kutsal kase olarak kabul ettik. Ancak günümüzün non-deterministic infrastructure (deterministik olmayan altyapı) ve dinamik microservices monitoring dünyasında, bu statik metrikler artık sistemin gerçek sağlığını göstermekte yetersiz kalıyor. Modern ve dinamik sistemlerde ayakta kalabilmek için observability odaklı, yeni nesil bir telemetry design yaklaşımına geçmek zorundayız.
Peki ama neden? Çünkü artık “sunucu ayakta mı?” sorusu anlamsız. Kubernetes cluster’ınızda bir pod ölüyor, yerine yenisi geliyor; serverless fonksiyonlar milisaniyeler içinde cold start yaşayıp kayboluyor. Bu yazıda, geleneksel dört altın sinyalin neden yetersiz kaldığını ve modern dağıtık mimarilerde nasıl bir telemetri mimarisi kurmanız gerektiğini teknik detaylarıyla inceleyeceğiz.
Klasik Metriklerin Epistemolojik Çöküşü
Eski dünyada her şey basitti. Bir bare-metal sunucumuz, bir load balancer’ımız ve bir veritabanımız vardı. CPU %90’a ulaştığında disk IOPS limitine yaklaşıyorduk ve bu net bir alarm sebebiydi. Bugün ise CPU kullanımı tek başına hiçbir şey ifade etmiyor. Container bazlı kısıtlamalar (CFS throttling), multi-tenant yapılar ve mikroservislerin birbirleriyle olan asenkron ilişkileri, klasik “saturation” metriğini anlamsızlaştırıyor.
Deterministik olmayan altyapılarda bir hata (error), genellikle tek bir bileşenin çökmesinden değil; ağ gecikmesi, rate limitler, queue derinliği ve veri tutarsızlığı gibi birden fazla faktörün bir araya gelmesiyle (emergent behavior) oluşur. Dolayısıyla, sadece giriş ve çıkış kapılarını izleyerek içeride ne olduğunu anlamamız imkansızdır.
Dört Altın Sinyal Nerede Patlıyor?
Klasik dört altın sinyali tek tek masaya yatıralım ve modern mimarideki sınırlarını görelim:
- Latency (Gecikme): Ortalama (mean) latansı ölçmek bir yalandır. p99 veya p99.9 latansı bile bazen yanıltıcı olabilir. Eğer bir istek arka planda 50 farklı mikroservise dokunuyorsa, kümülatif p99 latansı tamamen kontrol dışı kalır. Bize gereken, istek bazlı bağlamsal gecikmedir (contextual latency).
- Traffic (Trafik): Saniyedeki istek sayısı (RPS) tek başına sistem yükünü açıklamaz. 1000 basit read isteği ile 10 tane yoğun write/join isteği sistemde aynı saturation’ı yaratmaz.
- Errors (Hatalar): HTTP 500’leri yakalamak kolaydır. Peki ya 200 OK dönen ama boş gövde (empty payload) gönderen veya mantıksal olarak hatalı çalışan servisler? Ya da circuit breaker devreye girdiği için hızlıca hata dönen (“fail-fast”) ama aslında downstream servislerin ayakta olduğu durumlar?
- Saturation (Doygunluk): Kubernetes ortamında bir container’ın CPU limiti (limit ve request farkı) yüzünden throttle edilmesi, host makinenin CPU’sunun boş olmasına rağmen uygulamanın yavaşlamasına neden olur. Klasik host-level saturation izleme burada tamamen kör kalır.
Yeni Nesil Telemetry Design: OpenTelemetry ile Bağlamsal İzleme
Çözüm, metrik, log ve trace verilerini birbirinden bağımsız adalar olarak toplamayı bırakmaktır. Modern bir telemetry design, yüksek kardinaliteye (high cardinality) ve bağlam geçişine (context propagation) dayanmalıdır.
Aşağıdaki OpenTelemetry Collector konfigürasyon bloğu, deterministik olmayan bir ortamda metrik ve trace verilerini nasıl zenginleştirebileceğimizi ve sistem üzerindeki “gürültüyü” nasıl azaltabileceğimizi gösteriyor. Burada özellikle transform processor’ını kullanarak dinamik etiketleme (enrichment) yapıyoruz:
receivers:
otlp:
protocols:
grpc:
http:
processors:
batch:
send_batch_size: 8192
timeout: 5s
send_batch_max_size: 10240
memory_limiter:
check_interval: 1s
limit_percentage: 75
spike_limit_percentage: 15
resourcedetection:
detectors: [env, gcp, ecs, ec2, k8snode]
timeout: 2s
transform:
error_mode: ignore
metric_statements:
- context: datapoint
statements:
- set(attributes["env"], "production")
- set(attributes["service.tier"], "critical") where attributes["service.name"] == "payment-gateway"
exporters:
otlp/prometheus:
endpoint: "prometheus-gateway:9090"
tls:
insecure: true
otlp/jaeger:
endpoint: "jaeger-collector:4317"
tls:
insecure: true
service:
pipelines:
metrics:
receivers: [otlp]
processors: [memory_limiter, resourcedetection, transform, batch]
exporters: [otlp/prometheus]
traces:
receivers: [otlp]
processors: [memory_limiter, resourcedetection, batch]
exporters: [otlp/jaeger]
Bu konfigürasyondaki resourcedetection adımı kritiktir. Uygulamanın hangi k8s podunda, hangi cloud provider üzerinde çalıştığını koda dokunmadan telemetri verisine enjekte eder. Bu sayede, deterministik olmayan altyapılardaki transient (geçici) hataları analiz ederken “Altyapısal bir dalgalanma mı oldu yoksa kodda mı hata var?” sorusuna anında yanıt bulabiliriz.
Dinamik Eşik Değerleri ve Anomalilerle Mücadele
Geleneksel alerting sistemleri statik threshold (eşik değer) mantığına dayanır. Örneğin: “CPU %80’i geçerse alarm ver.” Ancak auto-scale olan bir cluster’da bu kural sabaha karşı anlamsız alarmlarla uyanmanıza sebep olur. Bunun yerine PromQL kullanarak dinamik standart sapma (standard deviation) bazlı anomalileri tespit etmeliyiz.
Aşağıdaki PromQL sorgusu, bir servisin son 5 dakikadaki latansını (p99), son 1 haftalık geçmiş verinin ortalaması ve standart sapmasıyla karşılaştırır. Eğer mevcut latans, tarihsel sapmanın 3 katından fazlaysa bu gerçek bir anomalidir:
(
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service))
-
avg_over_time(histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service))[1w])
)
/
stddev_over_time(histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service))[1w])
> 3
Neden böyle bir sorgu kullanmalıyız? Çünkü her pazartesi saat 09:00’da sistemde doğal bir trafik artışı (ve dolayısıyla latans yükselmesi) oluyorsa, statik bir alert tetiklenir. Ancak bu dinamik sorgu, geçmiş pazartesi verilerini de hesaba katarak sistemi tolere eder. Böylece SRE ekibinin alert fatigue (alarm yorgunluğu) yaşamasının önüne geçilmiş olur.
eBPF: Altyapıyı Kodsuz Gözlemlemek
Uygulama seviyesinde SDK entegrasyonu yapmak her zaman mümkün veya pratik olmayabilir. Özellikle legacy servislerin veya üçüncü parti bileşenlerin (örneğin redis, nginx veya veri tabanları) telemetri verilerini toplamak ciddi bir operasyonel yük getirir.
İşte burada devreye eBPF (Extended Berkeley Packet Filter) giriyor. Kernel seviyesinde çalışan eBPF probaları sayesinde uygulamaya tek bir satır kod eklemeden, ağ paketlerini ve sistem çağrılarını (syscalls) intercept ederek ultra-low overhead ile telemetri üretebiliriz.
Örneğin, bir Kubernetes cluster’ında tüm podlar arasındaki TCP handshake sürelerini ve paket kayıplarını eBPF tabanlı bir tool (örn. Hubble/Cilium veya Pixie) ile izlediğinizde, “Ağda paket kaybı var ama hangi podlar etkileniyor?” sorusuna sıfır kod değişikliğiyle yanıt bulursunuz. Bu, modern observability vizyonunun en kritik yapı taşlarından biridir.
Sonuç: Yeni Nesil Telemetri Tasarımı İçin Yol Haritası
Dört altın sinyal tamamen ölmedi, ancak artık tek başlarına yetersizler. Onları sistemin genel durumunu gösteren kaba göstergeler olarak tutmalı, altını ise bağlamsal izleme ile doldurmalıyız. Başarılı bir yeni nesil telemetri tasarımı için şu adımları uygulamalısınız:
- Log, metrik ve trace’leri tek bir trace_id ve span_id ile birbirine bağlayın (Context Propagation).
- Kardinalite korkusunu aşın. Etiketlerde (tags/attributes) dinamik verileri (customer_id, k8s_pod_name, deployment_version) kullanmaktan çekinmeyin.
- Statik threshold alarmlarından kaçının; anomali tespiti için matematiksel modelleri (Z-score, Holt-Winters) PromQL seviyesinde uygulayın.
- eBPF teknolojisini altyapı gözlemlenebilirliği için bir standart haline getirin.
Unutmayın, sistemleriniz artık deterministik değil. Onları izleme yöntemleriniz de doğrusal ve durağan olamaz.