Loki ile Hafif Log Yönetimi: Grafana Entegrasyonu

Klasik ELK stack kurduysanız ve ardından sunucunun RAM’ini erittiğini gördüyseniz, Loki’nin neden bu kadar popüler hale geldiğini anlamak zor olmayacak. Grafana Labs tarafından geliştirilen Loki, “Prometheus ama loglar için” felsefesiyle tasarlanmış, hafif ve ölçeklenebilir bir log toplama sistemidir. Elasticsearch gibi logların içeriğini tam metin indekslemek yerine, sadece metadata etiketlerini indeksler. Bu yaklaşım disk alanı ve bellek kullanımını dramatik biçimde düşürür.

Bu yazıda bare metal bir Ubuntu sunucudan başlayarak Loki, Promtail ve Grafana’yı ayağa kaldıracağız, gerçek dünya senaryolarında nasıl sorgu yazılır göreceğiz ve production ortamında dikkat edilmesi gereken noktaları ele alacağız.

Loki’nin Mimarisi ve ELK’dan Farkı

Loki üç temel bileşenden oluşur:

  • Loki: Log verilerini depolayan ve sorgulayan ana servis
  • Promtail: Sunuculardan log toplayan agent (Prometheus’un node_exporter’ı gibi düşünebilirsiniz)
  • Grafana: Görselleştirme ve sorgulama arayüzü

Elasticsearch log satırlarının her kelimesini indeksler, bu yüzden arama hızlıdır ama kaynak tüketimi yüksektir. Loki ise log satırlarını ham halde saklar ve sadece etiketleri (labels) indeksler. {app="nginx", env="production"} gibi etiketlerle log akışlarını filtreler, içerik araması yaparken ise grep benzeri bir yaklaşım kullanır. 10 GB log için Elasticsearch 2-3 GB RAM isterken Loki aynı veri için 200-300 MB ile idare edebilir.

Kurulum: Ubuntu 22.04 Üzerinde Loki

Önce gerekli dizinleri ve kullanıcıyı oluşturalım:

# Loki için sistem kullanıcısı oluştur
sudo useradd --system --no-create-home --shell /bin/false loki

# Çalışma dizinlerini oluştur
sudo mkdir -p /opt/loki /etc/loki /var/lib/loki /var/log/loki

# Loki binary'sini indir (en güncel sürüm için GitHub releases kontrol edin)
cd /tmp
wget https://github.com/grafana/loki/releases/download/v2.9.4/loki-linux-amd64.zip
unzip loki-linux-amd64.zip
sudo mv loki-linux-amd64 /usr/local/bin/loki
sudo chmod +x /usr/local/bin/loki

# Dizin izinlerini ayarla
sudo chown -R loki:loki /opt/loki /var/lib/loki /var/log/loki

Şimdi Loki konfigürasyon dosyasını oluşturalım. Bu konfigürasyon production için makul bir başlangıç noktasıdır:

sudo nano /etc/loki/loki-config.yaml
auth_enabled: false

server:
  http_listen_port: 3100
  grpc_listen_port: 9096
  log_level: warn

common:
  instance_addr: 127.0.0.1
  path_prefix: /var/lib/loki
  storage:
    filesystem:
      chunks_directory: /var/lib/loki/chunks
      rules_directory: /var/lib/loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory

query_range:
  results_cache:
    cache:
      embedded_cache:
        enabled: true
        max_size_mb: 100

schema_config:
  configs:
    - from: 2024-01-01
      store: tsdb
      object_store: filesystem
      schema: v12
      index:
        prefix: index_
        period: 24h

ruler:
  alertmanager_url: http://localhost:9093

limits_config:
  reject_old_samples: true
  reject_old_samples_max_age: 168h
  ingestion_rate_mb: 16
  ingestion_burst_size_mb: 32

compactor:
  working_directory: /var/lib/loki/compactor
  shared_store: filesystem
  retention_enabled: true
  retention_delete_delay: 2h

