Elasticsearch Cluster Kurulumu ve Node Yönetimi

Üç node’dan oluşan bir Elasticsearch cluster’ı ayağa kaldırmak kulağa basit gelir. Ama production ortamında bunu ilk kez yapıyorsanız, split-brain senaryolarıyla, yanlış yapılandırılmış discovery ayarlarıyla ya da JVM heap boyutu yüzünden performans sorunlarıyla karşılaşma ihtimaliniz oldukça yüksek. Bu yazıda sıfırdan bir Elasticsearch cluster’ı nasıl kurduğumu, node yönetimini nasıl yaptığımı ve bu süreçte öğrendiğim dersleri paylaşacağım.

Ortam Hazırlığı ve Gereksinimler

Başlamadan önce şunu söylemeliyim: Elasticsearch, düzgün çalışması için oldukça titiz bir yazılım. Sistem seviyesinde bazı ayarlar yapılmadan cluster stabil olmaz. Bunları atlamak “şimdilik çalışıyor” hissini verir ama production’da başınızı ağrıtır.

Kullandığım ortam:

  • 3 adet CentOS 8 / RHEL 8 sunucu (minimum 8GB RAM, 4 vCPU)
  • Elasticsearch 8.x
  • Her sunucuya statik IP atanmış durumda
  • node1: 192.168.10.11
  • node2: 192.168.10.12
  • node3: 192.168.10.13

İlk yapılacak şey işletim sistemi seviyesindeki ayarlar. Bu adımı her üç node’da da uygulayın:

# Swap'ı devre dışı bırakıyoruz - Elasticsearch için kritik
swapoff -a
sed -i '/ swap / s/^(.*)$/#1/g' /etc/fstab

# vm.max_map_count ayarı - Elasticsearch bu değeri kontrol eder
sysctl -w vm.max_map_count=262144
echo "vm.max_map_count=262144" >> /etc/sysctl.conf

# Dosya descriptor limitlerini artırıyoruz
cat >> /etc/security/limits.conf << EOF
elasticsearch soft nofile 65535
elasticsearch hard nofile 65535
elasticsearch soft nproc 4096
elasticsearch hard nproc 4096
EOF

# Systemd için de aynı limitleri set ediyoruz
mkdir -p /etc/systemd/system/elasticsearch.service.d
cat > /etc/systemd/system/elasticsearch.service.d/override.conf << EOF
[Service]
LimitNOFILE=65535
LimitNPROC=4096
EOF

Bu ayarları yapmadan kuruluma devam etmeyin. vm.max_map_count değeri düşük olduğunda Elasticsearch başlangıçta hata verir ve log’larda bunu açıkça söyler. Ama nofile limiti yüksek trafik altında sessiz sedasız sorun çıkarabilir.

Elasticsearch Kurulumu

Her üç node’da kurulumu gerçekleştiriyoruz. RPM repository’yi ekleyip kurulum yapacağız:

# Elastic repository'yi ekliyoruz
rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch

cat > /etc/yum.repos.d/elasticsearch.repo << EOF
[elasticsearch]
name=Elasticsearch repository for 8.x packages
baseurl=https://artifacts.elastic.co/packages/8.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=0
autorefresh=1
type=rpm-md
EOF

# Kurulum
dnf install --enablerepo=elasticsearch elasticsearch -y

# Servisi enable ediyoruz ama henüz başlatmıyoruz
systemctl daemon-reload
systemctl enable elasticsearch

Kurulum tamamlandıktan sonra yapılandırma dosyasına geçelim.

Node Yapılandırması

Burada asıl iş başlıyor. Her node için farklı elasticsearch.yml yapılandırması oluşturacağız. Önce node1 için:

# /etc/elasticsearch/elasticsearch.yml - NODE 1

# Cluster adı - tüm node'larda aynı olmalı
cluster.name: production-logs

# Bu node'un adı
node.name: es-node-1

