OpenSearch: AWS’nin ELK Stack Alternatifi
Elastic şirketinin 2021’de lisans değişikliğine gitmesiyle birlikte, pek çok organizasyonda “şimdi ne yapacağız?” sorusu gündeme geldi. Özellikle üretim ortamlarında Elasticsearch ve Kibana kullanan ekipler için bu gerçek bir karar anıydı. AWS’nin bu duruma verdiği yanıt OpenSearch oldu. Ama mesele sadece “lisans değişti, fork ettiler” kadar basit değil. OpenSearch, zamanla kendi ekosistemini oluşturan, bazı konularda ELK’ı geride bırakan, bazı konularda ise hâlâ yetişmeye çalışan bir proje haline geldi. Bu yazıda hem teorik hem de pratik açıdan OpenSearch’ü ele alacağız.
OpenSearch Nedir ve Nereden Gelir?
Elasticsearch 7.10.2, Elastic’in SSPL (Server Side Public License) lisansına geçmeden önceki son Apache 2.0 sürümüydü. AWS bu sürümü fork alarak OpenSearch projesini başlattı ve 2021 yılının ortasında ilk kararlı sürümü yayınladı. Kibana’nın fork’u ise OpenSearch Dashboards adını aldı.
Bugün OpenSearch, Amazon tarafından değil, OpenSearch Software Foundation çatısı altında yönetiliyor. Bu önemli bir ayrım çünkü projenin uzun vadeli sürdürülebilirliği açısından vendor lock-in kaygılarını bir ölçüde azaltıyor.
OpenSearch’ün ELK Stack ile karşılaştırıldığında öne çıkan temel farkları şöyle sıralayabiliriz:
- Lisans: OpenSearch tamamen Apache 2.0 lisanslıdır, ticari kısıtlama yoktur
- Güvenlik eklentisi: ELK’ta X-Pack gerektiren pek çok güvenlik özelliği OpenSearch’te ücretsiz gelir
- ML Commons: Makine öğrenmesi özellikleri community sürümünde mevcut
- k-NN search: Vektör arama desteği açık kaynak olarak sunuluyor
- Kibana uyumluluğu: OpenSearch Dashboards, Kibana 7.10.2 tabanlıdır ama artık bağımsız bir yol izliyor
Kurulum: Docker Compose ile Hızlı Başlangıç
Prod ortamına geçmeden önce yerel ortamda ayağa kaldırmak için Docker Compose kullanmak en pratik yol. OpenSearch, single-node kurulumda memory lock için bazı sistem ayarları istiyor.
Önce sistem parametrelerini ayarlayalım:
# vm.max_map_count ayarı - bu olmadan OpenSearch başlamaz
sudo sysctl -w vm.max_map_count=262144
# Kalıcı hale getirmek için
echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf
# ulimit ayarları
sudo sh -c 'echo "opensearch soft nofile 65536" >> /etc/security/limits.conf'
sudo sh -c 'echo "opensearch hard nofile 65536" >> /etc/security/limits.conf'
Şimdi docker-compose.yml dosyasını oluşturalım:
cat << 'EOF' > docker-compose.yml
version: '3'
services:
opensearch-node1:
image: opensearchproject/opensearch:2.11.0
container_name: opensearch-node1
environment:
- cluster.name=opensearch-cluster
- node.name=opensearch-node1
- discovery.seed_hosts=opensearch-node1,opensearch-node2
- cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2
- bootstrap.memory_lock=true
- "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
- OPENSEARCH_INITIAL_ADMIN_PASSWORD=Admin_password_1234!
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
volumes:
- opensearch-data1:/usr/share/opensearch/data
ports:
- 9200:9200
- 9600:9600
networks:
- opensearch-net
opensearch-node2:
image: opensearchproject/opensearch:2.11.0
container_name: opensearch-node2
environment:
- cluster.name=opensearch-cluster
- node.name=opensearch-node2
- discovery.seed_hosts=opensearch-node1,opensearch-node2
- cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2
- bootstrap.memory_lock=true
- "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
- OPENSEARCH_INITIAL_ADMIN_PASSWORD=Admin_password_1234!
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
volumes:
- opensearch-data2:/usr/share/opensearch/data
networks:
- opensearch-net
opensearch-dashboards:
image: opensearchproject/opensearch-dashboards:2.11.0
container_name: opensearch-dashboards
ports:
- 5601:5601
environment:
OPENSEARCH_HOSTS: '["https://opensearch-node1:9200","https://opensearch-node2:9200"]'
OPENSEARCH_USERNAME: admin
OPENSEARCH_PASSWORD: Admin_password_1234!
networks:
- opensearch-net
volumes:
opensearch-data1:
opensearch-data2:
networks:
opensearch-net:
EOF
docker-compose up -d
Güvenlik Yapılandırması: ELK’tan Önemli Fark
OpenSearch’te güvenlik özellikleri default olarak aktif gelir. Bu bazen acemi kullanıcıları şaşırtıyor çünkü SSL sertifikaları ve kimlik doğrulama kutudan çıktığı gibi yapılandırılmış durumda. Elasticsearch’te bu özellikleri X-Pack ile ücretli olarak alıyordunuz.
Demo sertifikalar production için uygun değil. Kendi sertifikalarınızı oluşturalım:
# OpenSearch'in kendi araçlarıyla sertifika oluşturma
docker exec -it opensearch-node1 bash
# Container içinde
cd /usr/share/opensearch/plugins/opensearch-security/tools/
./opensearch-onetime-setup.sh
# Root CA oluştur
openssl genrsa -out root-ca-key.pem 2048
openssl req -new -x509 -sha256 -key root-ca-key.pem
-subj "/C=TR/ST=Istanbul/O=Sirketim/CN=root"
-out root-ca.pem -days 730
# Admin sertifikası
openssl genrsa -out admin-key-temp.pem 2048
openssl pkcs8 -inform PEM -outform PEM -in admin-key-temp.pem
-topk8 -nocrypt -v1 PBE-SHA1-3DES -out admin-key.pem
openssl req -new -key admin-key.pem
-subj "/C=TR/ST=Istanbul/O=Sirketim/CN=admin"
-out admin.csr
openssl x509 -req -in admin.csr -CA root-ca.pem
-CAkey root-ca-key.pem -CAcreateserial
-sha256 -out admin.pem -days 730
Güvenlik yapılandırmasını güncellemek için securityadmin.sh kullanıyoruz. Bu, prod ortamlarda değişiklik yaparken dikkat etmeniz gereken kritik bir araç:
# Güvenlik konfigürasyonunu uygula
./securityadmin.sh
-cd /usr/share/opensearch/config/opensearch-security/
-icl -nhnv
-cacert /usr/share/opensearch/config/root-ca.pem
-cert /usr/share/opensearch/config/admin.pem
-key /usr/share/opensearch/config/admin-key.pem
Fluent Bit ile Log Toplama
Logstash yerine Fluent Bit kullanmak, özellikle kaynak kısıtlı ortamlarda büyük fark yaratıyor. Fluent Bit yaklaşık 450KB bellek kullanırken Logstash minimum 512MB JVM heap istiyor. Gerçek üretim ortamlarında bu fark çok daha belirgin hale geliyor.
Kubernetes ortamında Fluent Bit’i OpenSearch’e bağlamak için fluent-bit.conf:
cat << 'EOF' > /etc/fluent-bit/fluent-bit.conf
[SERVICE]
Flush 1
Log_Level info
Daemon off
Parsers_File parsers.conf
[INPUT]
Name tail
Tag app.logs
Path /var/log/containers/*.log
Parser docker
DB /var/log/flb_kube.db
Mem_Buf_Limit 50MB
Skip_Long_Lines On
Refresh_Interval 10
[INPUT]
Name systemd
Tag host.systemd
Systemd_Filter _SYSTEMD_UNIT=nginx.service
Read_From_Tail On
[FILTER]
Name kubernetes
Match app.logs
Kube_URL https://kubernetes.default.svc:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
Merge_Log On
Keep_Log Off
K8S-Logging.Parser On
K8S-Logging.Exclude Off
[FILTER]
Name grep
Match app.logs
Regex log (ERROR|WARN|CRITICAL)
[OUTPUT]
Name opensearch
Match *
Host opensearch-node1
Port 9200
Index app-logs
Type _doc
HTTP_User admin
HTTP_Passwd Admin_password_1234!
tls On
tls.verify Off
Suppress_Type_Name On
Logstash_Format On
Logstash_Prefix app-logs
Time_Key @timestamp
EOF
Index Template ve Mapping Yönetimi
OpenSearch’e veri atmadan önce doğru mapping tanımlamak, sonradan “neden bu alan text yerine keyword olmuş” diye saçını yolmamak anlamına geliyor. Özellikle IP adresleri ve zaman damgaları için explicit mapping şart.
# Index template oluşturma
curl -X PUT "https://localhost:9200/_index_template/app-logs-template"
-H 'Content-Type: application/json'
-u admin:Admin_password_1234!
--insecure
-d '{
"index_patterns": ["app-logs-*"],
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"index.refresh_interval": "30s",
"index.codec": "best_compression"
},
"mappings": {
"properties": {
"@timestamp": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
},
"client_ip": {
"type": "ip"
},
"log_level": {
"type": "keyword"
},
"service_name": {
"type": "keyword"
},
"message": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 512
}
}
},
"response_time_ms": {
"type": "float"
},
"http_status": {
"type": "integer"
}
}
}
},
"priority": 100
}'
ISM (Index State Management) ile Otomatik Index Yaşam Döngüsü
Bu, OpenSearch’in ELK’a göre gerçekten ücretsiz sunduğu kritik özelliklerden biri. Elasticsearch’te ILM (Index Lifecycle Management) X-Pack gerektiriyordu. ISM ile otomatik olarak eski indexleri arşivleyebilir, silebilir veya read-only hale getirebilirsiniz.
Gerçek bir senaryo: 30 günden eski logları otomatik sil, 7 günden eski indexleri read-only yap, replikaları azalt:
curl -X PUT "https://localhost:9200/_plugins/_ism/policies/log-rotation-policy"
-H 'Content-Type: application/json'
-u admin:Admin_password_1234!
--insecure
-d '{
"policy": {
"description": "Log rotation: hot-warm-delete",
"default_state": "hot",
"states": [
{
"name": "hot",
"actions": [
{
"rollover": {
"min_index_age": "1d",
"min_size": "5gb"
}
}
],
"transitions": [
{
"state_name": "warm",
"conditions": {
"min_index_age": "7d"
}
}
]
},
{
"name": "warm",
"actions": [
{
"read_only": {}
},
{
"replica_count": {
"number_of_replicas": 0
}
}
],
"transitions": [
{
"state_name": "delete",
"conditions": {
"min_index_age": "30d"
}
}
]
},
{
"name": "delete",
"actions": [
{
"delete": {}
}
],
"transitions": []
}
],
"ism_template": [
{
"index_patterns": ["app-logs-*"],
"priority": 100
}
]
}
}'
Alerting: OpenSearch’in Native Alarm Sistemi
ELK Stack’te Watcher ya da ElastAlert gibi harici araçlara ihtiyaç duyuyordunuz. OpenSearch, alerting eklentisini kutudan çıktığı gibi sunuyor. 5xx hata oranı belirli eşiği geçince Slack’e veya e-posta ile bildirim göndermek artık çok daha kolay.
Monitor oluşturma örneği:
curl -X POST "https://localhost:9200/_plugins/_alerting/monitors"
-H 'Content-Type: application/json'
-u admin:Admin_password_1234!
--insecure
-d '{
"type": "monitor",
"name": "5xx-error-rate-monitor",
"enabled": true,
"schedule": {
"period": {
"interval": 5,
"unit": "MINUTES"
}
},
"inputs": [
{
"search": {
"indices": ["app-logs-*"],
"query": {
"size": 0,
"query": {
"bool": {
"filter": [
{
"range": {
"@timestamp": {
"gte": "now-5m",
"lte": "now"
}
}
},
{
"range": {
"http_status": {
"gte": 500,
"lte": 599
}
}
}
]
}
},
"aggs": {
"error_count": {
"value_count": {
"field": "http_status"
}
}
}
}
}
}
],
"triggers": [
{
"name": "high-error-rate",
"severity": "1",
"condition": {
"script": {
"source": "ctx.results[0].aggregations.error_count.value > 100",
"lang": "painless"
}
},
"actions": [
{
"name": "slack-notification",
"destination_id": "SLACK_DESTINATION_ID",
"message_template": {
"source": "5xx hata sayisi son 5 dakikada {{ctx.results.0.aggregations.error_count.value}} adede ulasti!"
}
}
]
}
]
}'
Performans Tuning: Prod Ortamı İçin Kritik Ayarlar
Cluster’ı ayağa kaldırdınız, loglar akıyor ama zamanla yavaşlamaya başlıyor. Bu noktada yapılması gereken bazı kritik ayarlar var. JVM heap size’ı toplam RAM’in yarısından fazla vermeyin, işletim sistemi dosya önbelleği için yer bırakın. 64GB RAM olan bir makinede maksimum 32GB heap kullanın.
opensearch.yml için önerilen prod ayarları:
cat << 'EOF' >> /usr/share/opensearch/config/opensearch.yml
# Cluster ayarları
cluster.name: production-logs
node.name: ${HOSTNAME}
# Bellek
bootstrap.memory_lock: true
# Thread pool ayarları
thread_pool.write.queue_size: 1000
thread_pool.search.queue_size: 1000
# Index buffer
indices.memory.index_buffer_size: 20%
indices.memory.min_index_buffer_size: 96mb
# Circuit breaker - OOM'dan korur
indices.breaker.total.use_real_memory: true
indices.breaker.total.limit: 95%
# Shard allocation
cluster.routing.allocation.disk.threshold_enabled: true
cluster.routing.allocation.disk.watermark.low: 85%
cluster.routing.allocation.disk.watermark.high: 90%
cluster.routing.allocation.disk.watermark.flood_stage: 95%
# Recover ayarları
cluster.routing.allocation.node_concurrent_recoveries: 4
indices.recovery.max_bytes_per_sec: 200mb
# Slow log eşikleri
index.search.slowlog.threshold.query.warn: 10s
index.search.slowlog.threshold.query.info: 5s
index.search.slowlog.threshold.fetch.warn: 1s
index.indexing.slowlog.threshold.index.warn: 10s
EOF
Gerçek Dünya Senaryosu: E-Ticaret Log Analizi
Bir e-ticaret platformu düşünelim. Saniyede ortalama 2000 istek alıyor, peak saatlerde bu 10.000’e çıkıyor. Her isteğin nginx access log kaydı var ve ödeme sayfasındaki hataları gerçek zamanlı izlemek istiyorlar.
Bu senaryo için OpenSearch üzerinde çalışan bir analiz sorgusu:
# Ödeme sayfasındaki 5xx hatalarını son 1 saatte serbis bazında grupla
curl -X GET "https://localhost:9200/app-logs-*/_search"
-H 'Content-Type: application/json'
-u admin:Admin_password_1234!
--insecure
-d '{
"size": 0,
"query": {
"bool": {
"filter": [
{
"range": {
"@timestamp": {
"gte": "now-1h"
}
}
},
{
"term": {
"url_path.keyword": "/api/payment"
}
},
{
"range": {
"http_status": {
"gte": 500
}
}
}
]
}
},
"aggs": {
"errors_over_time": {
"date_histogram": {
"field": "@timestamp",
"fixed_interval": "5m"
},
"aggs": {
"by_service": {
"terms": {
"field": "service_name",
"size": 10
},
"aggs": {
"avg_response_time": {
"avg": {
"field": "response_time_ms"
}
}
}
}
}
},
"top_error_messages": {
"terms": {
"field": "message.keyword",
"size": 5
}
}
}
}'
Bu sorgu size hem zaman bazlı trend hem de hangi servisin ne kadar hata ürettiğini, ortalama yanıt sürelerini ve en sık karşılaşılan hata mesajlarını tek sorguda verir.
OpenSearch ile ELK: Hangisi Nerede Daha İyi?
Dürüst olmak gerekirse her iki sistemin de güçlü ve zayıf tarafları var.
OpenSearch’in öne çıktığı noktalar:
- Ücretsiz güvenlik: TLS, RBAC, audit logging hepsi açık kaynak
- ISM: Index yaşam döngüsü yönetimi ücretsiz
- Alerting: Native alarm sistemi ekstra araç gerektirmiyor
- AWS entegrasyonu: Amazon OpenSearch Service ile native entegrasyon
- Anomaly detection: ML tabanlı anomali tespiti community versiyonda mevcut
Elasticsearch’ün hâlâ önde olduğu noktalar:
- Ekolojim: Beats entegrasyonları, Elastic APM, daha geniş connector desteği
- Performans: 8.x serisiyle gelen optimizasyonlar OpenSearch’te henüz tam olarak yok
- Kibana olgunluğu: Lens, Maps gibi gelişmiş görselleştirme araçları OpenSearch Dashboards’da daha sınırlı
- Sürüm hızı: Elastic yeni özellikler çıkarmada daha agresif
Snapshot ve Backup Stratejisi
Production’da snapshot olmadan çalışmak, emniyet kemeri takmadan araba kullanmak gibi. OpenSearch S3 snapshot repository desteğini native olarak sunuyor:
# S3 snapshot repository tanımla
curl -X PUT "https://localhost:9200/_snapshot/s3-backup-repo"
-H 'Content-Type: application/json'
-u admin:Admin_password_1234!
--insecure
-d '{
"type": "s3",
"settings": {
"bucket": "opensearch-backups-prod",
"region": "eu-west-1",
"base_path": "opensearch/snapshots",
"server_side_encryption": true,
"compress": true,
"max_snapshot_bytes_per_sec": "100mb",
"max_restore_bytes_per_sec": "100mb"
}
}'
# Snapshot politikası oluştur - her gece 02:00'da
curl -X PUT "https://localhost:9200/_plugins/_sm/policies/nightly-backup"
-H 'Content-Type: application/json'
-u admin:Admin_password_1234!
--insecure
-d '{
"description": "Her gece otomatik snapshot",
"creation": {
"schedule": {
"cron": {
"expression": "0 2 * * *",
"timezone": "Europe/Istanbul"
}
},
"time_limit": "1h"
},
"deletion": {
"schedule": {
"cron": {
"expression": "0 3 * * *",
"timezone": "Europe/Istanbul"
}
},
"condition": {
"max_age": "14d",
"min_count": 5,
"max_count": 21
},
"time_limit": "1h"
},
"snapshot_config": {
"repository": "s3-backup-repo",
"indices": "app-logs-*,system-logs-*",
"ignore_unavailable": true,
"include_global_state": false,
"partial": false
}
}'
Sonuç
OpenSearch, 2021’deki doğuşundan bu yana ciddi bir olgunluğa ulaştı. Eğer ekibinizde halihazırda ELK Stack varsa ve X-Pack özellikleri için ücret ödüyorsanız, OpenSearch’e geçiş güçlü bir maliyet optimizasyonu fırsatı. Öte yandan sıfırdan başlıyorsanız ve AWS altyapısı kullanıyorsanız Amazon OpenSearch Service ile managed bir deneyim oldukça cazip.
Elasticsearch 7.x’ten OpenSearch’e migration API uyumluluğu açısından büyük ölçüde sorunsuz. Ancak Elasticsearch 8.x’ten geçiş yapmak isteyenler için bu süreç daha fazla planlama gerektiriyor, çünkü OpenSearch şu an 7.x API setinden evrimleşiyor ve bazı 8.x özellikleri henüz karşılık bulmuyor.
Kendi deneyimimden söyleyeyim: ISM politikaları ve native alerting tek başına birçok organizasyon için geçişi haklı kılabilecek kadar değerli. Sadece “lisans bedava” diye değil, gerçekten olgun ve üretim kullanımına hazır bir ürün olduğu için OpenSearch’i ciddiye almak gerekiyor.