chunk_store_config:
  max_look_back_period: 0s

table_manager:
  retention_deletes_enabled: true
  retention_period: 720h

Systemd servis dosyasını oluşturalım:

sudo nano /etc/systemd/system/loki.service
[Unit]
Description=Loki Log Aggregation System
After=network.target

[Service]
Type=simple
User=loki
Group=loki
ExecStart=/usr/local/bin/loki -config.file=/etc/loki/loki-config.yaml
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal
SyslogIdentifier=loki

# Güvenlik önlemleri
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=full
ProtectHome=yes

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable loki
sudo systemctl start loki
sudo systemctl status loki

# Loki'nin ayakta olduğunu doğrula
curl http://localhost:3100/ready

Promtail Kurulumu ve Konfigürasyonu

Promtail, log dosyalarını izleyip Loki’ye gönderen agent’tır. Her sunucuya kurulması gerekir:

# Promtail'i indir
cd /tmp
wget https://github.com/grafana/loki/releases/download/v2.9.4/promtail-linux-amd64.zip
unzip promtail-linux-amd64.zip
sudo mv promtail-linux-amd64 /usr/local/bin/promtail
sudo chmod +x /usr/local/bin/promtail

# Kullanıcı ve dizin
sudo useradd --system --no-create-home --shell /bin/false promtail
sudo mkdir -p /etc/promtail /var/lib/promtail
sudo usermod -a -G adm promtail  # Sistem loglarını okuyabilmesi için
sudo chown -R promtail:promtail /var/lib/promtail

Promtail konfigürasyonu birçok sysadmin’in zaman harcadığı yer. Aşağıdaki konfigürasyon nginx, sistem logları ve uygulama loglarını kapsar:

sudo nano /etc/promtail/promtail-config.yaml
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /var/lib/promtail/positions.yaml

clients:
  - url: http://localhost:3100/loki/api/v1/push
    tenant_id: default
    backoff_config:
      min_period: 500ms
      max_period: 5m
      max_retries: 10
    timeout: 10s