# Node rolleri - master ve data rolleri birlikte
node.roles: [master, data, ingest]

# Ağ ayarları
network.host: 192.168.10.11
http.port: 9200
transport.port: 9300

# Discovery - diğer node'ların adresleri
discovery.seed_hosts:
  - 192.168.10.11:9300
  - 192.168.10.12:9300
  - 192.168.10.13:9300

# İlk cluster oluşturulurken master olabilecek node'lar
cluster.initial_master_nodes:
  - es-node-1
  - es-node-2
  - es-node-3

# Path ayarları
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch

# Güvenlik ayarları (8.x'te varsayılan açık geliyor)
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: elastic-certificates.p12

Node2 ve node3 için sadece node.name ve network.host değerlerini değiştirmeniz yeterli.

Önemli not: cluster.initial_master_nodes ayarı yalnızca cluster ilk kez oluşturulurken kullanılır. Bir kez cluster ayağa kalktıktan sonra bu satırı kaldırın ya da yoruma alın. Aksi takdirde bir node yeniden başlatıldığında cluster split-brain durumuna girebilir.

SSL/TLS Sertifikaları

Elasticsearch 8.x ile güvenlik varsayılan olarak açık geliyor. Sertifikaları oluşturup tüm node’lara dağıtmamız gerekiyor. Bu işlemi node1’de yapıp diğerlerine kopyalayacağız:

# Önce CA oluşturuyoruz
/usr/share/elasticsearch/bin/elasticsearch-certutil ca 
  --out /etc/elasticsearch/elastic-ca.p12 
  --pass ""

# Sertifikaları oluşturuyoruz
/usr/share/elasticsearch/bin/elasticsearch-certutil cert 
  --ca /etc/elasticsearch/elastic-ca.p12 
  --ca-pass "" 
  --out /etc/elasticsearch/elastic-certificates.p12 
  --pass ""

# Sertifikaları diğer node'lara kopyalıyoruz
scp /etc/elasticsearch/elastic-certificates.p12 [email protected]:/etc/elasticsearch/
scp /etc/elasticsearch/elastic-certificates.p12 [email protected]:/etc/elasticsearch/

# İzinleri düzenliyoruz (tüm node'larda)
chown elasticsearch:elasticsearch /etc/elasticsearch/elastic-certificates.p12
chmod 660 /etc/elasticsearch/elastic-certificates.p12

Sertifikaları oluştururken boş passphrase kullandım. Production ortamında passphrase kullanmak isteyebilirsiniz ama o zaman keystore’a da eklemeniz gerekiyor. Basitlik adına burada boş bıraktım.

JVM Heap Boyutu Ayarı

Bu belki de en çok göz ardı edilen ayar. JVM heap için sisteminizin toplam RAM’inin yarısını verin, ama 31GB’ı geçmeyin. 31GB sınırının özel bir önemi var: JVM, 32GB’ın altındaki heap’ler için compressed ordinary object pointers (OOPs) kullanıyor ve bu performansı önemli ölçüde artırıyor.

# /etc/elasticsearch/jvm.options.d/heap.options dosyası oluşturuyoruz
cat > /etc/elasticsearch/jvm.options.d/heap.options << EOF
# 8GB RAM'li sunucu için 4GB heap
-Xms4g
-Xmx4g
EOF

Xms ve Xmx değerlerini her zaman eşit tutun. Farklı değer verirseniz JVM sürekli heap yeniden boyutlandırma yapacak ve ciddi performans kayıpları yaşarsınız.

Cluster’ı Ayağa Kaldırmak

Her şey hazır olduğunda servisleri başlatıyoruz. Sırayla yapın ve her node’un cluster’a katıldığını doğrulayın:

# Node1'de başlatıyoruz
systemctl start elasticsearch

# Log'ları takip ediyoruz
journalctl -u elasticsearch -f

# Node2'ye geçip başlatıyoruz
systemctl start elasticsearch

