SSD Nodes Learn 🎉 VPS $5.50/aydan başlayan
Rehberler Matt ConnorYazan Matt Connor

Tek Bir VPS Üzerinde Günlük Yönetimi Nasıl Yapılır?

Tek bir VPS üzerinde günlük yönetimi için journald, Loki ve OpenSearch seçeneklerini inceleyin. RAM sınırları ve veri tutma kurallarına göre en verimli yöntemi seçin.

Tek bir VPS üzerinde kendi kendine barındırılan günlük yönetimi maliyeti

Tek bir VPS (sanal özel sunucu) üzerinde kendi kendine barındırılan günlük yönetimi, tek bir soruya indirgenir: Bir arama kümesine mi ihtiyacınız var, yoksa günlük döndürme ve grep komutuna mı? Çoğu tedarikçi kılavuzu, bu soruya tek bir günlük satırı bile gönderilmeden önce üç düğüm ve 12 GB RAM ile başlayarak yanıt verir. Tek bir sunucuda bu yanıt işlevsizdir; bu nedenle aşağıdaki karşılaştırma, her seçeneğin herhangi bir veri tutmadan önce küçük bir sunucudan ne talep ettiğine göre yapılmıştır.

Bir veya iki sunucu çalıştırıyorsanız ve geçen Salı günü ne olduğunu bilmek istiyorsanız, systemd-journald ve logrotate bu işi zaten yapmaktadır; bir sonraki bölümden sonra okumayı bırakabilirsiniz. Eğer birden fazla makinenin günlüklerini tek bir yerde toplaması ve haftalarca geriye dönük arama yapılması gerekiyorsa, Grafana Loki küçük bir sunucuya uygundur çünkü satırların metnini değil, etiketleri dizinler. Elasticsearch ve OpenSearch size gerçek tam metin araması sunar; ancak bunun bedelini bellek kullanımıyla ödetirler, çünkü JVM (Java virtual machine) yığınının altına inilemeyecek bir alt sınırı vardır.

journald ile başlayın, çünkü çoğu kişi burada durur

systemd-journald, güncel tüm Ubuntu veya Debian sunucularında halihazırda çalışmaktadır. Her servis biriminin standart çıktısını, çekirdek mesajlarını ve syslog'a gönderilen her şeyi yakalar. Dört komut, çoğu olayı kapsar.

journalctl -u nginx.service --since "2026-08-14 09:00" --until "2026-08-14 10:00"
journalctl -p err -b
journalctl -f -u ssh.service
journalctl --disk-usage

Sonuncusu, Archived and active journals take up 1.1G in the file system. gibi bir satır yazdırır. Başka bir şeye ihtiyacınız olup olmadığına karar veren sayı budur. Eğer birkaç yüz megabaytlık bir veri okuyorsa ve ihtiyacınız olanı -u ve --since ile bulabiliyorsanız, işiniz bitmiş demektir.

Günlüğün yeniden başlatma sonrasında varlığını sürdürüp sürdürmeyeceği, Storage= değerine ve /var/log/journal dizininin mevcut olup olmadığına bağlıdır. Yaygın olan Storage=auto ayarıyla journald, bu dizin mevcut olduğunda /var/log/journal konumuna, mevcut olmadığında ise /run/log/journal konumuna yazar. /run bellek desteklidir, bu nedenle bu dizinin bulunmadığı bir sunucuda her günlük yeniden başlatma sırasında silinir; bu da tam olarak onları okumak istediğiniz andır. Ubuntu imajları bu dizinle birlikte gelir. Minimal ve container tabanlı imajlar ise genellikle bu dizini içermez.

ls -d /var/log/journal
sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald
journalctl --disk-usage

Yeniden başlatmanın ardından journalctl --disk-usage, /run yerine /var/log/journal altında bir boyut bildirmelidir. Varsayılan değerler zaten sınırlandırılmıştır; journald'nin bir yedekleme aracı değil, ciddi bir çözüm olmasının temel nedeni budur. journald.conf kılavuz sayfası, SystemMaxUse= değerini dosya sistemi boyutunun %10'una, SystemKeepFree= değerini ise %15'ine ayarlar ve hesaplanan her varsayılan değeri 4G ile sınırlar. SystemMaxFileSize=, varsayılan olarak SystemMaxUse= değerinin sekizde biridir ve 128M ile sınırlandırılmıştır; bu nedenle normalde yedi adet döndürülmüş (rotated) dosya tutarsınız. MaxRetentionSec= varsayılan olarak 0'dır, bu da yaşa dayalı silme işlemini devre dışı bırakır. Bu son varsayılanı tekrar okuyun: varsayılan olarak günlük yalnızca boyuta göre sınırlandırılır, asla yaşa göre değil.

