Prometheus Nedir: Metrik Toplama Mimarisi

Yıllar önce bir gece 3’te telefon çaldığında, production sunucumuzun çöktüğünü öğrendim. Sorunun ne zaman başladığını bulmak için logları karıştırırken saatler geçti. O gece anladım ki reaktif izleme artık yetmiyor, proaktif bir sisteme ihtiyacım var. İşte o noktada Prometheus hayatıma girdi ve o günden beri gece 3 aramalarının sayısı dramatik biçimde azaldı.

Prometheus Nedir?

Prometheus, SoundCloud tarafından 2012 yılında geliştirilen ve 2016’da CNCF (Cloud Native Computing Foundation) bünyesine katılan açık kaynaklı bir izleme ve alerting sistemidir. Go diliyle yazılmıştır ve özellikle dinamik, container tabanlı ortamlar için tasarlanmıştır.

Ama teknik tanımları bir kenara bırakalım. Pratik açıdan Prometheus şunu yapar: Sistemlerinizdeki her şeyi sayısal veriye dönüştürür, bu verileri zaman serisi olarak saklar ve anormallikleri tespit etmenizi sağlar. CPU kullanımından HTTP istek sayısına, veritabanı bağlantı havuzundan disk I/O değerlerine kadar her şeyi ölçebilirsiniz.

Prometheus’un rakiplerinden ayıran en önemli özelliği pull-based mimarisidir. Yani sunucularınıza veri göndermeleri için bir agent kurup yapılandırmak yerine, Prometheus kendisi gidip veriyi çeker. Bu yaklaşım başlangıçta garip gelebilir ama pratikte çok büyük avantajlar sağlar.

Temel Mimari Bileşenler

Prometheus ekosistemi birbirini tamamlayan birkaç bileşenden oluşur. Bunları tek tek anlamak, sistemi doğru kurgulayabilmek için kritik öneme sahiptir.

Prometheus Server

Her şeyin kalbi burasıdır. Prometheus server üç ana görev üstlenir:

  • Scraping: Hedef endpointlerden metrikleri periyodik olarak çeker
  • Storage: Çekilen metrikleri yerel time-series veritabanında saklar
  • PromQL Engine: Sorgulama ve alerting kurallarını çalıştırır

Prometheus server, kendi başına oldukça bağımsız çalışabilir. Tek bir binary dosyasıdır ve minimal bağımlılıkla ayağa kalkar.

Exporters

Exporters, Prometheus’un anlayacağı formatta metrik sunan küçük programlardır. Sisteminizde halihazırda çalışan uygulamaların çoğu Prometheus formatında metrik sunmaz. Bu noktada exporter’lar devreye girer.

En yaygın kullanılan exporter’lar şunlardır:

  • node_exporter: Linux/Unix sistem metrikleri (CPU, RAM, disk, network)
  • windows_exporter: Windows sistem metrikleri
  • blackbox_exporter: HTTP, HTTPS, DNS, TCP endpoint kontrolü
  • mysqld_exporter: MySQL/MariaDB metrikleri
  • postgres_exporter: PostgreSQL metrikleri
  • redis_exporter: Redis metrikleri
  • nginx-prometheus-exporter: Nginx metrikleri

Pushgateway

Pull mimarisinin bir dezavantajı var: Kısa ömürlü işler (batch job, cron job) için Prometheus’un zamanında gelip veriyi çekmesi zordur. İş 30 saniyede bitiyorsa ve Prometheus 1 dakikada bir scrape ediyorsa, o iş hiç görünmeyebilir.

İşte burada Pushgateway devreye girer. Kısa ömürlü işleriniz metrikleri Pushgateway’e iter, Prometheus da Pushgateway’den o metrikleri çeker.

Alertmanager

Alertmanager, Prometheus’un ürettiği alertleri alır, işler ve ilgili kişilere iletir. Sadece “bir şey patladı” diye mail atmak yerine, alertleri gruplar, dedupe eder ve susturma (silencing) özelliği sayesinde bakım pencerelerinde gereksiz bildirim gönderilmesini engeller.

Service Discovery

Statik IP listesi tutmak, özellikle Kubernetes veya auto-scaling ortamlarında imkansız hale gelir. Prometheus’un service discovery mekanizması sayesinde yeni ayağa kalkan servisler otomatik olarak izlemeye alınır.

Desteklenen service discovery mekanizmaları arasında şunlar var:

  • Kubernetes API
  • Consul
  • AWS EC2
  • Azure
  • GCE
  • DNS-based discovery
  • Dosya tabanlı (file-based) discovery

Pull vs Push: Neden Pull Tercih Edildi?

