journald ile Yapılandırılmış Log Yönetimi

Modern Linux sistemlerinde log yönetimi, systemd’nin hayatımıza girmesiyle köklü bir dönüşüm geçirdi. Eski güzel syslog günleri geride kalırken, journald bize yapılandırılmış, sorgulanabilir ve merkezi bir log altyapısı sunuyor. Ancak birçok sysadmin hâlâ journald’yi sadece journalctl -f komutuyla sınırlı kullanıyor. Bu yazıda journald’nin gerçek gücünü ortaya çıkaracağız; production ortamlarında log yönetimini nasıl profesyonelce yapabileceğinizi, disk kullanımını nasıl kontrol altında tutacağınızı ve yapılandırılmış logları nasıl analiz edeceğinizi ele alacağız.

journald Nedir ve Neden Önemli?

journald, systemd ekosisteminin bir parçası olan systemd-journald servisinin kısaltmasıdır. Geleneksel syslog’dan temel farkı, logları düz metin yerine ikili formatta saklamasıdır. Bu sayede her log kaydı metadata ile birlikte gelir: hangi kullanıcı, hangi proses, hangi servis, kaçıncı PID, kernel mi userspace mi olduğu gibi bilgiler otomatik olarak eklenir.

Bunun pratikte ne anlama geldiğini düşünelim. Bir nginx servisinde hata araştırıyorsunuz ve binlerce log satırı içinden sadece belirli bir zaman aralığındaki kritik hataları filtrelemeniz gerekiyor. Syslog ile bunu grep zincirleriyle yapmak zorundayken, journald ile tek bir komutla bu işi halledebilirsiniz.

Temel Mimari

journald üç ana kaynaktan log toplar:

  • Kernel logları: /dev/kmsg üzerinden doğrudan kernel mesajları
  • Servis logları: systemd unit’lerinin stdout/stderr çıktıları
  • Native journal API: Uygulama loglarını structured format’ta gönderen servisler
  • Syslog socket: Geriye dönük uyumluluk için klasik syslog mesajları

Loglar varsayılan olarak /run/log/journal/ içinde tutulur ve sistem yeniden başladığında silinir. Kalıcı loglama için /var/log/journal/ dizinini oluşturmanız gerekir.

# Kalıcı log depolamayı aktifleştir
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

# Logların nerede tutulduğunu kontrol et
journalctl --disk-usage

journald Yapılandırması: /etc/systemd/journald.conf

journald’nin davranışını /etc/systemd/journald.conf dosyasından yönetirsiniz. Ancak production ortamlarında daha temiz bir yaklaşım, override dosyaları kullanmaktır. Bu sayede paket güncellemelerinde yapılandırmanız kaybolmaz.

# Drop-in yapılandırma dizini oluştur
sudo mkdir -p /etc/systemd/journald.conf.d/

# Production için önerilen yapılandırma
sudo cat > /etc/systemd/journald.conf.d/production.conf << 'EOF'
[Journal]
Storage=persistent
Compress=yes
MaxDiskUsage=2G
MaxFileSizeMB=128
MaxRetentionSec=3month
SystemMaxFiles=20
ForwardToSyslog=no
RateLimitIntervalSec=30s
RateLimitBurst=10000
EOF

sudo systemctl restart systemd-journald

Önemli parametreleri açıklayalım:

  • Storage=persistent: Logları disk üzerinde kalıcı olarak saklar
  • Compress=yes: LZ4 sıkıştırmasıyla disk kullanımını azaltır
  • MaxDiskUsage=2G: Journal’ın toplam disk kullanımı üst sınırı
  • MaxFileSizeMB=128: Tek bir journal dosyasının maksimum boyutu
  • MaxRetentionSec=3month: 3 aydan eski logları otomatik sil
  • SystemMaxFiles=20: Sistem logları için maksimum dosya sayısı
  • ForwardToSyslog=no: rsyslog’a iletmeyi kapat, ikili kayıt önle
  • RateLimitBurst=10000: Rate limiting eşiği, yoğun uygulamalar için artırılabilir

journalctl ile Etkili Log Sorgulama

journalctl’nin güzelliği, zengin filtreleme seçeneklerinde yatıyor. Gerçek dünya senaryolarına bakalım.

Zaman Bazlı Sorgular

# Son 1 saatin logları
journalctl --since "1 hour ago"

# Belirli zaman aralığı
journalctl --since "2024-01-15 08:00:00" --until "2024-01-15 09:30:00"

# Dün gece yarısından bu yana
journalctl --since yesterday

# Boot'a göre filtreleme
journalctl -b        # Şu anki boot
journalctl -b -1     # Bir önceki boot
journalctl -b -2     # İki boot önce

# Tüm boot geçmişini listele
journalctl --list-boots

Servis ve Unit Bazlı Filtreleme