[Journal]
Storage=persistent
SystemMaxUse=2G
MaxRetentionSec=30day

Bunu /etc/systemd/journald.conf.d/99-size.conf dosyasına yazın, journald'yi yeniden başlatın ve ardından journalctl --disk-usage değerinin yeni üst sınırınıza doğru ilerlediğini kontrol edin. Bir sonraki döndürme işlemini beklemeden alanı hemen geri kazanmak için sudo journalctl --vacuum-size=500M veya sudo journalctl --vacuum-time=14d komutunu çalıştırın. Her ikisi de sildiği her dosyayı yazdırır, bu nedenle sessiz bir çalışma, silinecek bir şey olmadığı anlamına gelir.

/var/log/nginx/access.log gibi günlüğün dışındaki her şey logrotate'in işidir ve bu araç bir systemd zamanlayıcısı üzerinden günlük olarak çalışır. Bir hata türünü bilmekte fayda vardır çünkü bu, df içindeki bir hata gibi görünür. Bir döndürme işleminden sonra eski dosya dizin listesinden kaybolur ancak daemon onu açık tutmaya devam eder; bu nedenle df -h diskin dolu olduğunu bildirirken du -sh /var/log çok daha azını rapor eder. Alan, yalnızca süreç günlüğünü yeniden açtığında geri gelir; yapılandırmadaki postrotate yeniden yükleme satırı bunun içindir. sudo lsof -nP +L1, silinmiş ancak hala açık tutulan dosyaları listeler ve her birini tutan süreci isimlendirir. Bir kuralı hiçbir şeye dokunmadan test etmek için sudo logrotate -d /etc/logrotate.d/nginx kullanın.

Birden fazla sunucudan tek bir toplayıcıya günlük gönderimi

Birden fazla sunucu olduğunda, birden fazla Linux sunucusunu aynı anda yönetmek, günlükler tek bir noktada toplandığında kolaylaşır. rsyslog çoğu dağıtımda halihazırda yüklü olduğundan, en düşük maliyetli merkezi toplayıcı her göndericideki bir dosyadır.

*.* action(type="omfwd" target="logs.example.com" port="514" protocol="tcp")

Bunu /etc/rsyslog.d/50-forward.conf olarak kaydedin, yapılandırmayı doğrulayan ve hiçbir şeyi başlatmadan çıkan sudo rsyslogd -N1 ile kontrol edin, ardından rsyslog servisini yeniden başlatın. Toplayıcı üzerinde TCP girişini etkinleştirin.

module(load="imtcp")
input(type="imtcp" port="514")

İkisi de mekanik olmak üzere iki uyarı mevcuttur. Standart syslog şifreleme veya kimlik doğrulama içermez; bu nedenle 514 numaralı porta erişebilen herhangi bir kaynak, sizinkilerle birebir aynı görünen günlük satırları enjekte edebilir. Bu portu özel bir ağa veya VPN'e bağlayın ve güvenlik duvarı ile kısıtlayın. İkinci olarak, varsayılan işlem kuyruğu bellekte tutulur; bu nedenle toplayıcıya ulaşılamadığında kuyruk dolar ve mesajlar, herhangi bir kopya tutulmaksızın düşürülür. rsyslog, bu durum için güvenilir iletim kılavuzunda disk destekli kuyruk yapısını açıklamaktadır.

ELK yığınının küçük bir VPS üzerinde neden çalışmadığı

ELK; depolama ve arama için Elasticsearch, veri alım hattı için Logstash ve arayüz için Kibana anlamına gelir. Alt sınır JVM heap değeridir ve bu değer, herhangi bir günlük kaydı gelmeden önce belirlenir.

Elastic dokümantasyonu, heap değerinin her bir Elasticsearch düğümüne ayrılan toplam belleğin %50'sinden fazla olmamasını önerir. Bunun nedeni, sürecin heap dışı tampon bellekleri de kullanması ve dizin dosyalarını hızlı okumak için işletim sistemi dosya önbelleğine bağımlı olmasıdır. Dolayısıyla 2 GB heap, Kibana ve sunucunun asıl kullanım amacı olan uygulamalar hesaba katılmadan önce 4 GB bellekli bir makine gerektirir. Elastic ayrıca Elasticsearch'ün heap boyutunu düğüm rolleri ve toplam belleğe göre otomatik ayarladığını belirtir; bu da küçük bir sunucunun düşük bir heap ile başlayıp ömrünü çöp toplama (garbage collection) işlemleriyle geçirmesi demektir.