Bu tartışma Prometheus kullanmaya başlayan hemen herkesin aklına takılır. “Neden sunucular veriyi kendileri göndermiyor?” diye sorulur.

Pull mimarisinin avantajları oldukça somuttur:

  • Merkezi kontrol: İzleme yapılandırması tek bir yerde (Prometheus server’da) tutulur
  • Sağlık tespiti: Eğer bir hedeften veri çekilemiyorsa, o hedefin sorunlu olduğunu anında bilirsiniz
  • Kolay debug: curl http://sunucu:9100/metrics komutuyla o anda ne döndüğünü görebilirsiniz
  • Güvenlik: Sunucuların dışarıya bağlantı açmasına gerek kalmaz

Şöyle düşünün: Push mimarisinde bir sunucudan veri gelmediğinde, bu sunucunun çökmesinden mi, network sorundan mı yoksa agent’ın bozulmasından mı kaynaklandığını bilemezsiniz. Pull mimarisinde “scrape başarısız” dediğinizde hedefin ulaşılamaz durumda olduğunu kesin olarak bilirsiniz.

Metrik Tipleri

Prometheus dört temel metrik tipi tanımlar ve bunları doğru kullanmak, anlamlı dashboardlar oluşturabilmenin temelidir.

Counter

Sadece artan bir değer tutar. Sıfırlanmaz (process restart hariç). HTTP istek sayısı, gönderilen email sayısı, hata sayısı gibi kavramlar için kullanılır.

# Örnek counter metriği
http_requests_total{method="GET", status="200"} 1547
http_requests_total{method="POST", status="500"} 23

Counter’ı tek başına sorgulamak genellikle anlamsızdır. rate() veya increase() fonksiyonlarıyla birlikte kullanılır:

# Son 5 dakikadaki saniye başına istek sayısı
rate(http_requests_total[5m])

# Son 1 saatteki toplam hata sayısı
increase(http_errors_total[1h])

Gauge

Artıp azalabilen anlık değerler için kullanılır. CPU kullanımı, RAM kullanımı, aktif bağlantı sayısı bu kategoriye girer.

# Örnek gauge metrikleri
node_memory_MemAvailable_bytes 2147483648
process_open_fds 42
temperature_celsius{sensor="cpu"} 67.5

Histogram

İsteklerin yanıt süresi gibi değerlerin dağılımını ölçmek için kullanılır. Değerleri önceden tanımlanmış bucket’lara yerleştirir.

# HTTP request duration histogram
http_request_duration_seconds_bucket{le="0.1"} 234
http_request_duration_seconds_bucket{le="0.5"} 891
http_request_duration_seconds_bucket{le="1.0"} 1203
http_request_duration_seconds_bucket{le="+Inf"} 1247
http_request_duration_seconds_sum 523.4
http_request_duration_seconds_count 1247

Histogram’dan yüzdelik değer hesaplamak için:

# 95. yüzdelik HTTP yanıt süresi
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))

Summary

Histogram’a benzer ama quantile’ları client tarafında hesaplar. Genellikle histogram tercih edilir çünkü summary’de birden fazla instance’ı aggregate etmek zordur.

Prometheus Kurulumu

Teoriyi bir kenara bırakıp pratiğe geçelim. Basit bir Ubuntu sunucusuna Prometheus kuruyoruz:

# Prometheus kullanıcısı oluştur
sudo useradd --no-create-home --shell /bin/false prometheus

# Dizinleri oluştur
sudo mkdir /etc/prometheus
sudo mkdir /var/lib/prometheus
sudo chown prometheus:prometheus /var/lib/prometheus

# Prometheus'u indir
cd /tmp
wget https://github.com/prometheus/prometheus/releases/download/v2.48.0/prometheus-2.48.0.linux-amd64.tar.gz
tar xvf prometheus-2.48.0.linux-amd64.tar.gz

# Binary dosyaları kopyala
sudo cp prometheus-2.48.0.linux-amd64/prometheus /usr/local/bin/
sudo cp prometheus-2.48.0.linux-amd64/promtool /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/prometheus
sudo chown prometheus:prometheus /usr/local/bin/promtool

# Console dosyalarını kopyala
sudo cp -r prometheus-2.48.0.linux-amd64/consoles /etc/prometheus
sudo cp -r prometheus-2.48.0.linux-amd64/console_libraries /etc/prometheus
sudo chown -R prometheus:prometheus /etc/prometheus

Temel yapılandırma dosyasını oluşturalım:

sudo nano /etc/prometheus/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s
  external_labels:
    datacenter: 'production'
    region: 'tr-east-1'

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - localhost:9093