# Belirli bir servisin logları
journalctl -u nginx.service
journalctl -u nginx.service --since "2 hours ago"

# Birden fazla servis
journalctl -u nginx.service -u php-fpm.service

# Failed unit'lerin loglarını gör
for unit in $(systemctl --failed --no-legend | awk '{print $1}'); do
    echo "=== $unit ==="
    journalctl -u "$unit" --since "1 hour ago" -n 20
done

Priority Bazlı Filtreleme

journald, syslog priority seviyelerini kullanır:

  • 0 (emerg): Sistem kullanılamaz
  • 1 (alert): Hemen aksiyon alınmalı
  • 2 (crit): Kritik durum
  • 3 (err): Hata durumları
  • 4 (warning): Uyarılar
  • 5 (notice): Normal ama önemli
  • 6 (info): Bilgi mesajları
  • 7 (debug): Debug mesajları
# Sadece hata ve üzeri
journalctl -p err

# Warning ve üzeri, son 100 satır
journalctl -p warning -n 100

# Critical hatalar, son boot
journalctl -p crit -b

# Belirli servis için sadece hatalar
journalctl -u postgresql.service -p err --since "1 day ago"

Yapılandırılmış Loglama: Fields ve Metadata

journald’nin en güçlü özelliği, her log kaydına otomatik eklenen metadata alanlarıdır. Bu alanları kullanarak son derece hassas sorgular yapabilirsiniz.

# Log kaydının tüm metadata alanlarını gör
journalctl -u sshd.service -n 1 -o verbose

# JSON formatında çıktı (log analiz araçlarıyla entegrasyon için)
journalctl -u nginx.service --since "1 hour ago" -o json | head -5

# Tek satır JSON (pipeline için ideal)
journalctl -u nginx.service -o json-pretty -n 10

# Belirli bir _SYSTEMD_UNIT field'ına göre filtrele
journalctl _SYSTEMD_UNIT=docker.service

# _PID'e göre filtrele
journalctl _PID=1234

# Belirli kullanıcının başlattığı proseslerin logları
journalctl _UID=1000

# Kernel namespace'den gelen mesajlar
journalctl _TRANSPORT=kernel

Önemli journal alanları:

  • _HOSTNAME: Mesajın geldiği host adı
  • _SYSTEMD_UNIT: İlgili systemd unit adı
  • _PID: Proses ID
  • _UID / _GID: Kullanıcı ve grup ID
  • _COMM: Proses adı
  • _EXE: Çalıştırılabilir dosyanın tam yolu
  • _TRANSPORT: Mesajın geldiği transport (journal, syslog, kernel, audit)
  • PRIORITY: Log öncelik seviyesi
  • MESSAGE: Asıl log mesajı

Gerçek Dünya Senaryosu: Web Sunucusu Sorun Tespiti

Diyelim ki production nginx sunucunuzda aralıklı 502 hataları alıyorsunuz. Klasik yaklaşım nginx access log’larını grep’lemek olurdu. Ancak journald ile daha kapsamlı bir sorun analizi yapabilirsiniz.

#!/bin/bash
# nginx-diagnosis.sh - Nginx sorun tespit scripti

SINCE_TIME="2 hours ago"
OUTPUT_DIR="/tmp/nginx-diagnosis-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$OUTPUT_DIR"

echo "[*] Nginx error logları toplanıyor..."
journalctl -u nginx.service -p err --since "$SINCE_TIME" 
    -o json > "$OUTPUT_DIR/nginx-errors.json"

echo "[*] PHP-FPM hataları toplanıyor..."
journalctl -u php8.2-fpm.service -p warning --since "$SINCE_TIME" 
    -o json > "$OUTPUT_DIR/phpfpm-warnings.json"

echo "[*] Sistem kaynak sorunları kontrol ediliyor..."
journalctl -p err --since "$SINCE_TIME" 
    -k > "$OUTPUT_DIR/kernel-errors.txt"

echo "[*] OOM killer aktivitesi..."
journalctl -k --grep="Out of memory" --since "$SINCE_TIME" 
    > "$OUTPUT_DIR/oom-events.txt"

echo "[*] Toplam hata sayıları:"
echo "Nginx errors: $(wc -l < "$OUTPUT_DIR/nginx-errors.json")"
echo "PHPFPM warnings: $(wc -l < "$OUTPUT_DIR/phpfpm-warnings.json")"
echo "Kernel errors: $(wc -l < "$OUTPUT_DIR/kernel-errors.txt")"
echo "OOM events: $(wc -l < "$OUTPUT_DIR/oom-events.txt")"

echo "[+] Tanı dosyaları: $OUTPUT_DIR"

Log Rotasyonu ve Disk Yönetimi

Production ortamında disk dolmasına izin vermemek kritik öneme sahiptir. journald bu konuda güçlü araçlar sunar.

