Elasticsearch Cluster Mimarisi: Node ve Shard Kavramları

Elasticsearch ile ciddi iş yapmaya başladığınızda, tek node üzerinde çalışan bir kurulum çok geçmeden yetersiz kalmaya başlar. Yüksek veri hacmi, artan sorgu yükü ve yüksek erişilebilirlik gereksinimleri sizi kaçınılmaz olarak cluster mimarisine yönlendirir. Ancak cluster kurmak tek başına yeterli değil; node tiplerini, shard dağılımını ve replica stratejisini doğru anlamadan kurduğunuz cluster size kâr değil zarar getirebilir. Bu yazıda Elasticsearch cluster mimarisini, node ve shard kavramlarını gerçek dünya senaryolarıyla birlikte ele alacağız.

Elasticsearch Cluster Nedir?

Bir Elasticsearch cluster’ı, ortak bir cluster ismi altında birbirine bağlanan bir veya birden fazla node’dan oluşur. Her node, cluster’ın bir parçasıdır ve veriyi birlikte depolar, birlikte işler. Cluster’ın en temel özelliği yatay ölçeklenebilirlik sağlamasıdır; yani sisteme yeni node ekleyerek kapasiteyi artırabilirsiniz.

Cluster içindeki tüm node’lar birbirini tanır ve hangi node’un hangi veriyi tuttuğunu bilir. Bir istemci herhangi bir node’a sorgu gönderdiğinde, o node ilgili node’lardan veriyi toplayarak sonucu döndürür. Kullanıcı açısından cluster tek bir büyük veritabanı gibi görünür.

# Cluster sağlık durumunu kontrol et
curl -X GET "localhost:9200/_cluster/health?pretty"

# Tüm node'ları listele
curl -X GET "localhost:9200/_cat/nodes?v&pretty"

# Cluster istatistiklerini görüntüle
curl -X GET "localhost:9200/_cluster/stats?pretty"

Yukarıdaki komutların çıktısında status alanı üç renk alabilir. green tüm shard’ların sağlıklı olduğunu, yellow primary shard’ların tamam ama bazı replica’ların atanmadığını, red ise bir veya birden fazla primary shard’a erişilemediğini gösterir. Prodüksiyonda yellow durumu genellikle göz ardı edilir ama aslında dikkat edilmesi gereken bir uyarıdır.

Node Tipleri ve Rolleri

Elasticsearch’te her node bir veya birden fazla rol üstlenebilir. Küçük cluster’larda tüm rolleri tek bir node üstlenir, büyük cluster’larda ise roller ayrıştırılır. Node rollerini doğru dağıtmak hem performans hem de kararlılık açısından kritiktir.

Master Node

Master node, cluster’ın beynidir. Index oluşturma ve silme, node ekleme ve çıkarma, shard atama gibi cluster düzeyindeki yönetim işlemlerini koordine eder. Master node veri depolamaz, sadece cluster state’ini yönetir.

Prodüksiyonda dedicated master node kullanmak şiddetle tavsiye edilir. Eğer master node aynı zamanda veri de depoluyorsa, yoğun sorgu trafiği altında master işlevleri aksayabilir ve bu tüm cluster’ı etkiler.

# elasticsearch.yml - Dedicated Master Node konfigürasyonu
node.name: master-node-01
node.roles: [ master ]
cluster.name: production-cluster
network.host: 0.0.0.0
discovery.seed_hosts: ["master-01", "master-02", "master-03"]
cluster.initial_master_nodes: ["master-node-01", "master-node-02", "master-node-03"]

# Master node için JVM heap ayarı (veri taşımadığı için daha az bellek yeterli)
# jvm.options dosyasında:
# -Xms2g
# -Xmx2g

Split-brain problemi Elasticsearch dünyasının en korkulan senaryolarından biridir. İki master node birbirinden haberdar olamazsa her ikisi de kendini master ilan edebilir ve farklı cluster state’leri oluşturabilir. Bu sorunu önlemek için quorum mantığıyla çalışan minimum master node sayısını doğru ayarlamak gerekir. Elasticsearch 7.x sonrasında bu otomatik olarak yönetilse de yine de tekil sayıda (3 veya 5) dedicated master node kullanmak standart pratiktir.

Data Node

