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/metricskomutuyla 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,90dgibi değerler alır - –storage.tsdb.retention.size: Maksimum disk kullanımı.
50GBgibi - –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.
