Elasticsearch Cluster Sağlığı İzleme ve Sorun Giderme
Elasticsearch cluster’ınız aniden yavaşladı, bazı shard’lar “unassigned” durumuna geçti ve uygulamalarınız timeout almaya başladı. Sabahın 3’ünde telefon çalıyor. Bu senaryoyu yaşamamak için cluster sağlığını proaktif izlemek ve sorun giderme adımlarını önceden bilmek şart. Bu yazıda Elasticsearch cluster sağlığını nasıl izleyeceğinizi, en sık karşılaşılan sorunları nasıl teşhis edeceğinizi ve bunları nasıl çözeceğinizi gerçek dünya senaryolarıyla ele alacağız.
Cluster Sağlık Durumu: Green, Yellow, Red
Elasticsearch cluster’ınızın genel sağlık durumu üç renk kodlu statüyle ifade edilir:
- Green: Tüm primary ve replica shard’lar atanmış ve çalışıyor. İdeal durum.
- Yellow: Tüm primary shard’lar atanmış fakat en az bir replica shard atanamamış. Veri kaybı riski yok ama redundancy eksik.
- Red: En az bir primary shard atanamamış. Veri kaybı riski var ve bazı sorgular başarısız olabilir.
Cluster sağlığını kontrol etmenin en temel yolu:
curl -X GET "http://localhost:9200/_cluster/health?pretty"
Çıktıda dikkat etmeniz gereken alanlar şunlar:
- status: green/yellow/red
- number_of_nodes: Cluster’daki toplam node sayısı
- number_of_data_nodes: Data node sayısı
- active_primary_shards: Aktif primary shard sayısı
- unassigned_shards: Atanamamış shard sayısı
- initializing_shards: Başlatılmakta olan shard sayısı
- relocating_shards: Taşınmakta olan shard sayısı
Belirli bir index’in sağlığını kontrol etmek için:
curl -X GET "http://localhost:9200/_cluster/health/my-index-2024?pretty"
Node Durumlarını İzleme
Cluster’daki tüm node’ların durumunu görmek için _cat API’si çok kullanışlıdır. Hem okunabilir hem de script içinde parse etmesi kolaydır.
# Tüm node'ları listele
curl -X GET "http://localhost:9200/_cat/nodes?v&h=name,ip,heap.percent,ram.percent,cpu,load_1m,load_5m,node.role,master"
# Node istatistiklerini detaylı al
curl -X GET "http://localhost:9200/_nodes/stats/jvm,process,fs?pretty"
Node rollerini anlamak önemli. Çıktıda node.role sütununda şunları görebilirsiniz:
- m: Master node
- d: Data node
- i: Ingest node
- c: Coordinating node
- r: Remote cluster client
- l: Machine learning node
Heap kullanımı %75 üzerine çıktığında alarm alın. %85 üzerinde ise JVM GC (Garbage Collection) pressure başlar ve ciddi performans sorunları yaşanır.
JVM Heap Pressure Tespiti
curl -X GET "http://localhost:9200/_nodes/stats/jvm?pretty" |
python3 -c "
import json, sys
data = json.load(sys.stdin)
for node_id, node in data['nodes'].items():
name = node['name']
used = node['jvm']['mem']['heap_used_percent']
print(f'{name}: Heap kullanim %{used}')
"
Heap basıncını gerçek zamanlı izlemek için basit bir bash script yazabilirsiniz:
#!/bin/bash
# es_heap_monitor.sh
THRESHOLD=80
ES_HOST="http://localhost:9200"
while true; do
RESPONSE=$(curl -s "$ES_HOST/_nodes/stats/jvm")
echo "$RESPONSE" | python3 -c "
import json, sys
from datetime import datetime
data = json.load(sys.stdin)
for node_id, node in data['nodes'].items():
name = node['name']
used = node['jvm']['mem']['heap_used_percent']
if used > $THRESHOLD:
print(f'[UYARI] {datetime.now()} - {name}: Heap %{used} - Esik degeri asildi!')
else:
print(f'[OK] {name}: Heap %{used}')
"
sleep 30
done
Shard Sorunlarını Teşhis Etme
Unassigned shard’lar en sık karşılaşılan ve en sinir bozucu sorunlardan biridir. Bunları tespit etmek için:
# Unassigned shard'ları listele
curl -X GET "http://localhost:9200/_cat/shards?v&h=index,shard,prirep,state,unassigned.reason,node" | grep UNASSIGNED
# Neden atanamamadığını anlamak için explain API'sini kullan
curl -X GET "http://localhost:9200/_cluster/allocation/explain?pretty" -H 'Content-Type: application/json' -d '
{
"index": "my-problematic-index",
"shard": 0,
"primary": true
}'
explain API’sinin çıktısı size tam olarak neden shard’ın atanamadığını söyler. Sık karşılaşılan sebepler:
- NODE_LEFT: Shard’ın bulunduğu node cluster’dan ayrıldı
- ALLOCATION_FAILED: Disk doluluk ya da başka bir kısıtlama nedeniyle atama başarısız
- INDEX_CREATED: Yeni index oluşturuldu, henüz atanmadı
- REINITIALIZED: Shard yeniden başlatılıyor
Disk Kullanımı Kısıtlamaları
Elasticsearch, disk doluluk oranına göre shard atamayı durdurabilir. Varsayılan eşikler şunlardır:
- %85: Disk watermark low – yeni shard ataması durdurulur
- %90: Disk watermark high – mevcut shard’lar başka node’a taşınır
- %95: Disk watermark flood stage – index read-only moduna alınır
Disk durumunu kontrol edin:
curl -X GET "http://localhost:9200/_cat/allocation?v&h=node,disk.used,disk.avail,disk.percent,shards"
Eğer bir index read-only moduna girdiyse, disk sorunu çözüldükten sonra şu komutla tekrar yazılabilir hale getirebilirsiniz:
curl -X PUT "http://localhost:9200/my-index/_settings"
-H 'Content-Type: application/json'
-d '{"index.blocks.read_only_allow_delete": null}'
Geçici olarak watermark değerlerini yükseltmek de bir çözüm olabilir (kalıcı çözüm değil, sadece acil durum için):
curl -X PUT "http://localhost:9200/_cluster/settings"
-H 'Content-Type: application/json'
-d '{
"transient": {
"cluster.routing.allocation.disk.watermark.low": "90%",
"cluster.routing.allocation.disk.watermark.high": "95%",
"cluster.routing.allocation.disk.flood_stage": "97%"
}
}'
Index Performansını İzleme
Yavaş sorgular mı yaşıyorsunuz? Slowlog aktif hale getirilerek hangi sorguların yavaş çalıştığını tespit edebilirsiniz.
# Belirli bir index için slowlog ayarla
curl -X PUT "http://localhost:9200/my-index/_settings"
-H 'Content-Type: application/json'
-d '{
"index.search.slowlog.threshold.query.warn": "10s",
"index.search.slowlog.threshold.query.info": "5s",
"index.search.slowlog.threshold.query.debug": "2s",
"index.search.slowlog.threshold.fetch.warn": "1s",
"index.search.slowlog.level": "info"
}'
Slowlog dosyaları genellikle şu konumdadır:
/var/log/elasticsearch/{cluster-name}_index_search_slowlog.json
Index istatistiklerini düzenli olarak kontrol edin:
# Index bazında sorgu ve index istatistikleri
curl -X GET "http://localhost:9200/_stats/search,indexing,merges?pretty" |
python3 -c "
import json, sys
data = json.load(sys.stdin)
for index, stats in data['indices'].items():
search = stats['total']['search']
indexing = stats['total']['indexing']
print(f'Index: {index}')
print(f' Toplam sorgu: {search["query_total"]}')
print(f' Sorgu zamani (ms): {search["query_time_in_millis"]}')
print(f' Index edilen doc: {indexing["index_total"]}')
print()
"
Gerçek Dünya Senaryosu: Split-Brain Problemi
Split-brain, distributed sistemlerin kabusu. Elasticsearch’te master node seçimi bozulduğunda iki ayrı “cluster” oluşabilir ve veri tutarsızlığına yol açabilir.
Bu sorunu önlemek için minimum_master_nodes ayarı kritik öneme sahiptir. Formül şudur: (toplam_master_eligible_node / 2) + 1
Örneğin 3 master-eligible node’unuz varsa bu değer 2 olmalıdır.
# Mevcut master election ayarlarını kontrol et
curl -X GET "http://localhost:9200/_cluster/settings?pretty"
# Elasticsearch 7.x ve sonrası için voting configuration kontrol
curl -X GET "http://localhost:9200/_cluster/voting_config_exclusions"
elasticsearch.yml içinde bu ayarı yapılandırın:
# Elasticsearch 7.x öncesi için
discovery.zen.minimum_master_nodes: 2
# Elasticsearch 7.x ve sonrası (yeni discovery mekanizması)
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
discovery.seed_hosts: ["10.0.0.1:9300", "10.0.0.2:9300", "10.0.0.3:9300"]
Mevcut master node’u kontrol edin:
curl -X GET "http://localhost:9200/_cat/master?v"
Gerçek Dünya Senaryosu: Segment Merge Sorunu
Büyük miktarda veri yazan sistemlerde segment sayısı çok artabilir. Bu hem disk alanı hem de sorgu performansını etkiler. Force merge işlemi bunu çözebilir ancak dikkatli kullanılmalıdır, çünkü çok kaynak tüketir.
# Segment istatistiklerini kontrol et
curl -X GET "http://localhost:9200/_cat/segments?v&h=index,shard,segment,size,docs.count,generation"
# Belirli bir index için force merge (production'da dikkatli kullanın!)
curl -X POST "http://localhost:9200/my-old-index/_forcemerge?max_num_segments=1"
# Force merge işlemi durumunu takip et
curl -X GET "http://localhost:9200/_cat/tasks?v&h=action,running_time,node" | grep merge
Aktif index’lerde force merge yapmaktan kaçının. Sadece artık yazılmayan (frozen/closed) index’lerde tercih edin.
Monitoring Scripti: Kapsamlı Sağlık Raporu
Tüm bu kontrolleri bir araya getiren bir bash scripti işinizi çok kolaylaştırır:
#!/bin/bash
# es_health_report.sh
ES_HOST="${1:-http://localhost:9200}"
RED='33[0;31m'
YELLOW='33[1;33m'
GREEN='33[0;32m'
NC='33[0m'
echo "========================================"
echo "Elasticsearch Saglik Raporu"
echo "Zaman: $(date)"
echo "Host: $ES_HOST"
echo "========================================"
# Cluster health
echo -e "n[CLUSTER SAGLIK]"
HEALTH=$(curl -s "$ES_HOST/_cluster/health")
STATUS=$(echo $HEALTH | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['status'])")
NODES=$(echo $HEALTH | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['number_of_nodes'])")
UNASSIGNED=$(echo $HEALTH | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['unassigned_shards'])")
if [ "$STATUS" = "green" ]; then
echo -e "Durum: ${GREEN}GREEN${NC}"
elif [ "$STATUS" = "yellow" ]; then
echo -e "Durum: ${YELLOW}YELLOW${NC}"
else
echo -e "Durum: ${RED}RED${NC}"
fi
echo "Node sayisi: $NODES"
echo "Atanmamis shard: $UNASSIGNED"
# Node heap
echo -e "n[NODE HEAP KULLANIMI]"
curl -s "$ES_HOST/_cat/nodes?v&h=name,heap.percent,ram.percent,cpu,load_1m" | while IFS= read -r line; do
if echo "$line" | grep -qE "^[0-9]|name"; then
echo "$line"
fi
done
# Disk kullanimi
echo -e "n[DISK KULLANIMI]"
curl -s "$ES_HOST/_cat/allocation?v&h=node,disk.used,disk.avail,disk.percent,shards"
# Red indeksler
echo -e "n[SORUNLU INDEKSLER]"
curl -s "$ES_HOST/_cat/indices?v&h=health,status,index,docs.count,store.size" | grep -E "^red|^yellow" | head -20
echo -e "n========================================"
echo "Rapor tamamlandi."
echo "========================================"
Bu scripti cron ile her 5 dakikada çalıştırıp çıktıyı log dosyasına yönlendirin:
chmod +x es_health_report.sh
echo "*/5 * * * * /opt/scripts/es_health_report.sh >> /var/log/es_health.log 2>&1" | crontab -
Snapshot ile Yedekleme Durumunu Kontrol Etme
Sorun gidermenin bir parçası da düzenli yedeklerin alındığından emin olmaktır. Repository ve snapshot durumunu kontrol edin:
# Kayıtlı snapshot repository'lerini listele
curl -X GET "http://localhost:9200/_snapshot?pretty"
# Belirli repository'deki snapshot'ları listele
curl -X GET "http://localhost:9200/_snapshot/my_backup_repo/_all?pretty"
# En son snapshot'ın durumunu kontrol et
curl -X GET "http://localhost:9200/_snapshot/my_backup_repo/_current?pretty"
# Snapshot oluşturma durumu
curl -X GET "http://localhost:9200/_snapshot/_status?pretty"
Snapshot çıktısında state alanı SUCCESS değilse yedekleme sürecinizde sorun var demektir. PARTIAL durumu bazı shard’ların yedeklenemediğini gösterir.
Elasticsearch Log Analizi
/var/log/elasticsearch/ dizinindeki loglar sorun gidermede birincil kaynağınızdır.
# Son 1 saatteki WARN ve ERROR loglarını filtrele
grep -E "WARN|ERROR" /var/log/elasticsearch/my-cluster.log |
awk -v d="$(date -d '1 hour ago' '+%Y-%m-%dT%H:%M')" '$0 > d' |
tail -50
# OutOfMemory hatalarını ara
grep "OutOfMemoryError" /var/log/elasticsearch/my-cluster.log
# Circuit breaker hatalarını ara
grep "CircuitBreakingException" /var/log/elasticsearch/my-cluster.log | tail -20
Circuit breaker hataları alıyorsanız, JVM heap’i artırmayı veya indices.breaker.total.limit değerini düzenlemeyi düşünün:
curl -X PUT "http://localhost:9200/_cluster/settings"
-H 'Content-Type: application/json'
-d '{
"persistent": {
"indices.breaker.total.limit": "70%",
"indices.breaker.request.limit": "40%",
"indices.breaker.fielddata.limit": "40%"
}
}'
Performans Sorunlarında Kontrol Listesi
Genel yavaşlık şikayeti aldığınızda sırayla kontrol etmeniz gerekenler:
- Heap kullanımı:
_nodes/stats/jvmile kontrol edin. %85 üzeriyse JVM GC sorun yaratıyordur - Thread pool rejectları:
curl -s "localhost:9200/_cat/thread_pool?v"ile search ve write thread pool’larını kontrol edin. Yüksekrejectedsayısı kaynak yetersizliğine işaret eder - Field data kullanımı: Text field’lar üzerinde aggregation yapıyorsanız bu çok bellek tüketir.
_nodes/stats/indices/fielddataile kontrol edin - Shard sayısı: Küçük index’ler için çok fazla shard performansı düşürür. Index başına 1-2 shard yeterli olabilir
- Merge işlemleri: Aktif merge işlemleri sistemi yavaşlatabilir.
_cat/tasksile takip edin - Network gecikmeleri: Node’lar arası iletişim sorunları için
_nodes/stats/transportincelenebilir
Sonuç
Elasticsearch cluster sağlığını izlemek reaktif değil, proaktif bir yaklaşım gerektiriyor. _cluster/health, _cat/nodes, _nodes/stats gibi API’leri düzenli sorgulayan monitoring script’leri kurmak, sorunları sabah 3’te uyandırmadan önce tespit etmenizi sağlar.
En önemli pratik öneriler şunlar: Heap kullanımı için %75 alarm eşiği belirleyin, disk doluluk için watermark değerlerini proaktif takip edin, unassigned shard’lar için explain API’sini kullanmaktan çekinmeyin ve slowlog’u aktif tutun. Split-brain gibi ciddi sorunlar için ise cluster konfigürasyonunuzu doğru yapmak en büyük güvenceniz olacak.
Buradaki script’leri ve komutları kendi ortamınıza adapte ederek bir runbook oluşturmanızı tavsiye ederim. Sorun çıktığında paniklemek yerine adım adım kontrol listesini takip etmek hem süreyi kısaltır hem de hata yapma olasılığını azaltır. Elasticsearch’in bu kadar detaylı API sağlaması, aslında çok şeffaf bir sistem olduğunun göstergesi. Sadece doğru soruları sormayı bilmek yeterli.
