“Container İzleme ve Loglama” yazımızda Prometheus ve Grafana ile metrikleri (CPU, bellek, istek sayısı gibi sayısal değerler) nasıl izleyeceğimizi görmüştük. Ama bir hatanın kök nedenini bulmak genellikle sayılarla değil, log satırlarıyla mümkün olur — ve onlarca container’ın loglarını tek tek docker logs ile aramak sürdürülemez. Elastic Stack (eskiden ELK olarak bilinir), dağınık logları merkezi, aranabilir bir yerde toplamanın endüstri standardı çözümüdür.

Elastic Stack’in dört parçası

Bileşen Görevi
Elasticsearch Logları depolayan ve saniyeler içinde aranabilir kılan dağıtık arama/analitik motoru.
Logstash Logları toplar, ayrıştırır (parse eder), zenginleştirir ve Elasticsearch’e yazar — bir “işleme hattı” (pipeline).
Kibana Elasticsearch’teki veriyi arama, filtreleme ve görselleştirme (dashboard) için web arayüzü.
Beats (örn. Filebeat) Sunucularda/container’larda çalışan hafif ajanlar; log dosyalarını okuyup Logstash’e veya doğrudan Elasticsearch’e iletir.

Tipik bir akış şöyle işler: Filebeat her sunucuda/container’da log satırlarını toplar → Logstash bu ham logları yapılandırılmış veriye dönüştürür (örneğin bir Nginx log satırından IP, tarih, HTTP durum kodu gibi alanları ayıklar) → Elasticsearch bu yapılandırılmış veriyi indeksler → Kibana üzerinden aranır ve görselleştirilir.

Prometheus + Grafana ile ELK arasındaki fark

Bu iki yığın birbirinin yerine değil, birbirini tamamlayıcı olarak kullanılır:

Prometheus + Grafana Elastic Stack
Veri türü Metrikler — sayısal, zaman serisi (CPU %, istek/sn) Loglar — serbest metin, yapılandırılmış olaylar
Tipik soru “CPU kullanımı son 1 saatte nasıl değişti?” “Bu kullanıcı ID’siyle ilgili hangi hata mesajları geçti?”
Veri toplama Pull tabanlı (Prometheus hedefleri periyodik olarak sorgular) Push tabanlı (Beats/Logstash veriyi gönderir)
Saklama maliyeti Görece düşük (özetlenmiş sayısal veri) Görece yüksek (tam log metni indekslenir)

Olgun bir izleme kurulumu genellikle ikisini bir arada kullanır: Prometheus/Grafana “bir sorun VAR mı?” sorusuna (alarmlarla) hızlı cevap verir; Elastic Stack “sorun TAM OLARAK NE?” sorusuna, ilgili logları kazarak cevap verir.

Docker Compose ile hızlı bir Elastic Stack kurulumu

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
    environment:
      discovery.type: single-node
      xpack.security.enabled: "false"   # sadece yerel/test ortamı için
      ES_JAVA_OPTS: "-Xms512m -Xmx512m"
    ports:
      - "9200:9200"
    volumes:
      - es_data:/usr/share/elasticsearch/data

  kibana:
    image: docker.elastic.co/kibana/kibana:8.15.0
    environment:
      ELASTICSEARCH_HOSTS: http://elasticsearch:9200
    ports:
      - "5601:5601"
    depends_on:
      - elasticsearch

  logstash:
    image: docker.elastic.co/logstash/logstash:8.15.0
    volumes:
      - ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf:ro
    depends_on:
      - elasticsearch

volumes:
  es_data:
i

xpack.security.enabled: "false" sadece yerel deneme/öğrenme ortamı için kabul edilebilir — production’da Elasticsearch’ü kimlik doğrulaması kapalı şekilde asla dışarıya açmayın. Gerçek bir kurulumda X-Pack güvenliğini etkinleştirip TLS ve kullanıcı bazlı erişim tanımlamanız gerekir.

Container loglarını Elastic Stack’e ulaştırmanın iki yolu

1. Filebeat ile Docker loglarını otomatik toplamak — en yaygın ve önerilen yöntem: Filebeat’i bir container olarak çalıştırıp, Docker’ın diskte tuttuğu log dosyalarını (varsayılan json-file log sürücüsüyle) otomatik keşfedip okumasını sağlarsınız.

# filebeat.yml
filebeat.autodiscover:
  providers:
    - type: docker
      hints.enabled: true