scrape_configs:
  # Sistem logları
  - job_name: system
    static_configs:
      - targets:
          - localhost
        labels:
          job: varlogs
          host: prod-web-01
          env: production
          __path__: /var/log/{syslog,auth.log,kern.log}

  # Nginx access logları
  - job_name: nginx_access
    static_configs:
      - targets:
          - localhost
        labels:
          job: nginx
          host: prod-web-01
          env: production
          log_type: access
          __path__: /var/log/nginx/access.log
    pipeline_stages:
      - regex:
          expression: '^(?P<remote_addr>S+) S+ S+ [(?P<time_local>[^]]+)] "(?P<method>S+) (?P<path>S+) S+" (?P<status>d+) (?P<bytes_sent>d+)'
      - labels:
          method:
          status:
      - metrics:
          http_requests_total:
            type: Counter
            description: "Toplam HTTP istek sayısı"
            source: status
            config:
              action: inc

  # Nginx error logları
  - job_name: nginx_error
    static_configs:
      - targets:
          - localhost
        labels:
          job: nginx
          host: prod-web-01
          env: production
          log_type: error
          __path__: /var/log/nginx/error.log
    pipeline_stages:
      - regex:
          expression: '(?P<level>emerg|alert|crit|error|warn|notice|info|debug)'
      - labels:
          level:

  # Uygulama logları (örnek: Python/Node.js uygulaması)
  - job_name: app_logs
    static_configs:
      - targets:
          - localhost
        labels:
          job: myapp
          host: prod-web-01
          env: production
          __path__: /var/log/myapp/*.log
    pipeline_stages:
      - multiline:
          firstline: '^d{4}-d{2}-d{2}'
          max_wait_time: 3s
      - regex:
          expression: '^(?P<timestamp>d{4}-d{2}-d{2} d{2}:d{2}:d{2}) (?P<level>DEBUG|INFO|WARNING|ERROR|CRITICAL)'
      - labels:
          level:
      - timestamp:
          source: timestamp
          format: '2006-01-02 15:04:05'

Multiline konfigürasyonu özellikle Java stack trace’leri veya Python traceback’leri için kritik. Bunlar olmadan her satır ayrı log eventi olarak görünür ve analiz imkansızlaşır.

# Promtail servisini oluştur ve başlat
sudo nano /etc/systemd/system/promtail.service
[Unit]
Description=Promtail Log Shipper
After=network.target loki.service

[Service]
Type=simple
User=promtail
Group=promtail
ExecStart=/usr/local/bin/promtail -config.file=/etc/promtail/promtail-config.yaml
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable promtail
sudo systemctl start promtail

# Promtail'in logları gönderip göndermediğini kontrol et
curl http://localhost:9080/metrics | grep promtail_sent_entries_total

Grafana Kurulumu ve Loki Entegrasyonu

# Grafana APT repository ekle
sudo apt-get install -y apt-transport-https software-properties-common
wget -q -O /usr/share/keyrings/grafana.key https://apt.grafana.com/gpg.key
echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com stable main" | 
  sudo tee /etc/apt/sources.list.d/grafana.list

sudo apt-get update
sudo apt-get install -y grafana

sudo systemctl daemon-reload
sudo systemctl enable grafana-server
sudo systemctl start grafana-server

Grafana web arayüzüne http://sunucu-ip:3000 adresinden erişin. Default kullanıcı admin, şifre admin. İlk girişte şifre değiştirmenizi isteyecek, bunu atlamayın.

Loki data source ekleme adımları:

  • Sol menüden “Connections” > “Data sources” > “Add data source”
  • “Loki” seçin
  • URL kısmına http://localhost:3100 yazın
  • “Save & test” butonuna basın
  • “Data source connected and labels found” mesajını görmelisiniz

LogQL ile Gerçek Dünya Sorguları

LogQL, Loki’nin sorgu dilidir. PromQL’e benzer bir sözdizimi vardır. Grafana’da “Explore” bölümünden bu sorguları deneyebilirsiniz.

Temel log akışı görüntüleme:

# Tüm nginx logları
{job="nginx"}

# Sadece production ortamındaki hata logları
{env="production", log_type="error"}

# Belirli host'un auth logları
{job="varlogs", host="prod-web-01"} |= "Failed password"

SSH brute force tespiti:

# Son 15 dakikada başarısız SSH girişimlerinin sayısı
count_over_time(
  {job="varlogs"} 
  |= "Failed password" 
  | regexp `from (?P<ip>d+.d+.d+.d+)` 
  [15m]
)

# IP bazında gruplama ile
sum by (ip) (
  count_over_time(
    {job="varlogs"} 
    |= "Failed password" 
    | regexp `from (?P<ip>d+.d+.d+.d+)` 
    [5m]
  )
)

Nginx 5xx error oranı:

# HTTP 500 hatalarının son 5 dakikadaki sayısı
sum(count_over_time({job="nginx", log_type="access"} |= "" 5" [5m]))

# 5xx oranı (yüzde olarak)
sum(count_over_time({job="nginx", log_type="access"} | status =~ "5.." [5m])) /
sum(count_over_time({job="nginx", log_type="access"} [5m])) * 100

Uygulama hata takibi:

# ERROR ve CRITICAL logları filtrele ve say
sum by (level) (
  count_over_time(
    {job="myapp"} 
    | label_format level=level 
    | level =~ "ERROR|CRITICAL" 
    [5m]
  )
)

# Belirli bir hata mesajını içeren loglar
{job="myapp"} 
|= "Database connection" 
| json 
| line_format "{{.timestamp}} [{{.level}}] {{.message}}"

Alerting: Kritik Durumlar İçin Uyarı Kuralları

Grafana’nın Alerting özelliğini kullanarak Loki sorgularına dayalı uyarılar oluşturabilirsiniz. Alerting > Alert rules > Create alert rule yolunu izleyin.

Disk dolmadan önce uyarı almak için alert rule konfigürasyon örneği:

# /etc/loki/rules/alerts.yaml
groups:
  - name: log_alerts
    rules:
      - alert: HighErrorRate
        expr: |
          sum(rate({job="myapp"} |= "ERROR" [5m])) > 10
        for: 2m
        labels:
          severity: warning
          team: backend
        annotations:
          summary: "Uygulama hata oranı yüksek"
          description: "Son 5 dakikada dakika başına 10'dan fazla ERROR logu var"

      - alert: SSHBruteForce
        expr: |
          sum(count_over_time({job="varlogs"} |= "Failed password" [5m])) > 50
        for: 1m
        labels:
          severity: critical
          team: security
        annotations:
          summary: "Olası SSH brute force saldırısı"
          description: "Son 5 dakikada 50'den fazla başarısız SSH girişimi tespit edildi"

      - alert: NginxHighLatency
        expr: |
          count_over_time({job="nginx", log_type="error"} [5m]) > 100
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Nginx hata sayısı yüksek"

Loki konfigürasyonuna ruler bölümünü ekleyin:

# /etc/loki/loki-config.yaml dosyasına ekle
ruler:
  storage:
    type: local
    local:
      directory: /var/lib/loki/rules
  rule_path: /var/lib/loki/rules_tmp
  alertmanager_url: http://localhost:9093
  ring:
    kvstore:
      store: inmemory
  enable_api: true
  enable_alertmanager_v2: true

Çok Sunuculu Ortamda Promtail Yapılandırması

10 sunucunuz varsa her birine Promtail kurmanız ve her birinin Loki’ye göndermesi gerekir. Ansible ile bunu otomatikleştirmek mantıklıdır:

# Ansible ile Promtail kurulumu için basit script
# promtail_setup.sh - her sunucuda çalıştır

#!/bin/bash
LOKI_SERVER="10.0.1.100"  # Merkezi Loki sunucunuzun IP'si
HOST_NAME=$(hostname)
ENVIRONMENT=${1:-"production"}  # Script argümanı olarak alın

cat > /etc/promtail/promtail-config.yaml << EOF
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /var/lib/promtail/positions.yaml

clients:
  - url: http://${LOKI_SERVER}:3100/loki/api/v1/push

scrape_configs:
  - job_name: system
    static_configs:
      - targets:
          - localhost
        labels:
          job: varlogs
          host: ${HOST_NAME}
          env: ${ENVIRONMENT}
          __path__: /var/log/{syslog,auth.log}

  - job_name: nginx
    static_configs:
      - targets:
          - localhost
        labels:
          job: nginx
          host: ${HOST_NAME}
          env: ${ENVIRONMENT}
          __path__: /var/log/nginx/*.log
EOF

systemctl restart promtail
echo "Promtail yapılandırması tamamlandı: ${HOST_NAME} -> ${LOKI_SERVER}"

Performans Optimizasyonu ve Production Dikkat Noktaları

Label kardinalitesi: Loki’nin en sık düşülen tuzağı budur. Her benzersiz label kombinasyonu ayrı bir log akışı oluşturur. Kullanıcı ID’sini veya IP adresini label olarak eklerseniz, binlerce farklı akış oluşur ve performans çöker. Label olarak kullanılacak değerler az sayıda ve sabit olmalıdır.

Yanlış kullanım:

# BU YAPMAYIN - yüksek kardinalite
labels:
  user_id: "12345"
  client_ip: "192.168.1.100"
  request_id: "abc-def-123"

Doğru kullanım:

# DOĞRU - düşük kardinalite
labels:
  env: "production"
  app: "api-server"
  host: "web-01"
  level: "error"

Disk yönetimi için retention politikası:

# Loki konfigürasyonunda retention ayarları
limits_config:
  retention_period: 720h  # 30 gün

compactor:
  retention_enabled: true
  retention_delete_delay: 2h
  retention_delete_worker_count: 150

Bellek kullanımını izleme:

# Loki memory kullanımını kontrol et
curl -s http://localhost:3100/metrics | grep -E "^go_memstats_(heap_alloc|sys)_bytes"

# Aktif stream sayısını kontrol et
curl -s http://localhost:3100/metrics | grep loki_ingester_streams_created_total

Firewall kuralları – Loki dışarıya açılmamalı:

# Loki sadece local ve trusted network'ten erişilebilir olsun
sudo ufw allow from 10.0.0.0/8 to any port 3100
sudo ufw deny 3100
sudo ufw allow from 10.0.0.0/8 to any port 3101

# Grafana dışarıya açık olabilir ama Loki kesinlikle hayır
sudo ufw allow 3000/tcp

Grafana Dashboard Oluşturma

Grafana’da “Dashboards > New > New Dashboard” ile yeni dashboard oluşturun. Nginx monitoring için tipik panel sorguları:

# Panel 1: Toplam istek hacmi (son 1 saat)
sum(count_over_time({job="nginx", log_type="access"} [1h]))

# Panel 2: Hata dağılımı (pie chart için)
sum by (status) (
  count_over_time(
    {job="nginx", log_type="access"} 
    | regexp `" (?P<status>d+) ` 
    [5m]
  )
)

# Panel 3: En çok hata alan path'ler
topk(10,
  sum by (path) (
    count_over_time(
      {job="nginx", log_type="access"} 
      | regexp `"(?:GET|POST|PUT|DELETE) (?P<path>S+).*" 5dd` 
      [1h]
    )
  )
)

Grafana’nın built-in “Logs” panel tipini kullanın, tablo yerine. Bu panel otomatik olarak log seviyelerini renklendirir ve filtreleme imkanı sunar.

Sorun Giderme

Promtail loglar göndermiyorsa kontrol listesi:

# Promtail'in log dosyalarını okuyabildiğini kontrol et
sudo -u promtail cat /var/log/nginx/access.log | head -5

# Positions dosyasını kontrol et
cat /var/lib/promtail/positions.yaml

# Promtail debug modunda çalıştır
sudo promtail -config.file=/etc/promtail/promtail-config.yaml -log.level=debug 2>&1 | head -50

# Loki'ye erişim kontrolü
curl -v http://loki-server:3100/ready

# Loki'deki mevcut label'ları listele
curl http://localhost:3100/loki/api/v1/labels

# Belirli bir label için values
curl "http://localhost:3100/loki/api/v1/label/job/values"

Sonuç

Loki, özellikle kaynak kısıtlı ortamlarda veya halihazırda Grafana kullanan ekiplerde son derece pratik bir çözüm. ELK stack’in tam metin indeksleme gücünü gerektirmiyorsanız ve log analizi ihtiyaçlarınız label bazlı filtreleme ile karşılanabiliyorsa, Loki hafif yapısıyla ciddi avantaj sağlar.

Kurulum sürecinde en çok dikkat edilmesi gereken nokta label tasarımı. Kardinaliteyi düşük tutmak performans açısından kritik. Buna ek olarak, production’da retention politikasını ve disk kullanımını düzenli izlemek gerekiyor. logcli komut satırı aracını da keşfetmenizi öneririm, SSH üzerinden hızlı log sorgulaması için çok pratik.

Bir sonraki adım olarak Loki’yi Prometheus ile birlikte kullanmak, yani metrikler ve logları aynı Grafana dashboard’unda ilişkilendirmek, incident response sürecini dramatik biçimde hızlandırıyor. Bir alert tetiklendiğinde hem metriği hem de ilgili log satırlarını aynı ekranda görmek, sorunun kaynağına çok daha hızlı ulaşmanızı sağlıyor.

Benzer Konular

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir