Ofisteki Gece Yarısı Sessizliğinde Gelen İlham: Neden Merkezi Loglama?
Hiç gece yarısı telefonunuz çalıp siteniz erişilemez olduğunda paniklediniz mi? Ben yaşadım. Ekran karşısında gözler yarı kapalı, SSH ile bağlan, sistem günlüklerine bak, uygulama loglarını ara, Nginx ayrı bir şey söylüyor, uygulama başka bir şey… Parçalı log dünyasında kaybolmak bir iki dakikalık iş değil; hele kritik bir akşam satış kampanyası varsa dakikalar uzun, sabır kısa. O gece kendime şunu söyledim: “Bu iş böyle olmayacak, loglar tek bir yerde olacak, araması kolay olacak, bir de alarm kuracağım ki sorun büyümeden haberim olsun.”
İşte bu yazıda tam da bu derdin ilacını konuşacağız. VPS log yönetimini Grafana Loki ve Promtail ile nasıl merkezileştiririz, hangi logları ne kadar süre tutarız, gereksiz gürültüyü nasıl azaltırız ve en önemlisi güvenilir alarm kurallarını nasıl oturturuz adım adım paylaşacağım. Teknik adı observability olsun, günlük dilde “aklım başımda kalsın” diyelim; amacımız stres azaltmak ve netlik kazanmak. Mesela şöyle düşünün: Loglar tek bir pencereden akıyor, arama saniyeler içinde, etiketler (labels) sayesinde filtrelemek çocuk oyuncağı ve alarmlar gerçek sorunları işaret ediyor. Kulağa iyi geliyor, değil mi?
Loki ve Promtail’i Basitçe Düşünelim: Kim Ne İş Yapar?
İlk buluştuğumda Loki’yi şöyle bir benzetmeyle kafama oturttum: Promtail sahadan haber toplayan muhabir, Loki editör masası, Grafana da gazetenin sayfa tasarımcısı. Promtail, VPS’inizdeki dosyalardan, journald’dan ya da konteyner loglarından satırları toplar, bazılarını etiketler, bazılarını budar ve Lokiye gönderir. Loki bu logları ucuz ve hızlı aranabilir bir yapıda saklar, etiketler sayesinde istediğiniz akışı saniyeler içinde önünüze getirir. Sonra Grafana ile panolar kurar, LogQL ile esnek aramalar yapar, gerekirse alarmlar tanımlarsınız.
Bu üçlüden hoşlandığım şey, ağır bir indeksleme yerine etiket temelli yaklaşımı tercih etmeleri. Bu sayede disk ve CPU tüketimi daha sakin; aradığınızı bulma işi de etiketleri mantıklı seçtiğiniz sürece gayet hızlı. Dezavantaj tarafında ise etiket patlamasına yol açacak şekilde her ayrıntıyı label’a dönüştürürseniz işler sarpa sarabiliyor. Yani dozaj önemli. Benim rutinim şu: minimum ama anlamlı etiketler; örneğin app, env, host ve gerekiyorsa level. Geri kalan zenginlik log satırında kalsın, gerektiğinde arar buluruz.
Kurarken akıllı bir yol, önce küçük bir uygulamayla test etmek. Bir iki servisle başlayın, etiketleri azdan çoğa doğru evriltin, sorgularınız yerini buldukça kalıcı kurallara dönüştürün. Zaten bir noktada “şu aramayı çok sık yapıyorum” dediğiniz anda etiket stratejiniz de kendiliğinden netleşiyor.
VPS’te Basit Bir Plan: Servisleri Nerede, Nasıl Koşturacağız?
Benim pratikte kullandığım iki yaklaşım var: Docker Compose ile üçlüyü (Loki, Promtail, Grafana) konteyner olarak ayağa kaldırmak ya da systemd servisleriyle çıplak VPS üzerinde çalıştırmak. Konteyner yöntemi hızlı dönmek için harika; systemd ise daha ince ayar istiyorsanız, disk yollarını ve izinleri kendiniz kurgulamak istiyorsanız daha kontrollü. Hangisini tercih ederseniz edin, bir depolama klasörü ayırın, log ve indeks dosyaları için temiz bir yapı kurun, disk boyutunuzu da gerçekçi tutun. Burada es geçmeyin; loglar büyümeyi sever, siz sınıra gelmeden sınırı onlara gösterin.
Örneğin Promtail için basit bir yapılandırma ile başlayabiliriz. Mesela şöyle düşünün: Nginx, uygulama ve sistem loglarını toplayalım, makul etiketler atalım, bazı gereksiz satırları düşelim, sonra Loki’ye yollayalım. Aşağıdaki örnek, dosya tabanlı log toplayan bir senaryo. Çok karmaşık değil, ama işi görüyor:
# /etc/promtail/config.yml
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /var/lib/promtail/positions.yaml
clients:
- url: http://127.0.0.1:3100/loki/api/v1/push
scrape_configs:
- job_name: nginx
static_configs:
- targets: ["localhost"]
labels:
job: nginx
app: web
env: prod
__path__: /var/log/nginx/*.log
pipeline_stages:
- match:
selector: '{job="nginx"}'
stages:
- regex:
expression: '^(?P<remote_addr>S+) S+ S+ [(?P<time_local>[^]]+)] "(?P<request>[^"]+)" (?P<status>d+) (?P<body_bytes_sent>d+) "(?P<http_referer>[^"]*)" "(?P<http_user_agent>[^"]*)"'
- labels:
status:
http_user_agent:
- drop:
expression: '.*.healthcheck$'
- job_name: app
static_configs:
- targets: ["localhost"]
labels:
job: app
app: api
env: prod
__path__: /var/log/myapp/*.log
pipeline_stages:
- match:
selector: '{job="app"}'
stages:
- multiline:
firstline: '^[0-9]{4}-[0-9]{2}-[0-9]{2}'
- regex:
expression: 'level=(?P<level>w+)'
- labels:
level:
- match:
selector: '{level="debug"}'
action: drop
- job_name: system
journal:
json: false
max_age: 24h
labels:
job: systemd
app: system
env: prod
relabel_configs:
- source_labels: ['__journal__systemd_unit']
target_label: 'unit'
Bu yapı, uygulama loglarından debug satırlarını düşer, Nginx tarafında gereksiz healthcheck isteklerini filtreler ve sistem günlüklerini de bir etikete iliştirir. Multiline aşaması ise uzun stack trace kayıtlarını tek olay olarak birleştirir; özellikle Java, .NET gibi platformlarda hayat kurtarır. Yalın ama işe yarar.
Eğer konteyner dünyasında geziyorsanız, Docker loglarını da Promtail ile doğrudan alabilirsiniz. Zamanla kendi akışınıza en uygun yöntemi buluyorsunuz. Bu arada konteyner tabanlı WordPress veya benzeri sistemlerde log yönetimine değindiğim şu yazı pratik olabilir: Docker ile WordPress’i VPS’te yaşatırken logları nerede, nasıl tuttuğumu anlattığım rehber. Benzer desenleri Promtail tarafında da kullanabilirsiniz.
Loki Tarafında Saklama (Retention): Ne Kadar, Nerede ve Neden?
İtiraf edeyim: En çok sorulan soru “Ne kadar süre log tutalım?” oluyor. Burada tek doğru yok. Üç şeye bakıyorum: sorun çözme alışkanlığı (geriye dönük ne kadar inceliyorsunuz), mevzuat/denetim gereksinimleri ve disk/bütçe gerçekleri. Küçük bir uygulama için 7–14 gün genelde huzurlu bir bölge. Trafiğin yoğun olduğu bir e‑ticaret için kritik logları daha uzun, gürültüyü daha kısa tutuyorum. Mesela ERROR seviyesindeki uygulama logları 30 gün, Nginx access logları 7 gün gibi. Ama bunu tek bir devreyle yönetmek yerine Loki’nin retention mekanizmasını kullanmak işleri kolaylaştırıyor.
Loki’nin yeni nesil kompaktör (compactor) yapısıyla saklama sürelerini global veya etiket bazlı tanımlayabiliyorsunuz. Global bir tutma süresi, işe başlamak için iyi bir taban. Daha incelikli akışlar için belirli etiket kombinasyonlarıyla daha kısa/uzun tutma süresi kurgulanabiliyor. Senaryonuz büyüdükçe üzerine inşa edersiniz. Aşağıdaki örnek, global bir süreyi ve kompaktörü etkinleştirir; dosya sistemiyle de gayet iyi çalışır. Üretimde obje depolama (S3/GCS) şart değil ama büyüdükçe gönül rahatlığı veriyor.
# /etc/loki/config.yml
server:
http_listen_port: 3100
grpc_listen_port: 9096
common:
path_prefix: /var/lib/loki
storage:
filesystem:
chunks_directory: /var/lib/loki/chunks
rules_directory: /var/lib/loki/rules
replication_factor: 1
ring:
instance_addr: 127.0.0.1
kvstore:
store: inmemory
schema_config:
configs:
- from: 2024-01-01
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
limits_config:
reject_old_samples: true
reject_old_samples_max_age: 168h # 7 gün
retention_period: 168h # global saklama (7 gün)
compactor:
working_directory: /var/lib/loki/compactor
shared_store: filesystem
compactor_ring:
kvstore:
store: inmemory
retention_enabled: true
ruler:
alertmanager_url: http://127.0.0.1:9093
rule_path: /var/lib/loki/rules-temp
storage:
type: local
local:
directory: /var/lib/loki/rules
ring:
kvstore:
store: inmemory
enable_api: true
Bu yapı özetle şunu diyor: Tutma sürem 7 gün, kompaktör etkin, kurallar ve depolar dosya sistemi üzerinde. Daha ayrıntılı ve akış bazlı saklama için Loki’nin resmi dokümantasyonu iyi bir yol arkadaşı; etiket seçicilerle belli uygulama ve seviyeler için farklı süreler tanımlayabiliyorsunuz. Burada bir tavsiye: önce global bir süre belirleyin, disk baskısını hissedince ya da iş ihtiyacı doğunca akış bazında uzatıp kısaltın. Kâğıt üzerinde mükemmel olan, pratikte nadiren mükemmel.
Uzun süre saklama gerektiren kurumlar için sıcak-soğuk yaklaşımı seviyorum. Sıcak tarafta Loki’de güncel loglar, soğuk tarafta ise sık erişilmeyen arşivler. Soğuk tarafı S3 uyumlu depoya atıp, gerektiğinde geri alma stratejisi kurulabilir. Bu konuda S3 uyumlu uzak yedekleme ve saklama üzerine anlattıklarım size fikir verebilir; log arşivi de temelde aynı mantıkla akıyor.
Promtail ile Gürültüyü Azaltmak: Etiketler, Multiline ve İnce Ayar
Promtail tarafında küçük dokunuşlar büyük rahatlık getiriyor. Mesela şöyle düşünün: Üretimde debug satırlarına nadiren bakıyorsunuz, ama onlar log hacmini şişiriyor. İlk aşamada debug’u düşmek bile disk ve ağ kullanımını belirgin azaltır. Bir de gereksiz sağlık kontrollerini (healthcheck) filtrelediniz mi, Nginx trafiği yarı yarıya sakinleşebiliyor. Bunlar küçük ama etkili.
Etiket seçiminde cimri olun derim. Kullanışlı bir set genelde şunlardan oluşuyor: app (hangi uygulama), env (ortam: dev/stage/prod), host (sunucu adı), job (kaynak). Opsiyonel olarak level ve belli durumlarda status. Her kullanıcı kimliği, her istek URL’si, her parametre etiket olursa Loki’nin güçlü yanını zayıf noktaya çevirirsiniz. İhtiyaç olunca log satırından arar buluruz; gerekirse sonra etiketleriz.
Multiline kuralları ise ayrı bir nimettir. Java stack trace, Python trace, Node.js hata yığınları; hepsi tek olay olarak birleşince hem analiz hem alarm kuralları derli toplu olur. firstline deseninizi uygulamanızın log formatına göre ayarlayın ve test edin. Bu test için en iyi yöntem, bir staging ortamında gerçek logları birkaç gün izlemek. Kendi deneyimimde, multiline’ı oturtunca yanlış alarm sayısı hissedilir şekilde düşüyor.
Bir not da güvenlik için. Loglar, hassas bilgiler sızdırma konusunda sinsidir. Promtail pipeline’ına küçük bir redaction (maskleme) aşaması ekleyip e‑posta, token, kredi kartı benzeri desenleri yıldızlamak işinizi kolaylaştırır. Doğru yerde bir regex ve replace aşaması, ileride çok şey kurtarır.
Grafana ile Arama, Pano ve Alarm: LogQL’e Dostça Bir Bakış
Gelelim işin eğlenceli kısmına. Grafana’da Loki veri kaynağını ekleyip ilk sorgunuzu çalıştırdığınızda “Vay be” dedirten o anı hatırlıyorum. LogQL, Prometheus mantığını arkasına almış; çok sert değil, ama güçlü. Basit başlayın: {app="api", env="prod"} ile akışı yakalayıp bir de |= "ERROR" ekleyin. Sonra “kaç taneymiş bunlar” diyorsanız count_over_time({app="api", env="prod"} |= "ERROR" [5m]) sizi hedefe götürür.
Mesela şöyle bir alarm düşünelim: Son 5 dakikada bir uygulamanın hata satırları belirli bir eşiği aştıysa haber ver. Bunu iki yolla kurabilirsiniz. Birincisi, Grafana’nın kendi alerting sistemiyle bir panelden kural türetmek. İkincisi, Loki’nin ruler bileşeniyle LogQL tabanlı alarmları doğrudan Alertmanager’a iletmek. Ben çoğu zaman Grafana üzerinden başlıyorum; görsel arayüz göz dolduruyor, sonra kalıcı hale getirmek için provisioning ekliyorum. Ruler yoluyla kalıcı kurallar isterseniz aşağıdaki gibi bir örnek işinizi görür:
# /var/lib/loki/rules/app-alerts.yml
groups:
- name: loki-app-alerts
rules:
- alert: UygulamaHataOraniYuksek
expr: sum(rate({app="api", env="prod"} |= "ERROR" [5m])) by (app) > 1
for: 2m
labels:
severity: warning
annotations:
summary: "API uygulamasında hata oranı yükseldi"
description: "Son 5 dakikada hata satırları eşiği aştı. Bakılması önerilir."
Buradaki for süresi, anlık sıçramaları elemek için önemli. Bir dakika şans eseri bir iki hata göründü diye telefonunuz çalmasın; asıl kalıcı bozulmaları tespit edin. Eşik değerini de gerçek kullanımınıza göre ayarlayın. İlk gün yüksekten başlayın, gürültü yoksa düşürün. Tam tersi durumda eşikleri biraz yükseltin ya da filtreyi daraltın. LogQL tarafında yeniyseniz bu ikili kaynak çok faydalı: Loki’nin resmi dokümantasyonu ve Grafana’nın yeni alerting sistemi.
Kendi pratiklerimden birkaçı şöyle: Hata oranı için uyarı ve kritik olmak üzere iki eşik kullanıyorum; kritik alarmda telefon, uyarıda Slack yeterli. Nginx 5xx dalgalanmalarını ayrı ele alıyorum; uygulama seviyesindeki hatalarla karışmasın. Bir de geceleri otomatik deploy yapıyorsanız, o zaman diliminde kısa süreli “deploy penceresi” gerekebiliyor. Bu arada canlıya geçiş, servis yönetimi ve log düzeninin birbirini nasıl tamamladığını şu yazıda örneklerle konuştuk: PM2/Systemd ve Nginx ile canlıya alırken panik yapmamak. Alarmların gereksiz tetiklenmesini azaltmak için oradaki deploy ritmini de oyuna katın.
Günlük Hayatta Küçük Dokunuşlar: Disk, Yedek, CI/CD ve Temizlik
İşin bir de işletme tarafı var. Disk büyüyüp dolduğunda kimse mutlu olmaz. Loki’nin retention ayarları tamam ama yine de du ve df ile düzenli ölçüm iyidir; Grafana’da basit bir panelle disk kullanımını izlemek için Node Exporter gibi araçları da oyuna katabilirsiniz. Temel ihtiyaç şu: Sınırın yakınında alarm çalsın, siz de saklama süresini veya filtrelemeyi ayarlayın.
Yedekleme kısmında, loglar kritik bir denetim izi taşıyorsa, sadece “saklama süresi var” diye rahat etmeyin. Zaman zaman anlık arşiv almak iyi hissettirir. Burada restic ve borg ile S3 uyumlu uzak yedekleme yazısında anlattığım yaklaşım, log arşivleri için de uygulanabilir. Elbette gizlilik ve maskeleme kurallarını dışarı atmadan önce iki kez kontrol edin.
CI/CD hattınız varsa, log akışına deploy bilgisini etiket olarak iliştirmek çok işe yarar. Sürüm numarası ya da git SHA’yı bir ortam değişkeni olarak uygulama loglarına eklemek, “Bu hata hangi sürümde görünmeye başladı?” sorusunun süresini dakikalardan saniyelere indirir. CI/CD tarafını detaylı ele aldığım sıfır kesinti CI/CD rehberini okursanız, bu bağı kurmak kolaylaşır. Ayrıca logların merkezi bir yerde toplanmasının, dağıtıma hazırlık ve geri alma süreçlerinde nasıl moral verdiğini göreceksiniz.
Kapanışı küçük bir hatırlatmayla yapayım: Merkezi loglama tek başına kahraman değil; izleme ve ölçüm ailesinin bir üyesi. Ben logları Grafana panoları, metrikler ve ping/uptime kontrolleriyle birlikte kuruyorum. Bu bütünü, daha önce anlattığım merkezi loglama ve gözlemlenebilirlik üzerine yazıda daha geniş çerçevede irdeledik. Hepsi bir arada olunca hem sakin, hem hızlı karar veren bir sistem doğuyor.
Son Rötuşlar: Taktikler, Tuzaklar ve Sağduyu
Biraz da sahadaki minik dersler. Fazla etiket, güzel görünen ama pahalı bir alışkanlıktır; ölçülü olun. Bir anda alarm yağmuruna tutulduysanız, sorun çoğu zaman eşik ya da pencere boyutudur; önce “for” süresini artırarak deneyin. Multiline kuralları her şeyi sihirli değnekle düzeltmez; bazı uygulamalar özel format kullanır, birkaç revizyon gerekebilir. Nginx tarafında 4xx ile 5xx’leri aynı kekin dilimi gibi düşünmeyin; biri kullanıcı kaynaklı, diğeri genelde sunucu kaynaklıdır; alarm mantığı ayrı olunca değerlendirme daha tutarlı olur.
Dokümantasyona sarılmayı da unutmayın. Loki için Loki’nin resmi dokümantasyonu açık ve güncel, Promtail’in detayları için Promtail yapılandırma rehberi elinizin altında dursun. Adım adım giderseniz kısa sürede “Bunu daha önce niye yapmamışım” noktasına geliyorsunuz. Ve son bir not: Log yönetimi canlı bir organizma. Bugün çalışan ayar, yarın trafiğiniz değişince küçük bir dokunuş isteyebilir. Sağduyuyu elden bırakmadan ölç, gözle, ayarla döngüsünü alışkanlık haline getirin.
Kapanış: Sakin Zihin, Net Loglar ve Güvenilir Alarmlar
Toparlayalım. VPS’te log yönetimini rayına oturtmak için dev bir bütçeye ya da devasa bir kümeye ihtiyacınız yok. Grafana Loki ve Promtail, doğru seçilmiş etiketler ve akıllı filtrelerle son derece pratik bir merkez sunuyor. Saklama süresini önce makul bir seviyede başlatın; disk kullanımını izledikçe, iş ihtiyaçlarınıza göre uzatıp kısaltın. Alarm kurallarında küçük adımlarla gidin; gereksiz bildirimleri eleyip gerçekten önemi olan olayları öne çıkarın. Sürüm bilgisi gibi zenginleştirici detayları loglara iliştirin; sorun giderme seansları daha kısa, daha keyifli geçsin.
Umarım bu yazı size fikir vermiştir. Ben bu düzeni kurduktan sonra gece yarısı gelen telefonlar azaldı; gelse bile panik yerine bir planım oluyor. Siz de kendi akışınıza uyarlayın, ufak bir servisle başlayın, sonra yaygınlaştırın. Takıldığınız yerde dönüp bir kez daha bakabileceğiniz bir rehber bırakmak istedim. Bir dahaki yazıda görüşmek üzere; loglarınız sakin, alarmlarınız tam yerinde çalsın.
