Elasticsearch ile Anomali Tespiti: Machine Learning Kullanımı

Elasticsearch üzerinde makine öğrenmesi ile anomali tespiti yapmak, büyük veri ortamlarında güvenlik tehditlerini, performans sorunlarını ve beklenmedik sistem davranışlarını yakalamak için son derece güçlü bir yaklaşım. Özellikle günde milyonlarca log satırı işleyen ortamlarda, manuel kural yazmak hem zaman kaybı hem de yetersiz kalıyor. İşte tam bu noktada Elasticsearch’ün ML özellikleri devreye giriyor.

Elasticsearch ML Nedir ve Neden Kullanmalısınız?

Elasticsearch’ün makine öğrenmesi modülü, X-Pack kapsamında gelir ve Elastic Stack’in 6.x sürümünden itibaren ciddi şekilde olgunlaştı. Temel olarak zaman serisi verilerinde anormallik arayan unsupervised learning (denetimsiz öğrenme) algoritmalarını kullanır. Yani siz modele “bu normal, bu anormal” diye etiket vermek zorunda değilsiniz. Model, geçmiş verilerden normal davranışı öğrenir ve bu kalıptan sapmaları otomatik olarak işaretler.

Gerçek dünya senaryolarında şunları tespit edebilirsiniz:

  • Aniden düşen HTTP istek sayısı (servis çöküşü belirtisi)
  • Olağandışı saatlerde gelen yönetici girişleri (güvenlik ihlali)
  • CPU kullanımının normal bandın dışına çıkması (kaynak tüketim saldırısı)
  • Belirli bir API endpoint’ine gelen istek patlaması (DDoS veya scraping)
  • Log volume’undaki beklenmedik düşüşler (log pipeline arızası)

Kurulum Gereksinimleri ve Lisans Durumu

Önce şunu netleştirelim: Elasticsearch ML özellikleri Platinum veya Enterprise lisans gerektiriyor. Ancak 30 günlük trial ile başlayabilir, sonrasında küçük ortamlar için Elastic Cloud’un ücretsiz tier’ını deneyebilirsiniz. On-premise için trial aktif etmek şu şekilde:

# Trial lisans aktifleştirme
curl -X POST "localhost:9200/_license/start_trial?acknowledge=true" 
  -H "Content-Type: application/json"

# Mevcut lisans durumunu kontrol et
curl -X GET "localhost:9200/_license" | python3 -m json.tool

ML node’u için önerilen minimum sistem gereksinimleri:

  • RAM: En az 8GB, üretim için 16GB+
  • CPU: 4 core minimum, ML işlemleri CPU-intensive
  • xpack.ml.enabled: true (varsayılan olarak açık)
  • node.roles: ml rolü atanmış dedicated node önerilir

ML işlerini dedicated bir node’a yönlendirmek için elasticsearch.yml dosyasında şu ayarı yapın:

# /etc/elasticsearch/elasticsearch.yml - ML node ayarları
node.name: ml-node-01
node.roles: [ ml ]
xpack.ml.enabled: true
xpack.ml.max_machine_memory_percent: 30
xpack.ml.max_open_jobs: 20

Anomali Tespiti İçin Veri Hazırlığı

ML modeli kurmadan önce verinizin düzgün şekillendirilmiş olması gerekiyor. Timestamp alanı mutlaka date tipinde olmalı ve veri yeterli tarihsel derinliğe sahip olmalı. Genellikle modelin anlamlı baseline oluşturabilmesi için en az 2-4 haftalık veri öneriyorum.

Önce index mapping’i kontrol edin:

# Index mapping kontrolü
curl -X GET "localhost:9200/nginx-logs-*/_mapping" | 
  python3 -c "import sys,json; d=json.load(sys.stdin); 
  print(json.dumps(list(d.keys()), indent=2))"