# Mevcut disk kullanımını kontrol et
journalctl --disk-usage

# Belirli bir boyutun üzerindeki eski logları temizle
sudo journalctl --vacuum-size=1G

# Belirli bir tarihten eski logları sil
sudo journalctl --vacuum-time=2weeks

# Dosya sayısını sınırla
sudo journalctl --vacuum-files=10

# Doğrulama: Journal tutarlılık kontrolü
sudo journalctl --verify

Otomatik temizlik için cron job veya sistemd timer kullanabilirsiniz. Timer yaklaşımı daha sağlıklıdır:

# /etc/systemd/system/journal-cleanup.service
sudo cat > /etc/systemd/system/journal-cleanup.service << 'EOF'
[Unit]
Description=Journal Log Cleanup
After=systemd-journald.service

[Service]
Type=oneshot
ExecStart=/usr/bin/journalctl --vacuum-size=1500M
ExecStart=/usr/bin/journalctl --vacuum-time=45days
EOF

# /etc/systemd/system/journal-cleanup.timer
sudo cat > /etc/systemd/system/journal-cleanup.timer << 'EOF'
[Unit]
Description=Weekly Journal Cleanup
Requires=journal-cleanup.service

[Timer]
OnCalendar=weekly
Persistent=true

[Install]
WantedBy=timers.target
EOF

sudo systemctl enable --now journal-cleanup.timer
sudo systemctl status journal-cleanup.timer

Uzak Log Toplama: journald Remote

Birden fazla sunucu yönetiyorsanız, journald’nin remote log toplama özelliğini kullanabilirsiniz. systemd-journal-remote paketi bu iş için tasarlanmıştır.

# Log collector sunucusunda kurulum
sudo apt install systemd-journal-remote

# Collector yapılandırması
sudo cat > /etc/systemd/journal-remote.conf << 'EOF'
[Remote]
Seal=false
SplitMode=host
ServerKeyFile=/etc/ssl/private/journal-remote.key
ServerCertificateFile=/etc/ssl/certs/journal-remote.pem
TrustedCertificateFile=/etc/ssl/certs/ca.pem
EOF

# Servisi aktifleştir (HTTPS üzerinden log kabul eder)
sudo systemctl enable --now systemd-journal-remote.socket
sudo systemctl enable --now systemd-journal-remote.service

# Gönderici (kaynak) sunucularda
sudo apt install systemd-journal-remote

sudo cat > /etc/systemd/journal-upload.conf << 'EOF'
[Upload]
URL=https://log-collector.internal:19532
ServerKeyFile=/etc/ssl/private/journal-upload.key
ServerCertificateFile=/etc/ssl/certs/journal-upload.pem
TrustedCertificateFile=/etc/ssl/certs/ca.pem
EOF

sudo systemctl enable --now systemd-journal-upload.service

Collector sunucusunda tüm kaynak sunucuların loglarını birleşik olarak sorgulayabilirsiniz:

# Belirli bir host'un loglarını sorgula
journalctl -D /var/log/journal/remote/ _HOSTNAME=web-server-01

# Tüm remote loglardan hata ara
journalctl -D /var/log/journal/remote/ -p err --since "1 hour ago"

Uygulamalardan Yapılandırılmış Log Gönderme

journald’nin gerçek gücü, uygulamaların native journal API’sini kullanmasıyla ortaya çıkar. Python ve Node.js’ten örnek görelim.

# Python ile structured logging
from systemd import journal
import logging

# systemd journal handler
logger = logging.getLogger('myapp')
logger.addHandler(journal.JournalHandler(SYSLOG_IDENTIFIER='myapp'))
logger.setLevel(logging.DEBUG)

# Basit mesaj
logger.info("Uygulama başlatıldı")

# Structured fields ile
journal.send(
    "Kullanıcı giriş yaptı",
    PRIORITY=journal.LOG_INFO,
    SYSLOG_IDENTIFIER="myapp",
    USER_ID="12345",
    USER_EMAIL="[email protected]",
    REQUEST_ID="req-abc-123",
    REMOTE_ADDR="192.168.1.100"
)

Bu şekilde gönderilen logları journalctl ile kolayca sorgulayabilirsiniz:

# Özel field'lara göre filtrele
journalctl SYSLOG_IDENTIFIER=myapp USER_ID=12345

# Belirli bir request ID'yi takip et
journalctl SYSLOG_IDENTIFIER=myapp REQUEST_ID=req-abc-123

# JSON olarak dışa aktar ve jq ile işle
journalctl SYSLOG_IDENTIFIER=myapp -o json | 
    jq -r 'select(.PRIORITY <= "3") | [.REALTIME_TIMESTAMP, .MESSAGE] | @tsv'