# Node3'te de aynısını yapıyoruz
systemctl start elasticsearch

# Cluster durumunu kontrol ediyoruz
curl -X GET "https://192.168.10.11:9200/_cluster/health?pretty" 
  -u elastic:changeme 
  --cacert /etc/elasticsearch/elastic-ca.pem

Cluster sağlıklıysa status alanında green görmeniz lazım. yellow genellikle replica shard’ların atanamadığı anlamına gelir ki tek node’lu bir cluster’da bu normaldir. Ama 3 node’lu bir cluster’da yellow görüyorsanız bir sorun var demektir.

Node Rolleri ve Dedicated Node Mimarisi

Küçük cluster’larda her node hem master hem data rolü üstlenebilir. Ama veri boyutu büyüdükçe ve cluster kritikleştikçe dedicated node mimarisine geçmek mantıklı. Burada farklı senaryoları ele alalım.

Dedicated master node yapılandırması:

# Dedicated master node için
node.roles: [master]

# Bu node veri tutmayacak, sadece cluster koordinasyonunu yapacak
# En az 3 dedicated master node olmalı (quorum için)

Dedicated data node:

# Sadece veri tutan node
node.roles: [data, data_hot, data_warm, data_cold]

Coordinating only node (load balancer görevi görür, veri tutmaz, master olmaz):

# Boş bırakırsanız coordinating only olur
node.roles: []

Büyük log analizi ortamlarında tipik bir mimari şöyle olur: 3 dedicated master node, 5-10 data node ve önünde load balancer görevi yapan 2 coordinating node. Logstash doğrudan coordinating node’lara bağlanır, bu şekilde veri node’larına direkt yük bindirmemiş olursunuz.

ILM (Index Lifecycle Management) ile Hot-Warm-Cold Mimarisi

Log yönetiminde en sık karşılaştığım ihtiyaç: eski log’ları ucuz depolamaya taşımak. ILM bu işi otomatikleştiriyor.

# ILM policy oluşturuyoruz
curl -X PUT "https://192.168.10.11:9200/_ilm/policy/logs-policy?pretty" 
  -u elastic:changeme 
  -H 'Content-Type: application/json' 
  -d '{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {
            "max_primary_shard_size": "50gb",
            "max_age": "7d"
          },
          "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": {}
        }
      }
    }
  }
}'

Bu policy ile: 7 günlük log’lar hot tier’da tutulur, 7-30 gün arası warm’a geçer (daha az performanslı ama daha ucuz diskler), 30-90 gün arası cold’da freeze edilir ve 90 günden eski log’lar silinir.

Cluster Sağlık Monitöringi

Cluster’ı kurduğunuzda izleme mekanizmalarını da hazırlamalısınız. Sadece Kibana’ya bakmak yetmez, scriptler yazın ve alerting kurun.

#!/bin/bash
# elasticsearch-health-check.sh
# Cron'a ekleyin: */5 * * * * /opt/scripts/elasticsearch-health-check.sh

ES_HOST="https://192.168.10.11:9200"
ES_USER="elastic"
ES_PASS="changeme"
ALERT_EMAIL="[email protected]"

HEALTH=$(curl -s -X GET "${ES_HOST}/_cluster/health" 
  -u "${ES_USER}:${ES_PASS}" 
  --cacert /etc/elasticsearch/elastic-ca.pem | 
  python3 -c "import sys,json; data=json.load(sys.stdin); print(data['status'])")

NODE_COUNT=$(curl -s -X GET "${ES_HOST}/_cluster/health" 
  -u "${ES_USER}:${ES_PASS}" 
  --cacert /etc/elasticsearch/elastic-ca.pem | 
  python3 -c "import sys,json; data=json.load(sys.stdin); print(data['number_of_nodes'])")

if [ "$HEALTH" != "green" ]; then
  echo "ALERT: Elasticsearch cluster status is ${HEALTH}" | 
    mail -s "ES Cluster Health Alert" $ALERT_EMAIL