Logstash, küçük bütçeleri doğrudan zorlayan kısımdır. Elastic'in kendi JVM ayarları sayfası, tipik veri alımı için 4 GB'tan az ve 8 GB'tan fazla olmayan bir heap önerir. Bu, boru hattının ortasındaki tek bir süreç için 4 GB'lık bir VPS'in tamamı demektir.

ChartDocumented JVM heap settings, from each project's own docs
The data behind this chart
[
  {
    "label": "Loki plus Alloy (no JVM)",
    "documented_heap_mb": 0
  },
  {
    "label": "OpenSearch demo compose",
    "documented_heap_mb": 512
  },
  {
    "label": "OpenSearch production example",
    "documented_heap_mb": 2048
  },
  {
    "label": "Logstash recommended minimum",
    "documented_heap_mb": 4096
  }
]

Bunlar, her projenin kendi dokümantasyonunda yayınladığı değerlerdir. Bunlar bir test makinesinde yapılmış ölçümler değildir ve iş yükünüz bu değerleri değiştirecektir. OpenSearch'ün örnek compose dosyası, demo için düğüm başına 512 MB, üretim örneğinde ise 2048 MB değerini belirlerken, Logstash için önerilen alt sınır 4096 MB'tır. Heap sütunu Loki ve Alloy için 0 değerini gösterir çünkü bunlar JVM heap rezervasyonu gerektirmeyen Go programlarıdır. Tek bir sayıdaki tüm fark budur: Bir JVM bileşeni, günlük kaydı gelip gelmediğine bakılmaksızın kendi rezervasyonunu kullanır.

Yine de Elastic yığınını küçük bir sunucuda çalıştırmak istiyorsanız, Logstash'i kaldırın ve hafif bir toplayıcı ile doğrudan Elasticsearch'e veri gönderin. Logstash, yüksek hacimli verileri ayrıştırmak ve dönüştürmek için vardır; tek bir sunucuda bu işlemi uç noktada yapabilir veya tamamen atlayabilirsiniz.

Hem Elasticsearch hem de OpenSearch, vm.max_map_count değerinin 262144 seviyesine yükseltilmesini gerektirir. Bunun nedeni, dizin dosyalarını belleğe eşlemeleri (memory map) ve Linux varsayılan sınırının bu işlem için çok düşük olmasıdır. Yeni bir sunucuda başlatıldıktan saniyeler sonra kapanan bir container, genellikle sadece bu kısıtlama nedeniyle başarısız olur.

OpenSearch veya Elasticsearch: hangisini kurabilirsiniz?

Lisans geçmişi kısa tutulmuştur, çünkü neyi çalıştırmanıza izin verildiğini bu belirler. Ocak 2021'de Elastic, Elasticsearch ve Kibana'yı Apache 2.0 lisansından çıkarıp ikili SSPL (server side public license) ve Elastic License 2.0 modeline geçirdi. AWS, son Apache 2.0 kodunu OpenSearch olarak çatalladı (fork) ve bu proje Apache 2.0 altında kalmaya devam etti. Eylül 2024'te Elastic, ücretsiz kaynak kod için bir seçenek olarak AGPLv3 (GNU Affero General Public License version 3) lisansını ekledi. Tek bir VPS üzerinde kendi kendine barındırma (self-hosting) yapan bir kişi için, bu lisansların her biri yaptığınız işe izin vermektedir. Lisanslar, yazılımı yönetilen bir hizmet olarak başkalarına sunduğunuzda kısıtlayıcı hale gelir.

Küçük bir sunucudaki pratik fark, geçmişin düşündürdüğünden daha azdır, çünkü her ikisi de temelinde aynı motoru kullanır. İsimlendirmeler farklıdır: dizin yaşam döngüsü OpenSearch'te ISM (index state management), Elasticsearch'te ise ILM (index lifecycle management) olarak adlandırılır. Ağustos 2026 itibarıyla, OpenSearch 2.12 ve sonraki sürümleri, ilk çalıştırmada bir yönetici parolası ayarlanmadan başlamayı reddeder.