output.elasticsearch:
  hosts: ["elasticsearch:9200"]
  filebeat:
    image: docker.elastic.co/beats/filebeat:8.15.0
    user: root
    volumes:
      - ./filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
    depends_on:
      - elasticsearch

2. Docker’ın kendi GELF log sürücüsüyle doğrudan Logstash’e göndermek — ekstra bir ajan container’ı çalıştırmadan, her container’ın loglarını doğrudan hedefe yönlendirir:

services:
  api:
    image: kullanici-adi/benim-api:latest
    logging:
      driver: gelf
      options:
        gelf-address: "udp://logstash-sunucu:12201"
        tag: "benim-api"

Logstash pipeline’ı: ham logu yapılandırılmış veriye çevirmek

Logstash’in en değerli özelliği, serbest metin log satırlarını (örneğin bir Nginx erişim logunu) aranabilir alanlara ayrıştırabilmesidir:

# logstash.conf
input {
  beats {
    port => 5044
  }
}

filter {
  if [container][name] =~ "nginx" {
    grok {
      match => { "message" => "%{IPORHOST:istemci_ip} - - \[%{HTTPDATE:zaman}\] \"%{WORD:metod} %{DATA:yol} HTTP/%{NUMBER:http_versiyon}\" %{NUMBER:durum_kodu} %{NUMBER:boyut}" }
    }
    mutate {
      convert => { "durum_kodu" => "integer" }
    }
  }
}

output {
  elasticsearch {
    hosts => ["elasticsearch:9200"]
    index => "loglar-%{+YYYY.MM.dd}"
  }
}

grok filtresi, ham bir Nginx log satırını istemci_ip, metod, durum_kodu gibi ayrı alanlara böler. Bu sayede Kibana’da “sadece 500 durum kodlu istekleri göster” veya “en çok isteği hangi IP gönderiyor?” gibi sorguları saniyeler içinde çalıştırabilirsiniz — ham metinde arama yapmaktan çok daha güçlü bir yöntem.

Kibana’da logları keşfetmek

  1. localhost:5601 adresine gidin, Stack Management → Index Patterns altında loglar-* desenini tanımlayın.
  2. Discover sekmesinde, gelen tüm logları zaman sırasıyla görürsünüz; sağdaki alan listesinden durum_kodu, container.name gibi alanlara tıklayarak hızlı filtreler uygulayabilirsiniz.
  3. Arama çubuğuna durum_kodu >= 500 and container.name: "benim-api" gibi bir KQL (Kibana Query Language) sorgusu yazarak, sadece belirli bir servisin hata verdiği anları saniyeler içinde bulabilirsiniz.
  4. Dashboard sekmesinden, “son 1 saatte durum koduna göre istek sayısı” gibi grafikleri bir araya getirip Grafana’daki metrik panolarına benzer, log tabanlı bir izleme ekranı oluşturabilirsiniz.

Ne zaman Elastic Stack, ne zaman daha basit bir çözüm?

Elastic Stack güçlü ama kaynak açısından da (bellek, disk) pahalıdır — küçük bir projede tek başına Elasticsearch’ü ayakta tutmak, uygulamanızın kendisinden daha fazla kaynak tüketebilir. Karar vermeye yardımcı bir kaba kural:

  • Tek sunucu, az container: docker compose logs -f ve docker logs çoğu zaman yeterlidir.
  • Birkaç sunucu, orta ölçek: Daha hafif bir alternatif olan Grafana Loki (Prometheus’un log dünyasındaki karşılığı gibi düşünülebilir, “grep benzeri” indeksleme yapar, Elasticsearch’ten çok daha az kaynak tüketir) iyi bir orta nokta olabilir.
  • Büyük ölçek, karmaşık arama ihtiyacı, uzun süreli saklama: Elastic Stack’in tam metin arama gücü ve olgun ekosistemi (güvenlik analitiği, anomali tespiti gibi eklentiler dahil) burada öne çıkar.

Artık hem metrikleri (Prometheus + Grafana) hem de logları (Elastic Stack) merkezi olarak izleyip arayabiliyorsunuz. Bu, “Uçtan Uca Örnek Proje” yazımızdaki production kurulumuna eklenebilecek doğal bir sonraki katman — sunucu ve altyapı otomasyonunu (Ansible, Terraform) CI/CD ile (Jenkins veya GitHub Actions) birleştirdiğinizde, gerçek bir production-grade DevOps hattının tüm parçaları artık bu portalda bir arada.