Teknoloji

VPS Log Yönetimi Nasıl Rayına Oturur? Grafana Loki + Promtail ile Merkezi Loglama, Tutma Süreleri ve Alarm Kuralları

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.

Sıkça Sorulan Sorular

Kurulumu nispeten kolay, kaynak tüketimi dengeli ve arama hızları etiketler sayesinde gayet iyi. Promtail ile gürültüyü kaynağında azaltıp, Loki’de makul saklama süreleriyle diski yormadan merkezi loglama kurabilirsiniz. Grafana ile de aramayı, panoları ve alarm kurallarını tek çatıdan yönetirsiniz.

Tek bir doğru yok. Sorun çözme alışkanlığınız, denetim ihtiyaçlarınız ve disk/bütçe durumunuza göre karar verin. Küçük projelerde 7–14 gün iyi bir başlangıç; kritik hataları daha uzun, yüksek hacimli erişim loglarını daha kısa tutabilirsiniz. Zamanla ölçüp ayarlamak en sağlıklısı.

Genelde hafiftir. Filtreleri doğru kurup gereksiz satırları düşerseniz ağ ve disk kullanımını düşürürsünüz. Multiline ve regex aşamalarını abartmadan kullanın; ölçüp baktığınızda çoğu VPS’te belirgin bir yük oluşturmadığını görürsünüz.

Önce eşiği ve zaman penceresini gözden geçirin. Kısa pencereler dalgalanmaya duyarlıdır. LogQL’de filtreyi daraltmak, ‘for’ süresini uzatmak ve uyarı/kritik olarak iki seviyeye bölmek gürültüyü azaltır. Gerekirse belirli saatler için bakım/dağıtım penceresi tanımlayın.