sudo sysctl -w vm.max_map_count=262144
printf 'vm.max_map_count = 262144\n' | sudo tee /etc/sysctl.d/99-opensearch.conf
docker run -d -p 9200:9200 -p 9600:9600 -e "discovery.type=single-node" \
  -e "OPENSEARCH_INITIAL_ADMIN_PASSWORD=<custom-admin-password>" \
  opensearchproject/opensearch:latest

sysctl -w satırı ayarı hemen uygular, /etc/sysctl.d/ içindeki dosya ise yeniden başlatma sonrasında kalıcı olan kısımdır. Konteynerin curl -k -u admin:<password> https://localhost:9200 ile ayağa kalktığını doğrulayın. Servis, demo sertifikası kullanarak https üzerinden yanıt verir, bu nedenle -k doğrulamayı atlar; sağlıklı bir yanıt, küme adını ve sürümünü içeren küçük bir JSON bloğudur. OpenSearch kurulum sayfası ayrıca Docker Desktop kullanıcılarına ana makinede en az 4 GB bellek ayırmalarını önerir; bu, sürecin ihtiyaç duyduğu kaynak miktarı hakkında makul bir göstergedir.

Loki'nin boyutu nasıl korunur: tam metin dizini yerine etiketler

Loki, etiketler üzerinde tek bir dizin tutar ve günlük satırlarını sıkıştırılmış parçalar halinde depolar. Bir sorgu önce akışları seçer, ardından metni filtreler. {unit="ssh.service"} |= "Failed password", akışı etiketiyle seçer ve ardından bu parçaları dize için tarar. Satırın gövdesini dizinleyen hiçbir şey yoktur; bu nedenle veri alımı düşük maliyetli kalır ve bellekte tutulması gereken ters bir dizin bulunmaz. Maliyet sorgu zamanına kayar; genellikle hangi servise baktığınızı bildiğiniz durumlarda bu iyi bir takastır.

Grafana belgeleri, Loki'nin tamamının -target=all ile tek bir süreçte çalıştığı monolitik modu, günlük yaklaşık 20GB'a kadar olan küçük okuma ve yazma hacimleri için önermektedir. Tek bir VPS bu kapasite için oldukça uygundur.

Buradaki tuzak, etiket kardinalitesidir. Etiket değerlerinin her farklı kombinasyonu bir akıştır ve akış sayısı, Loki'nin bellek ve dizin boyutunu belirler. Bir istemci IP adresi veya istek tanımlayıcısı tutan bir etiket, her değer için bir akış oluşturur; bu nedenle yoğun bir web sunucusu günde on binlerce akış üretebilir ve süreç, çekirdek onu durdurana kadar büyür. Etiketleri kağıt üzerinde sayabileceğiniz değerlerle sınırlı tutun: birim, ana makine, iş, seviye. Değişken ayrıntıları, sorgu zamanında bir filtre ifadesinin bulabileceği şekilde satırın kendi içine yerleştirin.

Loki ve Alloy'un tek bir VPS üzerine kurulumu

İki süreç bu işi yürütür. Loki verileri depolar ve sorguları yanıtlar. Grafana Alloy ise logları okur ve iletir. Eskiden gönderici olarak Promtail kullanılırdı; ancak Promtail 2 Mart 2026 itibarıyla ömrünü tamamladığı için yeni kurulumlarda Alloy kullanılmaktadır. Loki'nin kendi Docker örneği artık bir Alloy yapılandırması ile gelmektedir.

wget https://raw.githubusercontent.com/grafana/loki/v3.7.0/cmd/loki/loki-local-config.yaml -O loki-config.yaml

Kullanmadan önce bu dosyayı okuyun. Dosya, path_prefix: /tmp/loki değerini /tmp/loki/chunks altındaki yığınlarla ayarlar; bu bir demo için doğru olsa da bir sunucu için yanlıştır. Container'ın /tmp dizini altındaki hiçbir veri, container yeniden oluşturulduğunda kalıcı olmaz; bu nedenle bir sonraki imaj güncellemesinde geçmiş verileriniz kaybolur. Bu yolu mount ettiğiniz bir dizine yönlendirin.

common:
  instance_addr: 127.0.0.1
  path_prefix: /loki
  storage:
    filesystem:
      chunks_directory: /loki/chunks
      rules_directory: /loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory
docker volume create loki-data
docker run --name loki -d \
  -v $(pwd):/mnt/config -v loki-data:/loki \
  -p 127.0.0.1:3100:3100 \
  grafana/loki:3.7.0 -config.file=/mnt/config/loki-config.yaml
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3100/ready