# Örnek bir mapping tanımı
curl -X PUT "localhost:9200/nginx-logs-template" 
  -H "Content-Type: application/json" 
  -d '{
    "mappings": {
      "properties": {
        "@timestamp": { "type": "date" },
        "status_code": { "type": "integer" },
        "bytes": { "type": "long" },
        "response_time": { "type": "float" },
        "client_ip": { "type": "ip" },
        "request_path": { "type": "keyword" }
      }
    }
  }'

Verinin kalitesini ölçmek için hızlı bir aggregation:

# Veri kalitesi ve zaman dağılımı kontrolü
curl -X GET "localhost:9200/nginx-logs-*/_search" 
  -H "Content-Type: application/json" 
  -d '{
    "size": 0,
    "aggs": {
      "zaman_dagilimi": {
        "date_histogram": {
          "field": "@timestamp",
          "calendar_interval": "1d"
        }
      },
      "bos_response_time": {
        "missing": {
          "field": "response_time"
        }
      }
    }
  }'

İlk ML Job Oluşturma: Single Metric

En basit anomali tespiti senaryosuyla başlayalım: nginx üzerindeki ortalama response time’ın anormal yükselmesi.

# Single metric job oluşturma - API üzerinden
curl -X PUT "localhost:9200/_ml/anomaly_detectors/nginx-response-time-anomaly" 
  -H "Content-Type: application/json" 
  -d '{
    "description": "Nginx ortalama yanit suresi anomali tespiti",
    "analysis_config": {
      "bucket_span": "15m",
      "detectors": [
        {
          "detector_description": "Ortalama response time anomalisi",
          "function": "mean",
          "field_name": "response_time",
          "detector_index": 0
        }
      ],
      "influencers": ["client_ip", "request_path"]
    },
    "analysis_limits": {
      "model_memory_limit": "256mb"
    },
    "data_description": {
      "time_field": "@timestamp",
      "time_format": "epoch_ms"
    },
    "model_plot_config": {
      "enabled": true
    }
  }'

Job oluştuktan sonra datafeed bağlayın:

# Datafeed oluşturma
curl -X PUT "localhost:9200/_ml/datafeeds/datafeed-nginx-response-time" 
  -H "Content-Type: application/json" 
  -d '{
    "job_id": "nginx-response-time-anomaly",
    "indices": ["nginx-logs-*"],
    "query": {
      "bool": {
        "filter": [
          { "range": { "status_code": { "gte": 200 } } }
        ]
      }
    },
    "scroll_size": 1000,
    "delayed_data_check_config": {
      "enabled": true
    }
  }'

# Datafeed'i başlat (geçmiş veriyle birlikte)
curl -X POST "localhost:9200/_ml/datafeeds/datafeed-nginx-response-time/_start" 
  -H "Content-Type: application/json" 
  -d '{
    "start": "2024-01-01T00:00:00Z"
  }'

Multi-Metric ve Population Analizi

Tek bir metrik izlemek başlangıç için yeterli ama üretim ortamlarında birden fazla metriği aynı anda izlemek istiyorsunuz. Ayrıca “hangi IP en anormal davranıyor?” gibi sorular sormak için population analysis kullanmak gerekiyor.

# Multi-metric job - hem request count hem response time
curl -X PUT "localhost:9200/_ml/anomaly_detectors/nginx-multi-metric" 
  -H "Content-Type: application/json" 
  -d '{
    "description": "Nginx cok metrikli analiz",
    "analysis_config": {
      "bucket_span": "10m",
      "detectors": [
        {
          "function": "high_mean",
          "field_name": "response_time",
          "by_field_name": "request_path",
          "detector_description": "Path bazinda yuksek response time"
        },
        {
          "function": "high_count",
          "over_field_name": "client_ip",
          "detector_description": "IP bazinda yuksek istek sayisi"
        },
        {
          "function": "high_sum",
          "field_name": "bytes",
          "over_field_name": "client_ip",
          "detector_description": "IP bazinda yuksek veri transferi"
        }
      ],
      "influencers": ["client_ip", "request_path", "status_code"]
    },
    "analysis_limits": {
      "model_memory_limit": "512mb"
    },
    "data_description": {
      "time_field": "@timestamp"
    }
  }'