rule_files:
  - "/etc/prometheus/rules/*.yml"

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node_exporter'
    static_configs:
      - targets:
        - 'web-server-01:9100'
        - 'web-server-02:9100'
        - 'db-server-01:9100'
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance
        regex: '([^:]+):.*'
        replacement: '${1}'

Systemd service dosyası oluşturalım:

sudo nano /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus Monitoring System
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus 
    --config.file /etc/prometheus/prometheus.yml 
    --storage.tsdb.path /var/lib/prometheus/ 
    --storage.tsdb.retention.time=30d 
    --web.console.templates=/etc/prometheus/consoles 
    --web.console.libraries=/etc/prometheus/console_libraries 
    --web.listen-address=0.0.0.0:9090 
    --web.enable-lifecycle

Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable prometheus
sudo systemctl start prometheus
sudo systemctl status prometheus

Node Exporter Kurulumu

Prometheus server kurulduktan sonra, izlemek istediğimiz sunuculara node_exporter kuruyoruz:

# İzlenecek her sunucuda çalıştır
cd /tmp
wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
tar xvf node_exporter-1.7.0.linux-amd64.tar.gz

sudo cp node_exporter-1.7.0.linux-amd64/node_exporter /usr/local/bin/
sudo useradd --no-create-home --shell /bin/false node_exporter
sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter

# Systemd service oluştur
cat << 'EOF' | sudo tee /etc/systemd/system/node_exporter.service
[Unit]
Description=Node Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter 
    --collector.systemd 
    --collector.processes 
    --web.listen-address=:9100

Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable node_exporter
sudo systemctl start node_exporter

# Çalışıp çalışmadığını test et
curl http://localhost:9100/metrics | head -50

Gerçek Dünya Senaryosu: E-ticaret Sitesi İzleme

Diyelim ki bir e-ticaret şirketinde çalışıyorsunuz. 3 web sunucusu, 2 veritabanı sunucusu ve bir Redis cluster’ınız var. Kampanya dönemlerinde sistem nasıl davranıyor? Hangi sunucu darboğaz yaratıyor? Bu soruların cevabını vermek için Prometheus yapılandırması şöyle görünür:

scrape_configs:
  # Web sunucuları
  - job_name: 'web_servers'
    static_configs:
      - targets:
        - 'web-01:9100'
        - 'web-02:9100'
        - 'web-03:9100'
    labels:
      environment: 'production'
      tier: 'web'

  # Nginx metrikleri
  - job_name: 'nginx'
    static_configs:
      - targets:
        - 'web-01:9113'
        - 'web-02:9113'
        - 'web-03:9113'

  # Veritabanı sunucuları
  - job_name: 'mysql'
    static_configs:
      - targets:
        - 'db-primary:9104'
        - 'db-replica:9104'
    labels:
      environment: 'production'
      tier: 'database'

  # Redis cluster
  - job_name: 'redis'
    static_configs:
      - targets:
        - 'redis-01:9121'
        - 'redis-02:9121'

  # Blackbox ile dışarıdan HTTP kontrolü
  - job_name: 'blackbox_http'
    metrics_path: /probe
    params:
      module: [http_2xx]
    static_configs:
      - targets:
        - https://www.siteniz.com
        - https://api.siteniz.com/health
        - https://www.siteniz.com/checkout
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox-exporter:9115

Bu yapılandırmayla artık şu soruların cevabını anlık olarak görebilirsiniz: Ödeme sayfası yüklenebiliyor mu? Veritabanı replica’sı ne kadar geride? Hangi web sunucusunda CPU spike var?

Alert Kuralları Tanımlama

Veriyi toplamak güzel ama asıl değer, anormalliklerde haberdar olmaktan gelir. Temel alert kurallarına bakalım:

# /etc/prometheus/rules/node_alerts.yml
groups:
  - name: node_alerts
    interval: 1m
    rules:
      # Yüksek CPU kullanımı
      - alert: HighCPUUsage
        expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Yüksek CPU kullanımı tespit edildi"
          description: "{{ $labels.instance }} sunucusunda CPU kullanimi {{ $value | printf "%.1f" }}% seviyesinde, 5 dakikadır devam ediyor."

      # Kritik disk dolulugu
      - alert: DiskSpaceCritical
        expr: (node_filesystem_avail_bytes{fstype!~"tmpfs|fuse.lxcfs"} / node_filesystem_size_bytes) * 100 < 10
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Disk alanı kritik seviyede"
          description: "{{ $labels.instance }} sunucusunda {{ $labels.mountpoint }} bölümünde yalnızca %{{ $value | printf "%.1f" }} alan kaldı."

      # RAM kullanımı
      - alert: HighMemoryUsage
        expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Yüksek RAM kullanımı"
          description: "{{ $labels.instance }} sunucusunda RAM kullanimi {{ $value | printf "%.1f" }}%."

      # Sunucu erişilemez
      - alert: InstanceDown
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Sunucu erişilemez durumda"
          description: "{{ $labels.instance }} ({{ $labels.job }}) 1 dakikadır yanıt vermiyor."

Alert kurallarını doğrulamak için promtool kullanın:

promtool check rules /etc/prometheus/rules/node_alerts.yml

PromQL Temel Sorgular

PromQL, Prometheus’un sorgulama dilidir ve başlangıçta karmaşık görünse de mantığını kavradıktan sonra oldukça güçlü hale gelir. Sık kullandığım birkaç örnek:

# Son 1 saatte en çok CPU kullanan 5 sunucu
topk(5, 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[1h])) * 100))

# Disk doluluk hızı: Kaç saat sonra disk dolacak?
predict_linear(node_filesystem_avail_bytes{mountpoint="/"}[6h], 4*3600) < 0

# HTTP 5xx hata oranı yüzde olarak
sum(rate(http_requests_total{status=~"5.."}[5m])) 
  / 
sum(rate(http_requests_total[5m])) * 100

# Sunucu başına ağ trafiği (MB/s)
irate(node_network_receive_bytes_total{device!="lo"}[5m]) / 1024 / 1024

# Veritabanı bağlantı havuzu kullanım oranı
mysql_global_status_threads_connected / mysql_global_variables_max_connections * 100

Veri Saklama ve Performans Ayarları

Prometheus varsayılan olarak 15 gün veri saklar. Production ortamda bu genellikle yeterli değildir. Önemli parametreler şunlardır:

  • –storage.tsdb.retention.time: Veri saklama süresi. 30d, 90d gibi değerler alır
  • –storage.tsdb.retention.size: Maksimum disk kullanımı. 50GB gibi
  • –storage.tsdb.path: Veri dizini
  • –query.max-concurrency: Eş zamanlı sorgu limiti
  • –web.max-connections: Maksimum HTTP bağlantı sayısı

Uzun süreli veri saklamak için Thanos veya VictoriaMetrics gibi çözümlere bakmanızı öneririm. Prometheus’un kendi TSDB’si yatay ölçekleme için tasarlanmamıştır.

Yapılandırmanızı güncelledikten sonra reload etmek için process’i yeniden başlatmak zorunda değilsiniz. --web.enable-lifecycle parametresiyle API üzerinden reload yapabilirsiniz:

# Yapılandırmayı reload et
curl -X POST http://localhost:9090/-/reload

# Yapılandırma dosyasını önceden kontrol et
promtool check config /etc/prometheus/prometheus.yml

Yaygın Hatalar ve Çözümleri

Prometheus kuran herkesin mutlaka karşılaştığı bazı sorunlar vardır:

Scrape zaman aşımı: Hedef yavaş yanıt veriyorsa scrape_timeout değerini artırın ama scrape_interval‘dan küçük tutun.

Çok fazla time series: Her label kombinasyonu ayrı bir time series oluşturur. user_id veya ip_address gibi yüksek kardinaliteli değerleri label olarak kullanmayın. Bu “cardinality explosion” denen soruna yol açar ve Prometheus’u çökertebilir.

Disk alanı tüketimi: Günde yaklaşık her time series için 1-2 byte/saniye hesaplayın. 10.000 time series için günde yaklaşık 1-2 GB disk alanı gerekir.

Zaman senkronizasyonu: Prometheus metriklere timestamp ekler. Sunucular arasında zaman farkı varsa metrikler tutarsız görünür. NTP’nin doğru çalıştığından emin olun.

Sonuç

Prometheus, modern altyapı izlemenin adeta bel kemiği haline gelmiştir. Pull tabanlı mimarisi, güçlü sorgulama dili PromQL ve zengin exporter ekosistemiyle hem küçük ölçekli kurulumlar hem de büyük Kubernetes cluster’ları için sağlam bir temel sunar.

Başlangıçta sadece node_exporter ile birkaç sunucuyu izleyerek başlayın. Metrikleri anlamaya, alert kuralları yazmaya ve yanlış alarmları azaltmaya odaklanın. Zamanla hangi metriklerin sizin için gerçekten değerli olduğunu keşfedeceksiniz. Sonraki adım olarak Grafana ile bu metrikleri görselleştirmek, izleme sistemini tamamlayacaktır.

Unutmayın: İyi bir izleme sistemi sizi sorunlardan korumaz, ama sorunları en kısa sürede tespit etmenizi ve çözmenizi sağlar. Bu da gece 3 telefon aramalarını tarihe gömmek anlamına gelir.

Benzer Konular

Bir yanıt yazın

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