Son komut 200 çıktısını vermelidir; çünkü /ready, Loki trafiği kabul etmeye hazır olduğunda HTTP 200 döner. Başka bir çıktı, sürecin hala başladığını veya yapılandırmanın reddedildiğini gösterir; docker logs loki ise bunun nedenini belirtir. Çalıştırma komutundaki iki detay kasıtlıdır. Port yalnızca 127.0.0.1 üzerinde yayınlanır; çünkü örnek yapılandırma auth_enabled: false içerir ve Loki kendi başına bir kullanıcı kimlik doğrulaması sunmaz. Bu nedenle 3100 numaralı porta erişebilen herkes tüm logları okuyabilir veya sahte loglar yazabilir. Servisi loopback üzerinde tutun ya da bir VPN veya kimlik doğrulaması yapan bir reverse proxy arkasına alın. İsimlendirilmiş volume (named volume) önemlidir; çünkü imaj loki kullanıcısı ve 10001 UID ile çalışır. Bu nedenle root tarafından sahiplenilen bir bind mount dizini, container tarafından yazılamaz durumdadır.

sudo apt-get update && sudo apt-get install -y gpg wget
sudo mkdir -p /etc/apt/keyrings/
sudo wget -O /etc/apt/keyrings/grafana.asc https://apt.grafana.com/gpg-full.key
echo "deb [signed-by=/etc/apt/keyrings/grafana.asc] https://apt.grafana.com stable main" \
  | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt-get update
sudo apt-get install -y alloy

Alloy, /etc/alloy/config.alloy dosyasını okur. Bu dosya sistem journal'ını ve bir dosya setini alır, her ikisini de yerel Loki'ye iletir.

loki.write "local" {
  endpoint {
    url = "http://127.0.0.1:3100/loki/api/v1/push"
  }
}

loki.relabel "journal" {
  forward_to = []
  rule {
    source_labels = ["__journal__systemd_unit"]
    target_label  = "unit"
  }
}

loki.source.journal "read" {
  forward_to    = [loki.write.local.receiver]
  relabel_rules = loki.relabel.journal.rules
  labels        = {job = "systemd-journal", host = "app-01"}
}

local.file_match "nginx" {
  path_targets = [{"__path__" = "/var/log/nginx/*.log", "job" = "nginx", "host" = "app-01"}]
}

loki.source.file "nginx" {
  targets    = local.file_match.nginx.targets
  forward_to = [loki.write.local.receiver]
}

Yeniden etiketleme (relabel) kuralı, __journal__systemd_unit journal alanını unit isimli bir etikete kopyalar; bu, {unit="ssh.service"} özelliğinin daha sonra çalışmasını sağlar. Bu kural olmadan, birim adı (unit name) girdinin içinde kalır ve bir etiket haline gelmez; bu durumda sorgulama yapamazsınız ve her sorgu tüm veriyi taramak zorunda kalır.

sudo systemctl reload alloy
systemctl show -p User alloy
sudo journalctl -n 5
sudo -u alloy journalctl -n 5

Kurulumların çoğu burada takılır. Alloy, root olarak değil kendi servis hesabı ile çalışır. Sistem journal'ını okumak için systemd-journal grubuna üyelik gerekir; /var/log/nginx altındaki dosyalar ise Debian ve Ubuntu üzerinde adm grubuna aittir. systemctl show komutunun son komutta yazdırdığı hesabı yerine koyun. Eğer root ile çalıştırılan komuttan çok daha az girdi dönüyorsa, ilgili hesap sistem journal'ını okuyamıyordur ve yapılandırmanız ne kadar doğru olursa olsun Loki boş kalacaktır. Grupları ekleyin ve sudo usermod -aG systemd-journal,adm alloy komutunu takiben sudo systemctl restart alloy ile yeniden başlatın.

curl -G -s "http://127.0.0.1:3100/loki/api/v1/query_range" \
  --data-urlencode 'query={job="systemd-journal"}' \
  --data-urlencode 'limit=5' | jq '.data.result | length'