fi

if [ "$NODE_COUNT" -lt "3" ]; then
  echo "ALERT: Only ${NODE_COUNT} nodes in cluster, expected 3" | 
    mail -s "ES Node Count Alert" $ALERT_EMAIL
fi

echo "$(date) - Cluster status: ${HEALTH}, Nodes: ${NODE_COUNT}" >> 
  /var/log/es-health.log

Node’u Güvenli Şekilde Cluster’dan Çıkarmak

Bir node’u bakım için kapatacaksanız bunu doğru yapmanız gerekiyor. Direkt systemctl stop elasticsearch yaparsanız shard reallocation başlar ve cluster gereksiz yere yük biner.

# Önce shard allocation'ı bu node için devre dışı bırakıyoruz
curl -X PUT "https://192.168.10.11:9200/_cluster/settings?pretty" 
  -u elastic:changeme 
  -H 'Content-Type: application/json' 
  -d '{
  "persistent": {
    "cluster.routing.allocation.exclude._ip": "192.168.10.12"
  }
}'

# Shard'ların taşınmasını bekliyoruz
# Bu komutu shard sayısı 0 olana kadar çalıştırın
curl -s "https://192.168.10.11:9200/_cat/shards?v" 
  -u elastic:changeme 
  --cacert /etc/elasticsearch/elastic-ca.pem | grep "192.168.10.12"

# Shard'lar taşındıktan sonra node'u kapatıyoruz
ssh 192.168.10.12 "systemctl stop elasticsearch"

# Bakım tamamlandıktan sonra node'u tekrar cluster'a alıyoruz
curl -X PUT "https://192.168.10.11:9200/_cluster/settings?pretty" 
  -u elastic:changeme 
  -H 'Content-Type: application/json' 
  -d '{
  "persistent": {
    "cluster.routing.allocation.exclude._ip": null
  }
}'

Bu sırayı takip etmediğinizde ne olur? Birkaç yüz GB’lık bir index’in shard’ları aniden başka node’lara kopyalanmaya başlar. Hem network’ü hem de disk I/O’yu bunaltır. 3 node’lu bir cluster’da bunu yaşadım, recovery 4 saat sürdü.

Shard Boyutu ve Sayısı Optimizasyonu

Yanlış shard stratejisi cluster performansını ciddi etkiler. Elastic’in önerisi: her shard 10-50GB arasında olsun. Çok küçük shard’lar (birkaç MB) overhead yaratır, çok büyük shard’lar ise recovery süresini uzatır.

# Mevcut shard durumunu kontrol ediyoruz
curl -X GET "https://192.168.10.11:9200/_cat/shards?v&h=index,shard,prirep,state,docs,store,node" 
  -u elastic:changeme 
  --cacert /etc/elasticsearch/elastic-ca.pem | sort -k6 -hr | head -20

# Bir index'in shard sayısını öğreniyoruz
curl -X GET "https://192.168.10.11:9200/_cat/indices/logs-*?v&h=index,pri,rep,docs.count,store.size" 
  -u elastic:changeme 
  --cacert /etc/elasticsearch/elastic-ca.pem

# Index template ile yeni index'ler için varsayılan shard sayısını ayarlıyoruz
curl -X PUT "https://192.168.10.11:9200/_index_template/logs-template?pretty" 
  -u elastic:changeme 
  -H 'Content-Type: application/json' 
  -d '{
  "index_patterns": ["logs-*"],
  "template": {
    "settings": {
      "number_of_shards": 3,
      "number_of_replicas": 1,
      "refresh_interval": "30s"
    }
  },
  "priority": 100
}'

refresh_interval ayarına dikkat edin. Varsayılan 1 saniyedir ve arama için gerekli ama log ingest ederken bu değeri artırmak yazma performansını dramatik şekilde artırır. Logstash ile bulk indexing yapıyorsanız 30s hatta 60s bile makul olabilir.