Gerçek veriyi depolayan ve sorguları işleyen node’lardır. Disk I/O, RAM ve CPU açısından en yoğun yükü bu node’lar taşır. Elasticsearch 7.x ile birlikte data node’lar daha spesifik rollere ayrılabilir hale geldi.

  • data_hot: Aktif olarak yazılan ve sık sorgulanan güncel veri. Yüksek performanslı SSD diskler kullanılmalı.
  • data_warm: Daha az sorgulanan ama hâlâ aktif tutulan veri. Daha ucuz disk çözümleri kullanılabilir.
  • data_cold: Nadiren erişilen arşiv verisi. Yavaş ama kapasiteli diskler tercih edilebilir.
  • data_frozen: Snapshot’tan anlık yüklenen, en az erişilen veri katmanı.

Bu mimari ILM (Index Lifecycle Management) ile birleşince log yönetimi gibi senaryolarda çok güçlü bir yapı ortaya çıkar. Yeni loglar hot node’lara yazılır, 7 gün sonra warm’a, 30 gün sonra cold’a taşınır.

# elasticsearch.yml - Hot Data Node konfigürasyonu
node.name: hot-data-01
node.roles: [ data_hot ]
cluster.name: production-cluster
path.data: /data/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
discovery.seed_hosts: ["master-01", "master-02", "master-03"]

Coordinating Node

Bu node tipi ne master ne de data rolü üstlenir. Sadece istemciden gelen sorguları alır, ilgili data node’lara dağıtır, gelen sonuçları birleştirir ve istemciye döndürür. Load balancer görevi görür.

Yüksek trafikli uygulamalarda coordinating node kullanmak, master ve data node’ların koordinasyon yükünden kurtulmasını sağlar. Özellikle aggregation ağırlıklı sorgularda bu node tipi büyük fayda sağlar.

# elasticsearch.yml - Coordinating Node konfigürasyonu
node.name: coord-node-01
node.roles: [ ]  # Boş bırakmak coordinating-only yapar
cluster.name: production-cluster
network.host: 0.0.0.0
discovery.seed_hosts: ["master-01", "master-02", "master-03"]
http.port: 9200

Ingest Node

Verinin Elasticsearch’e yazılmadan önce işlenmesini sağlar. Pipeline kullanarak field ekleme, dönüştürme, zenginleştirme gibi işlemler yapılabilir. Logstash’e hafif bir alternatif olarak düşünülebilir.

Shard Kavramı: Verinin Anatomisi

Shard, Elasticsearch’teki temel veri birimi ve aynı zamanda en çok yanlış anlaşılan kavramlardan biridir. Bir index oluşturduğunuzda Elasticsearch bu index’i bir veya birden fazla shard’a böler. Her shard aslında tam teşekküllü bir Lucene index’idir.

Primary ve Replica Shard’lar

Primary shard, verinin asıl kopyasının bulunduğu shard’dır. Yazma işlemleri her zaman primary shard’a gider.

Replica shard, primary shard’ın kopyasıdır. İki temel işlev görür: yüksek erişilebilirlik (primary fail olursa replica primary’ye terfi eder) ve okuma performansı (sorgular replica’lardan da karşılanabilir).

# Index oluştururken shard ve replica sayısını belirle
curl -X PUT "localhost:9200/urun-katalogu" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1
  },
  "mappings": {
    "properties": {
      "urun_adi": { "type": "text" },
      "fiyat": { "type": "float" },
      "kategori": { "type": "keyword" },
      "olusturma_tarihi": { "type": "date" }
    }
  }
}'

Yukarıdaki örnekte 3 primary + 3 replica = toplam 6 shard oluşur. Bu 6 shard cluster’daki node’lara dağıtılır. Önemli bir kural: Bir primary shard ile onun replica’sı aynı node üzerinde bulunamaz. Bu nedenle 1 replica ile çalışmak için en az 2 node gerekir.

Shard Boyutu: Kaç Shard Kullanmalıyım?

Bu soru sysadminlerin en çok kafasını karıştıran konulardan biridir. Elasticsearch ekibinin genel tavsiyesi şudur: Bir shard 10-50 GB arasında olmalıdır. Bu bir kural değil, pratikte işe yarayan bir kılavuzdur.

Çok fazla shard:

  • Cluster state boyutunu artırır, master node üzerindeki yükü artırır
  • Her sorgu daha fazla shard’a gitmek zorunda kalır, overhead artar
  • Küçük shard’lar segment merge işlemlerini verimsizleştirir

Çok az shard:

  • Yatay ölçeklenme kabiliyeti azalır
  • Büyük shard’lar recovery süresini uzatır
  • Tek bir shard birden fazla node’a dağıtılamaz, paralellik kaybolur
# Mevcut shard dağılımını gör
curl -X GET "localhost:9200/_cat/shards?v&pretty"

# Belirli bir index'in shard detaylarını gör
curl -X GET "localhost:9200/_cat/shards/urun-katalogu?v&pretty"