0'dan büyük bir sayı, o etiketle ilişkili akışların var olduğunu ve girdi içerdiğini gösterir. 0 değeri, o etiket altında henüz hiçbir verinin ulaşmadığı anlamına gelir. Bir varsayılan ayar, yaygın bir yanlış alarmı açıklar: loki.source.journal, max_age değerini 7h olarak ayarlar. Bu nedenle yeni bir başlangıçta journal'ın son yedi saati okunur, daha eski veriler okunmaz. İnsan arayüzü için Grafana'yı aynı makinede çalıştırın ve Loki veri kaynağını http://127.0.0.1:3100. adresine yönlendirin. Container logları farklı bir kaynak gerektirir: Alloy, çalışan Docker container'larını keşfeder ve onları takip eder. Loki'nin kendi başlangıç örneği bunu yapar; tek düğümlü bir k3s kümesi üzerinde ise bu iş, kubelet'in yazdığı pod log dizinine taşınır.

Saklama süresi: günlüklerinizin silineceği günü belirleyin

Neredeyse hiç kimse disk dolana kadar bir saklama süresi belirlemez; dolduğunda ise servis kesintisi yaşanırken saat sabah 3'te bu kararı vermek zorunda kalır. İlk günden şu iki soruyla kararınızı verin: Gerçekten ne kadar geriye dönük verilere bakıyorsunuz ve gelecek ay yapılacak bir olay incelemesi sırasında elinizde nelerin bulunması gerekiyor? Tek bir sunucu için 14 ila 30 gün arası her iki soruya da yanıt verir.

Loki, compactor özelliğini etkinleştirmediğiniz sürece hiçbir veriyi silmez. Saklama süresi varsayılan olarak kapalıdır; bu durum, retention_period ayar dosyasında hiçbir işlev görmeden beklerken disk alanı dolan kullanıcıları şaşırtır.

limits_config:
  retention_period: 744h

compactor:
  working_directory: /loki/retention
  compaction_interval: 10m
  retention_enabled: true
  retention_delete_delay: 2h
  retention_delete_worker_count: 150
  delete_request_store: filesystem

744h değeri 31 güne karşılık gelir. Bu bloğu yöneten dört temel kural şunlardır:

  • Saklama süresi compactor tarafından uygulanır ve Grafana belgeleri compactor'ın tek bir örnek (instance) olarak çalıştırılmasını önerir. Tek bir VPS üzerinde bu durum kendiliğinden gerçekleşir.
  • Minimum saklama süresi 24h'dir ve saklama özelliği yalnızca indeks periyodu 24h olduğunda çalışır. schema_config örneği halihazırda period: 24h değerini kullandığı için bu ayarı değiştirmeyin.
  • retention_enabled değeri true olduğunda delete_request_store gereklidir. Bu ayar, silme isteklerini tutan depolama alanını tanımlar; bu nedenle dosya sistemi tabanlı tek bir düğümde, şemadaki object_store: filesystem ile eşleşmelidir.
  • Chunks önce işaretlenir ve burada 2h olarak belirlenen retention_delete_delay süresinden sonra kaldırılır; bu nedenle boş alan, politikanın ima ettiğinden daha geç açığa çıkar. Ayarı, yeniden yüklemeden beş dakika sonra df ile değerlendirmeyin.

OpenSearch, tek tek satırlar yerine tüm indeksleri siler; bu nedenle günlük indeksleri günlük olarak oluşturulur. Bir ISM politikası, indeksi durumlar arasında ilerletir ve yeterince eskidiğinde siler; bir ism_template ise politikayı yeni indekslere otomatik olarak atar, böylece manuel işlem yapmanız gerekmez.

Günlük indekslerini 14 gün sonra silen ISM politikası
{
  "policy": {
    "description": "delete log indexes after 14 days",
    "default_state": "hot",
    "states": [
      {
        "name": "hot",
        "actions": [],
        "transitions": [
          { "state_name": "delete", "conditions": { "min_index_age": "14d" } }
        ]
      },
      {
        "name": "delete",
        "actions": [ { "delete": {} } ],
        "transitions": []
      }
    ],
    "ism_template": { "index_patterns": ["logs-*"], "priority": 100 }
  }
}

Politikayı _plugins/_ism/policies/logs-retention adresine bir PUT isteği göndererek oluşturun. Şablon, politika oluşturulduktan sonra yaratılan indekslere uygulanır; bu nedenle diskte halihazırda bulunan indekslere politikanın manuel olarak atanması gerekir.

Hangi sistemi kullanırsanız kullanın, bir saklama süresi değeri ancak arkasındaki boş alan denetimi kadar güvenilirdir. 10 günlük günlük verisi diski zaten dolduruyorsa, 14 günlük saklama süresi sizi kurtarmaz. Bu nedenle politikayı VPS üzerinde disk sağlığı izleme ve %80 doluluk oranında bir uyarı ile birlikte kullanın.