Population analysis için over_field_name kullanımı kritik. Bu sayede model, tüm IP’lerin genel davranışına göre bir IP’nin ne kadar sapkın davrandığını ölçüyor.

Anomali Sonuçlarını Sorgulamak

Job çalışmaya başladıktan sonra anomali sonuçlarını .ml-anomalies-* index’inden sorgulayabilirsiniz:

# Yüksek anomali skorlu sonuçları getir
curl -X GET "localhost:9200/.ml-anomalies-*/_search" 
  -H "Content-Type: application/json" 
  -d '{
    "size": 20,
    "query": {
      "bool": {
        "must": [
          { "match": { "job_id": "nginx-multi-metric" } },
          { "range": { "anomaly_score": { "gte": 75 } } },
          {
            "range": {
              "timestamp": {
                "gte": "now-7d",
                "lte": "now"
              }
            }
          }
        ]
      }
    },
    "sort": [
      { "anomaly_score": { "order": "desc" } }
    ],
    "_source": [
      "timestamp",
      "anomaly_score",
      "detector_index",
      "influencers",
      "actual",
      "typical",
      "bucket_span"
    ]
  }'

Anomali skoru yorumlaması şu şekilde düşünülebilir:

  • 0-25: Düşük önem, bilgi amaçlı
  • 25-50: Orta düzey sapma, izlenmeli
  • 50-75: Yüksek önem, incelenmeli
  • 75-100: Kritik anomali, acil müdahale

Gerçek Dünya Senaryosu: Güvenlik Tehdidi Tespiti

Bir müşteri ortamında şu senaryoyla karşılaştım: Gece 3’te bir kullanıcı hesabı normalin 50 katı API isteği atmaya başladı. Firewall kuralları sadece IP bazlı çalıştığı için bu user-agent tabanlı saldırıyı yakalayamadı. ML job sayesinde hem anında alert ürettik hem de sonraki gün forensic analiz yaptık.

Bu tür güvenlik senaryoları için authentication loglarını analiz eden bir job:

# Auth log anomali tespiti - brute force ve hesap ele geçirme
curl -X PUT "localhost:9200/_ml/anomaly_detectors/auth-security-anomaly" 
  -H "Content-Type: application/json" 
  -d '{
    "description": "Kimlik dogrulama anomalileri - guvenlik",
    "analysis_config": {
      "bucket_span": "5m",
      "detectors": [
        {
          "function": "high_count",
          "by_field_name": "user.name",
          "detector_description": "Kullanici bazinda yuksek istek"
        },
        {
          "function": "high_count",
          "partition_field_name": "event.outcome",
          "detector_description": "Basarisiz giris sayisi artisi"
        },
        {
          "function": "rare",
          "by_field_name": "user.name",
          "over_field_name": "source.geo.country_iso_code",
          "detector_description": "Nadir ulkeden giris"
        }
      ],
      "influencers": [
        "user.name",
        "source.ip",
        "source.geo.country_iso_code"
      ]
    },
    "analysis_limits": {
      "model_memory_limit": "256mb"
    },
    "data_description": {
      "time_field": "@timestamp"
    },
    "custom_settings": {
      "custom_urls": [
        {
          "url_name": "Kibana Discovery",
          "url_value": "kibana#/discover?_g=(time:(from:$earliest$,to:$latest$))"
        }
      ]
    }
  }'

Alert Konfigürasyonu: Watcher ile Entegrasyon

Anomali tespit etmek yetmez, anında haber almak gerekiyor. Elasticsearch Watcher ile ML anomalilerini Slack veya email’e bağlayabilirsiniz:

# Watcher alert - yüksek anomali skorlarında Slack bildirimi
curl -X PUT "localhost:9200/_watcher/watch/ml-high-anomaly-alert" 
  -H "Content-Type: application/json" 
  -d '{
    "trigger": {
      "schedule": {
        "interval": "10m"
      }
    },
    "input": {
      "search": {
        "request": {
          "indices": [".ml-anomalies-*"],
          "body": {
            "size": 5,
            "query": {
              "bool": {
                "must": [
                  { "range": { "anomaly_score": { "gte": 80 } } },
                  { "range": { "timestamp": { "gte": "now-10m" } } },
                  { "term": { "is_interim": false } }
                ]
              }
            },
            "sort": [{ "anomaly_score": { "order": "desc" } }]
          }
        }
      }
    },
    "condition": {
      "compare": {
        "ctx.payload.hits.total.value": {
          "gt": 0
        }
      }
    },
    "actions": {
      "slack_bildirim": {
        "webhook": {
          "scheme": "https",
          "host": "hooks.slack.com",
          "port": 443,
          "method": "post",
          "path": "/services/YOUR_WEBHOOK_PATH",
          "headers": {
            "Content-Type": "application/json"
          },
          "body": "{"text": "KRITIK ANOMALI: {{ctx.payload.hits.hits.0._source.job_id}} - Skor: {{ctx.payload.hits.hits.0._source.anomaly_score}}"}"
        }
      }
    }
  }'

Model Performansını İzlemek ve Ayarlamak

ML job’larınızın ne kadar iyi çalıştığını düzenli takip etmek gerekiyor. Model memory kullanımı, job durumu ve veri gecikmelerini kontrol etmek için:

# Tüm ML job'larının durumunu kontrol et
curl -X GET "localhost:9200/_ml/anomaly_detectors/_stats" 
  -H "Content-Type: application/json" | 
  python3 -m json.tool | grep -E "(job_id|state|model_size_stats)"

# Belirli bir job'ın detaylı istatistikleri
curl -X GET "localhost:9200/_ml/anomaly_detectors/nginx-multi-metric/_stats" 
  -H "Content-Type: application/json"

# Datafeed gecikmesini kontrol et
curl -X GET "localhost:9200/_ml/datafeeds/datafeed-nginx-response-time/_stats"

Model belleği dolmaya başlarsa şu parametreleri gözden geçirin:

  • model_memory_limit: Yeterince büyük olmalı ama sistemi zorlamayın
  • bucket_span: Küçük bucket daha hassas ama daha fazla bellek ister
  • by/over/partition field cardinality: Yüksek cardinality bellek patlatır

Örneğin client_ip alanını by_field olarak kullandığınızda eğer milyonlarca unique IP varsa modeli mahvedebilirsiniz. Bu durumda partition_field_name kullanın veya IP’leri subnet’lere gruplayın.

Job Otomasyonu: Scheduled Snapshot ve Cleanup

Uzun süre çalışan ML job’ları zamanla büyük miktarda snapshot verisi biriktirir. Bunları yönetmek için periyodik cleanup scripti:

#!/bin/bash
# ml_maintenance.sh - ML job bakım scripti

ES_HOST="localhost:9200"
JOB_ID="nginx-multi-metric"

# 30 günden eski model snapshot'larını sil
echo "Eski snapshotlar temizleniyor..."
THIRTY_DAYS_AGO=$(date -d "30 days ago" +%s%3N)

curl -X POST "${ES_HOST}/_ml/anomaly_detectors/${JOB_ID}/model_snapshots/_delete" 
  -H "Content-Type: application/json" 
  -d "{
    "delete_intervening_results": false,
    "end": ${THIRTY_DAYS_AGO}
  }"

# Job istatistiklerini logla
echo "Job istatistikleri:"
curl -s -X GET "${ES_HOST}/_ml/anomaly_detectors/${JOB_ID}/_stats" | 
  python3 -c "
import sys, json
d = json.load(sys.stdin)
stats = d['jobs'][0]
print(f'Durum: {stats["state"]}')
print(f'Model boyutu: {stats["model_size_stats"]["model_bytes"]} bytes')
print(f'Toplak bucket: {stats["data_counts"]["bucket_count"]}')
"