# Shard boyutlarını kontrol et
curl -X GET "localhost:9200/_cat/shards?v&h=index,shard,prirep,state,docs,store,node&pretty"

Shard Sayısını Sonradan Değiştiremezsiniz

Bu, Elasticsearch ile çalışırken öğrenilmesi gereken en önemli gerçeklerden biridir. Primary shard sayısı index oluşturulurken belirlenir ve sonradan değiştirilemez. Replica sayısı her zaman değiştirilebilir ama primary sayısı için ya index’i yeniden oluşturmanız ya da Reindex API’ı kullanmanız gerekir.

Bu yüzden başlangıçta doğru shard sayısını tahmin etmek kritiktir. Bunun için şu formül kullanılabilir:

Hedef shard boyutu 30 GB olsun, verinizin toplam büyümesi 1 yıl sonunda 300 GB olacaksa 300 / 30 = 10 primary shard mantıklıdır. Buna 1 replica eklerseniz toplam 20 shard olur ve bu 4-5 node arasında güzel dağılır.

Gerçek Dünya Senaryosu: E-Ticaret Log Cluster’ı

Bir e-ticaret platformu için Elasticsearch cluster’ı tasarladığımızı düşünelim. Günlük yaklaşık 50 GB log verisi geliyor, 3 ay boyunca aktif sorgulama yapılıyor, sonrasında arşivlenecek.

Cluster mimarisi:

  • 3 adet dedicated master node (2 core, 4 GB RAM)
  • 3 adet hot data node (8 core, 32 GB RAM, NVMe SSD)
  • 2 adet warm data node (4 core, 16 GB RAM, SATA SSD)
  • 2 adet coordinating node (4 core, 8 GB RAM, yük dengeleme için)