GB başına ne kadar disk alanı gerekir

Dürüst cevap, satırlarınıza ve alanlarınıza bağlıdır; bu nedenle yayınlanmış oranlara güvenmek yerine kendi verileriniz üzerinde ölçüm yapın. Mekanizmalar, yönü tahmin edebilecek kadar farklıdır. OpenSearch ve Elasticsearch, depolanan belgenin yanı sıra indekslenen her alan üzerinde ters dizin (inverted index) oluşturur; bu nedenle diske yazılan veri ham metinden daha büyüktür ve her kopya (replica) bu boyutu katlar. Tek bir düğüm üzerinde kopya sayısını 0 olarak ayarlayın; çünkü aynı düğümdeki bir kopya parçası, o düğümün çökmesi durumunda kurtarılamaz. Kopya sayısını 1'de bırakmak disk kullanımını ikiye katlar ve küme sağlığını kalıcı olarak sarı durumda tutar. Loki ise sıkıştırılmış parçalar ve küçük bir etiket dizini yazar; bu nedenle kapladığı alan, satırların sıkıştırılmış boyutuyla doğru orantılıdır.

sudo du -sh /var/lib/docker/volumes/loki-data/_data
curl -k -u admin:<password> "https://localhost:9200/_cat/indices?v&h=index,docs.count,store.size"

Hangi sistem geçerliyse, birbirini takip eden iki gün boyunca çalıştırın. Aradaki fark, günlük büyüme miktarınızdır. Bu değeri saklama sürenizle (gün sayısı) çarpın, sıkıştırma ve birleştirme işlemleri için yaklaşık %30 pay ekleyin ve ardından bunu mevcut birim kapasitesiyle karşılaştırın. Eğer sığmıyorsa, disk satın almadan önce saklama süresini kısaltın; çünkü daha büyük bir birim, aynı sorunu sadece birkaç hafta sonrasına erteleyecektir.

Küçük bir sunucuda ilk ne bozulur

Bellek ilk tükenen kaynaktır. Çekirdeğin OOM (out of memory) katili, büyük bir süreci seçer ve günlük tutan bir sunucudaki en büyük süreç genellikle JVM'dir. journalctl -k | grep -i "killed process", süreç adını köşeli parantez içinde göstererek sonlandırma işlemini belirtir. Kurban her zaman günlük yığını olmayabilir; sshd veya veritabanınız da seçilebilir; günlükleme denemesinin, günlüklerini almak istediğiniz uygulamayı devre dışı bırakması bu şekilde gerçekleşir. Konteynerlere açık sınırlar koyun; böylece hata, seçtiğiniz yerde gerçekleşir. Docker Compose içindeki bellek sınırları bunun içindir.

Disk ikinci sırada tükenir ve arama motorları belirli ve tanınabilir bir şekilde hata verir. Elasticsearch ve OpenSearch, disk kullanımını birkaç seviyede izler. Düşük eşik değeri %85, yüksek eşik değeri ise %90 seviyesindedir. %95'lik taşma aşamasında, o düğümde shard'ı bulunan her indeks index.blocks.read_only_allow_delete bloğunu alır ve yazma işlemleri blocked by: [FORBIDDEN/12/index read-only / allow delete (api)] hatasıyla başarısız olur. Blok, kullanım yüksek eşik değerinin altına düştüğünde kaldırılır. Önce alanı boşaltın, ardından blok devam ederse manuel olarak temizleyin.

curl -k -u admin:<password> -X PUT "https://localhost:9200/_all/_settings" \
  -H 'Content-Type: application/json' \
  -d '{"index.blocks.read_only_allow_delete": null}'

Loki daha sessiz bir şekilde başarısız olur. Geçiş yapabileceği bir salt okunur modu yoktur; bu nedenle dolu bir birim, göndericide başarısız itme işlemleri ve sorgu sonuçlarında boşluklar olarak kendini gösterir. Kardinalite sorunu ise bir hata yerine bellekte yavaş bir artış olarak ortaya çıkar. Chunks dizininin boyutunu bir olaydan sonra değil, düzenli bir program dahilinde izleyin.