echo "Bakim tamamlandi: $(date)"

Bu scripti cron ile haftada bir çalıştırmak yeterli:

# Crontab ekle
echo "0 2 * * 0 /opt/scripts/ml_maintenance.sh >> /var/log/es-ml-maintenance.log 2>&1" | crontab -

Kibana’da ML Sonuçlarını Görselleştirmek

API her ne kadar güçlü olsa da günlük operasyonda Kibana’nın ML UI’ı çok daha kullanışlı. Stack Management > Machine Learning > Anomaly Detection menüsünden tüm job’larınızı yönetebilirsiniz. Birkaç ipucu:

  • Anomaly Explorer görünümü: Job’lar arası genel anomali haritası için ideal
  • Single Metric Viewer: Tek bir metriğin baseline’ı ile gerçek değerini karşılaştırmak için
  • Swimlane view: Zaman bazlı anomali yoğunluğunu görmek için

Kibana Dashboard’a ML anomali sonuçlarını eklemek için .ml-anomalies-* index’i üzerine bir index pattern oluşturun ve normal visualization widget’ları ile kullanın.

Yaygın Hatalar ve Çözümleri

Birkaç yıllık deneyimden öğrendiğim kritik hatalar:

Yetersiz başlangıç verisi: Modeli çalıştırmadan önce en az 2 haftalık veri olmalı. Yoksa model hatayla karşılaştığı her şeyi anomali sayar ve gereksiz alert üretir.

Çok küçük bucket_span: 1-2 dakikalık bucket span, haftalık sezonsal kalıpları yakalamakta zorlanır. Genellikle 10-15 dakika iyi bir başlangıç noktası.

Yüksek cardinality field’ları by_field olarak kullanmak: user_agent gibi binlerce unique değeri olan alanlar belleği bitirir. Önce bir terms aggregation ile kaç unique değer olduğunu kontrol edin.

Datafeed query’si olmadan çalıştırmak: Tüm veriyi ML’e vermek yerine ilgili filtreleri uygulayın. Hem performans hem de model kalitesi için önemli.

Model snapshot almayı unutmak: Uzun süreli job’lar için manuel snapshot alın, böylece bir sorun çıktığında öğrenilen modeli kaybetmezsiniz:

# Manuel model snapshot al
curl -X POST "localhost:9200/_ml/anomaly_detectors/nginx-multi-metric/_flush" 
  -H "Content-Type: application/json" 
  -d '{"calc_interim": true}'

# Mevcut snapshotları listele
curl -X GET "localhost:9200/_ml/anomaly_detectors/nginx-multi-metric/model_snapshots" 
  -H "Content-Type: application/json"

Sonuç

Elasticsearch ML ile anomali tespiti, doğru kurulduğunda hem güvenlik hem de operasyonel görünürlük açısından çok büyük değer katıyor. Başlangıçta lisans maliyeti ve sistem kaynakları konusundaki endişeler anlaşılır, ama üretim ortamında kaçırdığınız bir güvenlik ihlali ya da saatlerce süren bir performans sorununun maliyetiyle karşılaştırıldığında bu yatırım hızla kendini amorti ediyor.

Pratik başlangıç önerim şu: Önce tek bir kritik metrikle, örneğin nginx response time veya login failure count ile başlayın. Modelin birkaç hafta veri toplamasını bekleyin, Kibana üzerinden kalibrasyon yapın, gereksiz alert noise’u azaltın. Sonra yavaş yavaş multi-metric ve population analysis job’larına geçin.

En önemli nokta şu: ML bir sihir değil, sisteminizi ne kadar iyi tanırsanız job konfigürasyonunuz o kadar isabetli olur. Influencer seçimi, bucket span ayarı ve veri kalitesi, algoritmanın kendisi kadar belirleyici. Sistemi kurup unutmak yerine haftada bir anomali sonuçlarına bakın ve modelin giderek daha akıllı hale geldiğini gözlemleyin.

Bir yanıt yazın

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