# ILM Policy oluştur
curl -X PUT "localhost:9200/_ilm/policy/eticaret-log-policy" -H 'Content-Type: application/json' -d'
{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {
            "max_primary_shard_size": "30gb",
            "max_age": "1d"
          },
          "set_priority": {
            "priority": 100
          }
        }
      },
      "warm": {
        "min_age": "7d",
        "actions": {
          "shrink": {
            "number_of_shards": 1
          },
          "forcemerge": {
            "max_num_segments": 1
          },
          "set_priority": {
            "priority": 50
          }
        }
      },
      "cold": {
        "min_age": "30d",
        "actions": {
          "freeze": {},
          "set_priority": {
            "priority": 0
          }
        }
      },
      "delete": {
        "min_age": "90d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}'
# Index template oluştur
curl -X PUT "localhost:9200/_index_template/eticaret-log-template" -H 'Content-Type: application/json' -d'
{
  "index_patterns": ["eticaret-log-*"],
  "template": {
    "settings": {
      "number_of_shards": 3,
      "number_of_replicas": 1,
      "index.lifecycle.name": "eticaret-log-policy",
      "index.routing.allocation.require._tier_preference": "data_hot",
      "index.refresh_interval": "30s"
    }
  }
}'

Bu yapıda günlük yaklaşık 50 GB veri 3 hot shard’a dağılır. Her shard ortalama 16-17 GB olur, bu ideal aralıktadır. 7 gün sonra warm’a taşınırken shrink action ile shard sayısı 1’e indirilir çünkü artık bu veriyi çok sık sorgulamıyoruz ve daha az shard yönetim kolaylığı sağlar.

Shard Allocation ve Rerouting

Shard’ların hangi node’lara dağıtılacağına master node karar verir. Ancak bu süreci allocation filtering ile kontrol edebilirsiniz.

# Belirli bir node'a shard atamayı engelle (bakım modu için)
curl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'
{
  "transient": {
    "cluster.routing.allocation.exclude._name": "data-node-03"
  }
}'

# Node bakım bittikten sonra kısıtlamayı kaldır
curl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'
{
  "transient": {
    "cluster.routing.allocation.exclude._name": null
  }
}'

# Unassigned shard varsa manuel reroute dene
curl -X POST "localhost:9200/_cluster/reroute?retry_failed=true"

Cluster’da unassigned shard gördüğünüzde paniklemeden önce nedenini anlamak gerekir. Bunun başlıca nedenleri şunlardır:

  • disk.watermark doluluk eşiklerine ulaşılmıştır, shard yeni node’lara atanmaz
  • Yeterli node yoktur (replica primary ile aynı node’a atanamaz)
  • Node bazında allocation filtering uygulanmaktadır
  • Node yeni başlamış ve henüz cluster’a tam katılmamıştır
# Disk watermark ayarlarını kontrol et ve gerekirse gevşet
curl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'
{
  "transient": {
    "cluster.routing.allocation.disk.watermark.low": "85%",
    "cluster.routing.allocation.disk.watermark.high": "90%",
    "cluster.routing.allocation.disk.watermark.flood_stage": "95%"
  }
}'

# Neden unassigned olduğunu açıklayan detaylı çıktı
curl -X GET "localhost:9200/_cluster/allocation/explain?pretty"

Node Boyutlandırma: Heap ve Bellek Yönetimi

Elasticsearch’in performansı büyük ölçüde JVM heap ayarına bağlıdır. Genel kural şudur: Heap boyutunu toplam RAM’in yarısına ayarlayın, ama 32 GB’ı geçmeyin. 32 GB eşiği JVM’in compressed object pointers (CompressedOops) özelliğiyle ilgilidir; bu eşiği geçince JVM bellek verimliliği dramatik şekilde düşer.

Kalan RAM ise Lucene’nin file system cache’i için bırakılır. Lucene yoğun biçimde OS page cache kullanır ve bu cache ne kadar büyükse sorgular o kadar hızlı döner.

# Node'un JVM bilgisini kontrol et
curl -X GET "localhost:9200/_nodes/stats/jvm?pretty" | grep -A5 "heap"

# Hot thread'leri gör (yüksek CPU durumunda)
curl -X GET "localhost:9200/_nodes/hot_threads"

# Node seviyesinde detaylı istatistikler
curl -X GET "localhost:9200/_nodes/stats?pretty&filter_path=nodes.*.name,nodes.*.jvm.mem,nodes.*.os.mem"

Prodüksiyonda mutlaka bootstrap.memory_lock: true ayarını yapın. Bu ayar JVM heap’inin swap’a yazılmasını engeller. Swap’a giren bir Elasticsearch node’u felaket derecesinde yavaşlar ve genellikle cluster’dan kopar.

# elasticsearch.yml
bootstrap.memory_lock: true

# /etc/security/limits.conf dosyasına ekle
elasticsearch soft memlock unlimited
elasticsearch hard memlock unlimited

# Systemd servisi için
# /etc/systemd/system/elasticsearch.service.d/override.conf
[Service]
LimitMEMLOCK=infinity

Cluster Monitoring ve Sağlık Kontrolü

Prodüksiyonda cluster sağlığını sürekli izlemek şarttır. Kibana’nın Stack Monitoring özelliği bu iş için biçilmiş kaftandır ama hızlı manuel kontrol için API yeterlidir.

# Genel sağlık durumu
curl -s "localhost:9200/_cluster/health?pretty"

# Index bazında shard durumu
curl -s "localhost:9200/_cat/indices?v&health=yellow"

# En büyük index'leri listele
curl -s "localhost:9200/_cat/indices?v&s=store.size:desc&h=index,docs.count,store.size,pri,rep"

# Node bazında disk kullanımı
curl -s "localhost:9200/_cat/allocation?v&pretty"

Özellikle şu metrikleri düzenli takip etmelisiniz:

  • JVM heap kullanımı: Sürekli yüzde 75’in üzerindeyse sorun vardır, GC baskısı artacaktır
  • Search latency: P99 gecikme değerleri normal baseline’ın 2-3 katına çıkıyorsa araştırın
  • Indexing rate: Ani düşüşler rejeksiyon veya disk doymasına işaret eder
  • Unassigned shard sayısı: Her zaman sıfır olmalı
  • Pending tasks: Master node’un işleyemediği cluster görevleri birikmemeli

Sonuç

Elasticsearch cluster mimarisi, doğru anlaşıldığında son derece esnek ve güçlü bir yapı sunar. Node rollerini ayrıştırmak, shard boyutlarını önceden planlamak ve ILM ile veri yaşam döngüsünü otomatize etmek; hem performans hem de maliyet açısından büyük fark yaratır.

Pratikte en çok yapılan hatalar şunlardır: çok fazla küçük shard oluşturmak, master node’u data rolüyle birlikte kullanmak, heap boyutunu 32 GB’ın üzerine çıkarmak ve shard sayısını index oluştururken düşünmeden varsayılan değerlerde bırakmak.

Bu yazıda ele aldığımız kavramları özümsedikten sonra bir adım ileri giderek cross-cluster replication, snapshot ve restore stratejileri ve security konfigürasyonu konularına geçmek Elasticsearch yönetimindeki bilginizi tamamlayacaktır. Cluster mimarisini bir kere doğru kurduğunuzda, üzerine inşa ettiğiniz her şeyin daha sağlam ve yönetilebilir olduğunu göreceksiniz.

Bir yanıt yazın

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