Log Analizi İçin İleri Teknikler

journalctl çıktısını diğer araçlarla birleştirerek güçlü analiz pipeline’ları kurabilirsiniz.

#!/bin/bash
# log-analysis.sh - Günlük log analiz raporu

REPORT_DATE=$(date +%Y-%m-%d)
REPORT_FILE="/var/reports/log-report-${REPORT_DATE}.txt"

{
    echo "=== Günlük Log Analiz Raporu: $REPORT_DATE ==="
    echo ""

    echo "--- Kritik Hata Özeti ---"
    journalctl -p err --since "1 day ago" 
        -o json-pretty | 
        python3 -c "
import json, sys, collections
errors = []
for line in sys.stdin:
    try:
        entry = json.loads(line)
        errors.append(entry.get('SYSLOG_IDENTIFIER', 'unknown'))
    except:
        pass
counter = collections.Counter(errors)
for name, count in counter.most_common(10):
    print(f'  {count:5d}  {name}')
"

    echo ""
    echo "--- SSH Başarısız Giriş Denemeleri ---"
    journalctl -u sshd.service --since "1 day ago" 
        --grep="Failed password" | 
        awk '{print $11}' | sort | uniq -c | sort -rn | head -10

    echo ""
    echo "--- Disk I/O Hataları ---"
    journalctl -k --since "1 day ago" --grep="I/O error" | wc -l

    echo ""
    echo "--- Systemd Failed Units ---"
    systemctl --failed --no-legend | awk '{print "  "$1}'

    echo ""
    echo "--- Journal Disk Kullanımı ---"
    journalctl --disk-usage

} > "$REPORT_FILE"

echo "Rapor hazırlandı: $REPORT_FILE"

# Raporu mail ile gönder (isteğe bağlı)
# mail -s "Günlük Log Raporu: $REPORT_DATE" [email protected] < "$REPORT_FILE"

journald ve Grafana/Prometheus Entegrasyonu

Modern monitoring stack’ine journald’yi entegre etmek için promtail veya vector gibi araçlar kullanabilirsiniz. Loki ile entegrasyon için temel promtail yapılandırması:

# /etc/promtail/config.yml
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: journal
    journal:
      max_age: 12h
      labels:
        job: systemd-journal
        host: __HOSTNAME__
    relabel_configs:
      - source_labels: ['__journal__systemd_unit']
        target_label: 'unit'
      - source_labels: ['__journal__hostname']
        target_label: 'hostname'
      - source_labels: ['__journal_priority_keyword']
        target_label: 'level'

Bu yapılandırmayla tüm systemd servis loglarınız otomatik olarak Loki’ye akar ve Grafana üzerinden görselleştirebilirsiniz.

Güvenlik: Journal Sealing

Production ortamlarında log manipülasyonunu önlemek için journal sealing özelliğini aktifleştirebilirsiniz. Bu özellik, FSS (Forward Secure Sealing) kullanarak log kayıtlarını kriptografik olarak imzalar.

# Journal sealing için anahtar oluştur
sudo journalctl --setup-keys

# Çıktı örneği:
# /var/log/journal/[machine-id]/fss
# Sealing key: XXXX-XXXX-XXXX-XXXX/XXXX-XXXX-XXXX

# Anahtarı güvenli bir yere kaydedin!
# Doğrulama (sealing key gerektirir)
sudo journalctl --verify --verify-key=XXXX-XXXX-XXXX-XXXX/XXXX-XXXX-XXXX

Sealing aktifken /etc/systemd/journald.conf.d/production.conf dosyanıza şunu ekleyin:

  • Seal=yes: FSS sealing’i aktifleştirir

Sonuç

journald, doğru yapılandırıldığında modern bir Linux sisteminin en değerli araçlarından biri haline gelir. Yapılandırılmış log formatı sayesinde hata tespiti dakikalar yerine saniyeler içinde tamamlanabiliyor. Disk yönetimi otomatize ediliyor ve merkezi log toplama altyapısı kurulabiliyor.

Öncelik olarak yapmanız gerekenler şunlardır: önce kalıcı loglama aktifleştirin, ardından disk kotalarını tanımlayın. Uygulamalarınızı native journal API kullanacak şekilde güncelleyin. Log analiz scriptlerinizi journalctl’nin JSON çıktısı üzerine kurun. Yüksek güvenlik gerektiren ortamlarda journal sealing’i devreye alın.

Eski syslog alışkanlıklarından vazgeçmek zor gelebilir ama journald’ye bir şans tanıdığınızda, grep zincirlerinden kurtulmanın ne kadar özgürleştirici olduğunu göreceksiniz. Yapılandırılmış loglar, hem günlük operasyonları hem de post-mortem analizleri ciddi ölçüde kolaylaştırıyor.

Similar Posts

Bir yanıt yazın

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