Son hata ise yanlış veriyi sisteme dahil etmektir. Bir günlük sistemi, metrik sistemi değildir: 10 saniyede bir örneklenen ve metin olarak saklanan CPU yükünü tutmak maliyetlidir ve grafiklemek zordur; bu iş Ubuntu 24.04 üzerinde bir Zabbix izleme sunucusu gibi bir araca aittir. Uygulama istisnaları gruplandırma, tekilleştirme ve yığın izleme görünümü gerektirir; bu da kendi kendine barındırılan bir hata takipçisinin işidir. Sitenin kapalı olduğunu bilmek ise ayrı bir görevdir ve Uptime Kuma gibi bir çalışma süresi ve durum sayfası tarafından karşılanır. Günlük sistemini, bir insanın okuyacağı metin satırları için kullanın.

FAQ

Sunucu günlüklerimi aramak için Elasticsearch kullanmam gerekiyor mu?

Bir veya iki sunucu için gerekmez. journalctl zaten birim, öncelik, önyükleme ve zaman aralığına göre filtreleme yapabilir; döndürülmüş dosyalar ise grep ve zgrep ile sorgulanabilir. Bir arama kümesi, ancak çok sayıda makineniz olduğunda, hepsinde aynı anda serbest metin araması yapmanız gerektiğinde veya birden fazla kişinin paylaşımlı bir arayüze ihtiyaç duyması durumunda bellek maliyetine değer. Bunun altındaki ölçeklerde, boyut sınırı ve saklama süresi yapılandırılmış journald, ek RAM tüketmeden aynı işi görür.

Kendi barındırdığım günlük yönetimi için ne kadar RAM gerekir?

Genel bir kural yerine her projenin yayınladığı teknik verileri kullanın. Loki ve Alloy, önceden ayrılmış bir heap alanı gerektirmeyen Go programlarıdır ve Grafana, monolitik Loki için günlük yaklaşık 20GB veri işleme kapasitesini dokümante eder. OpenSearch'ün örnek compose dosyası demo için 512 MB, üretim örneği için ise 2 GB heap alanı belirler; Elastic ise heap boyutunun toplam belleğin yüzde 50'si veya altında kalması gerektiğini belirtir, bu da 2 GB heap için Kibana hariç 4 GB bellekli bir makine demektir. Logstash dokümantasyonu ise tek başına en az 4GB heap önerir. Bunlar benchmark değil, dokümante edilmiş ayarlardır; bu nedenle bir plan oluşturmadan önce kendi yükünüzü ölçün.

Günlükler için Loki ve OpenSearch arasındaki temel fark nedir?

Dizinleme modelidir. Loki yalnızca etiketleri dizinler ve günlük içeriğini sorgu anında taranan sıkıştırılmış parçalar halinde tutar; bu nedenle yazma işlemleri ucuzdur ancak geniş kapsamlı sorgular daha maliyetlidir. OpenSearch ise alanların içeriğini dizinler; bu sayede rastgele tam metin aramaları hızlıdır ancak hem bellek hem de disk dizinleme maliyetine katlanır. Hangi servisi ve hangi zaman aralığını sorgulayacağınızı bildiğiniz durumlarda Loki'yi seçin. Önceden tahmin edemediğiniz metinleri aramanız gerektiğinde ise OpenSearch'ü tercih edin.

Bir VPS üzerinde günlükleri ne kadar süre tutmalıyım?

Disk sizin yerinize karar vermeden önce süreyi siz belirleyin. Her sistemde tek bir yerden yapılandırın: journald için MaxRetentionSec= ve SystemMaxUse=, Loki için compactor etkinleştirilmiş halde retention_period ve OpenSearch için min_index_age içeren bir ISM politikası. Çoğu tek sunuculu kurulum için 14 ila 30 gün, hata ayıklama ve olay incelemesi için yeterlidir. Daha uzun süre saklamanız gereken her şey sunucu dışında bir kopyada tutulmalıdır; çünkü yalnızca arızalanan sunucuda tutulan bir günlük, güvenilir bir kayıt değildir.

Günlükleri Loki'ye göndermek için hala Promtail mi kullanılmalı?

Hayır. Promtail, 2 Mart 2026 itibarıyla ömrünü tamamlamıştır (end of life) ve yerini Grafana Alloy almıştır. Loki'nin kendi Docker kurulum örneği artık Alloy yapılandırması ile gelmektedir ve Grafana, mevcut Promtail yapılandırmasını Alloy sözdizimine dönüştüren bir araç sunmaktadır. Mevcut bir Promtail kurulumu çalışmaya devam eder ancak artık güncelleme almaz; bu nedenle geçişi süresiz erteleyebileceğiniz bir yükseltme değil, zorunlu bir bakım işlemi olarak görün.

#logging#loki#opensearch#journald#monitoring