İçeriğe atla

Kapatmak için ESC tuşuna basın

OpenShift’te log normalizer ile log ve trace’leri eşleştirmek

Log normalizer operator'ü pod'lara sidecar ekleyip log'ları tek JSON formatına çeviriyor, trace_id ve pod bilgisini ekleyerek OTLP ile gönderiyor.

Yazar
Sezer Şanlıkan
Yayın
7 Kasım 2026,
Okuma
3 dakika
OpenShift üzerinde log normalizer sidecar'ının pod log'larını OpenTelemetry collector'a göndermesi
Bu haberde
  1. Korrel8r nedir?
  2. Trace’ten log’a geçişin önündeki engel
  3. Log normalizer pod’a nasıl giriyor
  4. Devreye almadan önce kapasiteyi hesaplayın
  5. Sessiz kalan durumlar
  6. Pilot için ilk adımlar

OpenShift için geliştirilen log normalizer operator’ü, seçilen pod’lara bir sidecar ekleyip uygulama çıktısını kod değişikliği gerektirmeden tek tip bir JSON kaydına çeviriyor. Kayıtlar kubectl logs ile okunmaya devam ediyor, spec.otlpEndpoint tanımlıysa OTLP gRPC üzerinden bir OpenTelemetry collector’a da gidiyor. Operator, Kubernetes 1.33+ veya OpenShift 4.18+ gerektiren native sidecar modelini kullanıyor.

Korrel8r nedir?

Korrel8r, Kubernetes ve OpenShift ortamlarında log, metrik, trace ve alert gibi observability sinyallerini birbirine bağlayan açık kaynak bir korelasyon motorudur. Bir sinyalden yola çıkıp aynı kaynakla ilişkili diğer sinyallere geçmek için kullanılır. Sorgularını mevcut log ve trace backend’leri üzerinde çalıştırır, verinin kendisini saklamaz. OpenShift konsolundaki sorun giderme akışlarında da yer alır.

Trace’ten log’a geçişin önündeki engel

Korrel8r gibi bir araç ancak ortak alanlar varsa eşleştirme yapabilir. Bir namespace’te JSON, logfmt, klog, Zap console ve düz metin stack trace yan yana akıyorsa trace_id ya hiç yoktur ya da her serviste başka adla durur.

Operator bu sorunu uygulamayı değiştirmeden, pod sınırında çözüyor. Trace_id, traceID, traceId, trace.id, otel.trace_id ve dd.trace_id gibi adları tek bir üst seviye trace_id ve span_id alanına taşıyor. Downward API ile pod adı, namespace, node adı ve pod UID’yi de OpenTelemetry resource attribute’u olarak ekliyor.

Third-party image’lar çalıştırıyorsanız bu özellik en çok işinize yarar. Collector’da her bileşen için parsing kuralı tutmanız veya logging kütüphanesini fork’lamanız gerekmiyor.

Log normalizer pod’a nasıl giriyor

Akış dört parçadan oluşuyor:

  • Operator, LogNormalizerConfig içindeki namespace selector’ı bir MutatingWebhookConfiguration’a çeviriyor.
  • Webhook, pod oluşturulurken bir emptyDir volume, wrapper binary’sini kopyalayan bir init container ve restartPolicy: Always ile çalışan native sidecar ekliyor.
  • Uygulama container’ının komutu yeniden yazılıyor; wrapper stdout ve stderr’i ikiye ayırıp bir kopyayı named pipe’a yolluyor.
  • Sidecar formatı tanıyor, multiline kayıtları birleştiriyor ve Drain tabanlı template_id üretiyor.

Go panic, Java stack trace ve Python traceback için ayrı consolidator’lar var. Bir exception mesajı ile stack frame’leri tek kayıtta kalıyor; alert kurallarınız satır satır parçalanmış hatalarla uğraşmıyor.

Devreye almadan önce kapasiteyi hesaplayın

Örnek yapılandırmada sidecar başına 50m CPU ve 32Mi bellek request’i, 200m CPU ve 128Mi limit var. 200 pod’luk bir namespace’te bu, yalnızca request’lerde 10 çekirdek ve yaklaşık 6,25Gi bellek eder. Namespace’te ResourceQuota tanımlıysa sidecar request’leri de kotadan düşer.

Log hacmi de artabilir. Orijinal çıktı uygulama container’ının stdout’unda kalıyor, normalize edilmiş JSON ise sidecar’ın stdout’una yazılıyor. Node seviyesinde tüm container log’larını toplayan bir agent’ınız varsa aynı olayı iki kez alırsınız. Pilot öncesi hangisini toplayacağınıza karar verin.

Drain ayarlarında maxClusters örnekte 1000. Çok değişken mesaj üreten servislerde similarityThreshold değerini oynatmadan template_id’ye dayanan bir alert kurmayın.

Sessiz kalan durumlar

Webhook failurePolicy: Ignore ile geliyor. Operator kapalıyken açılan pod’lar hata vermeden, normalizer olmadan başlıyor. Rollout sırasında operator yeniden başladıysa bazı replica’lar sidecar’sız kalabilir ve bunu ancak trace’e bağlanamayan log’larda fark edersiniz.

Webhook yalnızca yeni pod’ları değiştiriyor. Etiketi koyduğunuzda mevcut pod’lar olduğu gibi kalıyor. Command tanımlamayan container’larda ENTRYPOINT ve CMD registry’den çözülüyor; çözülemezse o container wrapper’sız başlıyor.

Injection’ın gerçekten yapıldığını pod annotation’ı üzerinden kontrol edin:

oc get pod -n my-app -o \
  jsonpath='{.metadata.annotations.lognormalizer\.opendatahub\.io/injected}{"\n"}'
oc get mutatingwebhookconfiguration log-normalizer-injector

Pilot için ilk adımlar

Operator ve sidecar image’larını kendiniz build edip cluster’ın erişebildiği bir registry’ye push etmeniz gerekiyor. CRD v1alpha1 seviyesinde; alan adları ileriki sürümlerde değişebilir.

Sıra önemli. Önce make install ile CRD’yi kurun, sonra default adlı LogNormalizerConfig’i gerçek sidecarImage değeriyle uygulayın, en son operator’ü deploy edin. Aksi halde operator açılışta placeholder image’lı bir varsayılan yapılandırma oluşturuyor.

Tek bir namespace ile başlayın ve etiketledikten sonra workload’ları yeniden başlatın:

oc label namespace my-app \
  lognormalizer.opendatahub.io/inject=enabled \
  --overwrite

Normalizer’ın girmesini istemediğiniz pod’lar için metadata’ya lognormalizer.opendatahub.io/inject: “false” annotation’ını ekleyin. Collector pod’u aynı namespace’teyse normalizer, debug-exporter çıktısını filtreleyerek feedback loop’u engelliyor. Collector’ı başka bir namespace’te tutarsanız sorun hiç oluşmaz. Korrel8r kurulumu ve backend seçimi bu operator’ün kapsamı dışında, onları ayrıca yapılandırmanız gerekiyor.

İlgili haberler

Tüm haberler

Yeni yazılardan haberdar olun

Sunucu, Kubernetes, DevOps ve güvenlik üzerine yeni yazılar ve site duyuruları e-postanıza gelsin. Reklam yok, adresiniz kimseyle paylaşılmaz.

© 2021–2026 Sezer Şanlıkan