Yaygın Sorunlar ve Çözümleri

Gerçek hayatta en çok karşılaştığım sorunları özetleyeyim:

Unassigned shards sorunu: Cluster sarı ya da kırmızı duruma düştüğünde ilk bakacağınız yer:

# Neden atanmamış shard var, görelim
curl -X GET "https://192.168.10.11:9200/_cluster/allocation/explain?pretty" 
  -u elastic:changeme 
  --cacert /etc/elasticsearch/elastic-ca.pem

Bu endpoint size “neden bu shard atanmıyor” sorusunun cevabını açıkça verir. Disk dolduğu için mi, node uygun olmadığı için mi, replica sayısı node sayısını geçtiği için mi, hepsini söyler.

Disk doluluk eşiği: Elasticsearch varsayılan olarak disk %85 dolduğunda yeni shard atamayı durdurur, %90’da index’e yazmayı keser:

# Disk eşiklerini geçici olarak ayarlayabilirsiniz
curl -X PUT "https://192.168.10.11:9200/_cluster/settings" 
  -u elastic:changeme 
  -H 'Content-Type: application/json' 
  -d '{
  "persistent": {
    "cluster.routing.allocation.disk.watermark.low": "90%",
    "cluster.routing.allocation.disk.watermark.high": "95%",
    "cluster.routing.allocation.disk.watermark.flood_stage": "97%"
  }
}'

Bu değerleri kalıcı olarak gevşetmek yerine disk sorununu çözün. Ama acil müdahale için işe yarar.

Snapshot ile Yedekleme

Production Elasticsearch cluster’ında yedekleme şart. Snapshot repository kurulumu:

# NFS mount varsayarak filesystem repository ekliyoruz
# /etc/elasticsearch/elasticsearch.yml'e şu satırı ekleyin:
# path.repo: ["/mnt/elasticsearch-snapshots"]

# Repository oluşturuyoruz
curl -X PUT "https://192.168.10.11:9200/_snapshot/my_backup?pretty" 
  -u elastic:changeme 
  -H 'Content-Type: application/json' 
  -d '{
  "type": "fs",
  "settings": {
    "location": "/mnt/elasticsearch-snapshots",
    "compress": true,
    "max_snapshot_bytes_per_sec": "50mb",
    "max_restore_bytes_per_sec": "50mb"
  }
}'

# Manuel snapshot alıyoruz
curl -X PUT "https://192.168.10.11:9200/_snapshot/my_backup/snapshot_$(date +%Y%m%d)?wait_for_completion=true&pretty" 
  -u elastic:changeme 
  --cacert /etc/elasticsearch/elastic-ca.pem

Snapshot’ları SLM (Snapshot Lifecycle Management) ile otomatikleştirmenizi öneririm. Kibana arayüzünden de yapabilirsiniz ama API ile yapılandırmak daha tekrarlanabilir ve versiyon kontrolüne alınabilir bir yaklaşım.

Sonuç

Elasticsearch cluster kurulumu ve yönetimi, sistemi ayağa kaldırmaktan çok onu stabil tutmakla ilgili. Swap kapatmak, JVM heap’ini doğru boyutlandırmak, shard stratejisini düşünmek, ILM kurmak ve yedekleme mekanizması oluşturmak: bunların hepsi kurulum günü yapılması gereken şeyler, sonraya bırakılan şeyler değil.

Burada anlattığım 3 node’lu yapı pek çok kurum için makul bir başlangıç noktası. Veriniz büyüdükçe dedicated master node’lara geçin, hot-warm-cold mimarisini devreye alın. Elastic’in kendi dokümanları güçlü ama bazen teoriden pratiğe geçişte boşluklar bırakıyor. Umarım bu yazı o boşlukların bir kısmını kapatmıştır.

Sorunuz olursa ya da farklı senaryolarla karşılaştıysanız yorumlarda paylaşın, deneyimlerimizi birleştirelim.

Bir yanıt yazın

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