Nginx ve Apache Metrikleri: Prometheus ile İzleme
Web sunucularının ne kadar meşgul olduğunu, kaç isteği karşıladığını ya da nerede darboğaz yaşandığını bilmeden bir sistemi yönetmek, gözleri kapalı araba kullanmak gibidir. Prometheus ve exporter’lar bu noktada devreye girerek ham log satırlarını anlamlı metriklere dönüştürür. Bu yazıda Nginx ve Apache için Prometheus entegrasyonunu sıfırdan kuracak, gerçek dünya senaryolarıyla metriklerin nasıl yorumlanacağını göreceğiz.
Genel Mimariyi Anlamak
Prometheus, pull tabanlı bir izleme sistemidir. Yani sunucuya gidip “ne durumdasın?” diye sorar, sunucu cevaplar. Bu cevaplar exporter adı verilen küçük ajanlar aracılığıyla gelir. Nginx için nginx-prometheus-exporter, Apache için ise apache_exporter kullanacağız.
Akış şu şekilde işler:
- Nginx veya Apache, dahili bir durum sayfası (
/stub_statusveya/server-status) yayınlar - Exporter bu sayfayı okur ve Prometheus’un anlayacağı formata çevirir
- Prometheus belirlenen aralıklarla exporter’ı scrape eder
- Grafana bu verileri görselleştirir
Bunu gerçek bir senaryo üzerinden düşünelim: E-ticaret sitenizdeki bir kampanya gecesi trafik 10 katına çıkıyor. Anlık aktif bağlantı sayısı, istek hızı ve hata oranlarını göremezseniz bir şeyler patladığında müdahale etmek için çok geç olabilir.
Nginx Tarafını Hazırlamak
stub_status Modülünü Aktifleştirme
Nginx, yerleşik ngx_http_stub_status_module modülüyle basit metrikler sunar. Önce modülün derlenmiş olup olmadığını kontrol edelim:
nginx -V 2>&1 | grep -o with-http_stub_status_module
Çıktıda with-http_stub_status_module görüyorsanız hazırsınız. Çoğu paket yöneticisinden kurulan Nginx’te bu modül varsayılan olarak gelir.
Şimdi /stub_status endpoint’ini tanımlayalım. Bunu doğrudan site konfigürasyonuna eklemek yerine ayrı bir dosyaya almak daha temiz bir yaklaşım:
cat > /etc/nginx/conf.d/stub_status.conf << 'EOF'
server {
listen 127.0.0.1:8080;
server_name localhost;
location /stub_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
}
EOF
Burada birkaç kritik nokta var. 127.0.0.1:8080 ile sadece localhost’tan erişime açıyoruz çünkü exporter aynı sunucuda çalışacak. access_log off satırı ise her Prometheus scrape’inin log dosyasına yazılmasını engelliyor; aksi halde log dosyalarınız saatler içinde şişer.
Konfigürasyonu test edip uygulayalım:
nginx -t && systemctl reload nginx
Endpoint’in çalıştığını doğrulamak için:
curl http://127.0.0.1:8080/stub_status
Çıktı şuna benzer bir şey olmalı:
Active connections: 43
server accepts handled requests
1523847 1523847 4271239
Reading: 0 Writing: 1 Waiting: 42
nginx-prometheus-exporter Kurulumu
GitHub releases sayfasından en güncel binary’yi indirelim:
cd /tmp
NGINX_EXPORTER_VERSION="1.1.0"
wget https://github.com/nginxinc/nginx-prometheus-exporter/releases/download/v${NGINX_EXPORTER_VERSION}/nginx-prometheus-exporter_${NGINX_EXPORTER_VERSION}_linux_amd64.tar.gz
tar xzf nginx-prometheus-exporter_${NGINX_EXPORTER_VERSION}_linux_amd64.tar.gz
mv nginx-prometheus-exporter /usr/local/bin/
chmod +x /usr/local/bin/nginx-prometheus-exporter
Systemd servisi oluşturalım. Bu adımı es geçmeyin; manuel çalıştırılan exporter’lar sunucu restart’larında kaybolur:
cat > /etc/systemd/system/nginx-exporter.service << 'EOF'
[Unit]
Description=Nginx Prometheus Exporter
After=network.target nginx.service
[Service]
Type=simple
User=nobody
Group=nobody
ExecStart=/usr/local/bin/nginx-prometheus-exporter
--nginx.scrape-uri=http://127.0.0.1:8080/stub_status
--web.listen-address=:9113
--web.telemetry-path=/metrics
Restart=always
RestartSec=5
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now nginx-exporter
--web.listen-address=:9113 ile exporter’ın 9113 portunda yayın yapmasını sağlıyoruz. Bu Nginx exporter için standart port numarasıdır. Ekstra güvenlik için NoNewPrivileges ve ProtectSystem direktifleri ekledik.
Çalıştığını kontrol edelim:
curl http://localhost:9113/metrics | grep nginx_
Apache Tarafını Hazırlamak
mod_status Aktivasyonu
Apache’nin yerleşik durum modülü mod_status‘tur. Debian/Ubuntu sistemlerde:
a2enmod status
CentOS/RHEL sistemlerde genellikle zaten aktiftir ama konfigürasyon dosyasını düzenlememiz gerekir.
/etc/apache2/mods-enabled/status.conf veya /etc/httpd/conf.d/server-status.conf dosyasını şu şekilde yapılandıralım:
cat > /etc/apache2/conf-available/server-status.conf << 'EOF'
<Location "/server-status">
SetHandler server-status
Require ip 127.0.0.1
Require ip ::1
</Location>
ExtendedStatus On
EOF
a2enconf server-status
systemctl reload apache2
ExtendedStatus On satırı çok önemli. Bu direktif olmadan Apache yalnızca temel sayaçları sunar; CPU kullanımı, request başına süre gibi detaylı metriklere ulaşamazsınız.
Doğrulama:
curl http://127.0.0.1/server-status?auto
?auto parametresi çıktıyı makine tarafından okunabilir formata çevirir. Bu çıktı exporter tarafından parse edilecek.
apache_exporter Kurulumu
cd /tmp
APACHE_EXPORTER_VERSION="1.0.6"
wget https://github.com/Lusitaniae/apache_exporter/releases/download/v${APACHE_EXPORTER_VERSION}/apache_exporter-${APACHE_EXPORTER_VERSION}.linux-amd64.tar.gz
tar xzf apache_exporter-${APACHE_EXPORTER_VERSION}.linux-amd64.tar.gz
mv apache_exporter-${APACHE_EXPORTER_VERSION}.linux-amd64/apache_exporter /usr/local/bin/
chmod +x /usr/local/bin/apache_exporter
Systemd servis dosyası:
cat > /etc/systemd/system/apache-exporter.service << 'EOF'
[Unit]
Description=Apache Prometheus Exporter
After=network.target apache2.service
[Service]
Type=simple
User=nobody
Group=nobody
ExecStart=/usr/local/bin/apache_exporter
--scrape_uri=http://127.0.0.1/server-status?auto
--telemetry.address=:9117
--telemetry.endpoint=/metrics
Restart=always
RestartSec=5
NoNewPrivileges=yes
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now apache-exporter
Apache exporter’ın standart portu 9117‘dir.
Prometheus’u Yapılandırmak
Hem Nginx hem de Apache exporter’larını Prometheus’a ekleyelim. prometheus.yml dosyanıza scrape job’larını ekleyin:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'nginx'
static_configs:
- targets: ['localhost:9113']
scrape_interval: 10s
metrics_path: /metrics
- job_name: 'apache'
static_configs:
- targets: ['localhost:9117']
scrape_interval: 10s
metrics_path: /metrics
- job_name: 'nginx-prod-cluster'
static_configs:
- targets:
- 'web01.sirket.com:9113'
- 'web02.sirket.com:9113'
- 'web03.sirket.com:9113'
relabel_configs:
- source_labels: [__address__]
target_label: instance
regex: '([^:]+):.*'
replacement: '$1'
Birden fazla web sunucusu olan ortamlar için relabel_configs bölümünü ekledik. Bu sayede port numarası olmadan sadece hostname görünür, Grafana dashboard’larında okunabilirlik artar.
Prometheus’u yeniden yükleyin:
systemctl reload prometheus
Prometheus web arayüzünde (http://prometheus-ip:9090/targets) her iki target’ın da UP durumda olduğunu görmelisiniz.
Önemli Metrikler ve Anlamları
Nginx Metrikleri
nginx-prometheus-exporter şu ana metrikleri sunar:
nginx_connections_active: Şu anda işlenen aktif bağlantı sayısı. Ani artışlar DDoS ya da uygulama katmanı sorununu işaret edebilir.nginx_connections_reading: Header okunmakta olan bağlantılar. Yüksek değer yavaş istemcilere ya da büyük header boyutlarına işaret eder.nginx_connections_writing: Yanıt yazılan bağlantılar. Upstream uygulama yavaşsa bu değer artar.nginx_connections_waiting: Keepalive bağlantıları. Yüksek bekleyen bağlantı sayısı genellikle normaldir.nginx_http_requests_total: Toplam HTTP istek sayısı (counter). Rate hesaplamak için kullanılır.
İstek hızını hesaplamak için Prometheus’ta şu PromQL sorgusunu kullanabilirsiniz:
rate(nginx_http_requests_total[5m])
Bu sorgu, son 5 dakikadaki ortalama saniyedeki istek sayısını verir.
Apache Metrikleri
apache_accesses_total: Toplam istek sayısı.nginx_http_requests_totalile aynı mantık.apache_workers:busyveidleetiketleriyle çalışan worker thread’leri gösterir.busydeğeriMaxRequestWorkers‘a yaklaşıyorsa sorun var demektir.apache_scoreboard: Her worker’ın durumunu gösterir.open,waiting,starting,reading,sending_replygibi state’ler.apache_cpuload: Apache süreçlerinin toplam CPU yükü.apache_duration_ms_total: Toplam istek süresi. Rate ile bölüp ortalama yanıt süresini hesaplayabilirsiniz.
Ortalama istek süresini hesaplamak için:
rate(apache_duration_ms_total[5m]) / rate(apache_accesses_total[5m])
Alertmanager ile Uyarı Kuralları
Metrikleri izlemek güzel, ama bir şeyler yanlış gittiğinde haberdar olmanız gerekiyor. Prometheus alert kuralları tanımlayalım:
# /etc/prometheus/rules/webserver_alerts.yml
groups:
- name: nginx_alerts
rules:
- alert: NginxDown
expr: nginx_up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Nginx sunucusu erişilemiyor"
description: "{{ $labels.instance }} sunucusunda Nginx metrikleri alınamıyor."
- alert: NginxHighConnectionCount
expr: nginx_connections_active > 500
for: 5m
labels:
severity: warning
annotations:
summary: "Nginx aktif bağlantı sayısı yüksek"
description: "{{ $labels.instance }} sunucusunda aktif bağlantı sayısı {{ $value }} oldu."
- alert: NginxHighRequestRate
expr: rate(nginx_http_requests_total[5m]) > 1000
for: 2m
labels:
severity: warning
annotations:
summary: "Nginx saniyedeki istek sayısı 1000'i aştı"
description: "Mevcut istek hızı: {{ $value | humanize }} req/s"
- name: apache_alerts
rules:
- alert: ApacheWorkersNearLimit
expr: apache_workers{state="busy"} / (apache_workers{state="busy"} + apache_workers{state="idle"}) > 0.9
for: 3m
labels:
severity: critical
annotations:
summary: "Apache worker havuzu dolmak üzere"
description: "Worker kullanım oranı %{{ $value | humanizeSI }}"
prometheus.yml dosyasına bu kural dosyasını ekleyin:
rule_files:
- "rules/webserver_alerts.yml"
Grafana Dashboard Kurulumu
Grafana’da hazır dashboard kullanmak zaman kazandırır. Nginx exporter için dashboard ID 12708, Apache için 11916 kullanabilirsiniz. Bunları Grafana’da Dashboards > Import menüsünden yükleyebilirsiniz.
Özel bir panel oluşturmak isteyenler için bazı faydalı PromQL sorguları:
Aktif bağlantıların zaman serisi grafiği için:
nginx_connections_active{instance="$instance"}
Apache worker doluluk oranı için:
apache_workers{state="busy"} / on(instance) (apache_workers{state="busy"} + apache_workers{state="idle"}) * 100
Saniyedeki istek artış hızı için (ikinci türev, trafik spike’larını yakalamak için):
deriv(rate(nginx_http_requests_total[5m])[10m:1m])
Gerçek Dünya Senaryosu: Yavaşlayan Site Analizi
Bir gece saat 02:00’da uyarı geliyor: “Site yavaş.” Grafana’yı açtığınızda şunları görüyorsunuz:
Nginx active connections grafiği normalin 3 katında, writing durumundaki bağlantılar yüksek ama reading normal. Bu pattern şunu söylüyor: istekler alınıyor, işleniyor ama yanıtlar yazılamıyor. Yani upstream (PHP-FPM, uygulama sunucusu) yavaşlamış olabilir.
Apache senaryosunda ise apache_workers{state="busy"} değerinin MaxRequestWorkers sınırına dayandığını görürsünüz. Bu noktada ya MaxRequestWorkers değerini artırmanız ya da uygulamayı hızlandırmanız gerekir.
Daha derin analiz için Nginx access log’larını ve uygulama metriklerini korelasyon yaparak incelemeniz gerekir. Prometheus metrikleri size “ne zaman” ve “ne kadar” sorusunu yanıtlar, “neden” sorusu için log analizi devreye girer.
Güvenlik Konuları
Exporter portlarını (9113, 9117) internete açmayın. Prometheus sunucusuna olan trafiği güvenlik duvarı ile sınırlayın:
# Sadece Prometheus sunucusunun erişmesine izin ver
ufw allow from 10.0.1.50 to any port 9113
ufw allow from 10.0.1.50 to any port 9117
Eğer Prometheus ve exporter’lar farklı network segmentlerindeyse TLS kullanmak için exporter’lara --web.config.file parametresiyle sertifika tanımlanabilir. Küçük ve kapalı ortamlarda bu genellikle fazla karmaşıklık yaratır ama üretim ortamlarında göz ardı edilmemeli.
/stub_status ve /server-status endpoint’lerine sadece localhost’tan erişim kuralı zaten oluşturduk. Ancak bunu düzenli olarak denetleyin; Nginx konfigürasyon değişikliklerinde bu kurallar yanlışlıkla devre dışı kalabilir.
Çoklu Sunucu Ortamlarında Service Discovery
Onlarca web sunucusu olan bir ortamda her birini elle prometheus.yml‘e eklemek sürdürülebilir değil. Consul veya dosya tabanlı service discovery kullanabilirsiniz:
scrape_configs:
- job_name: 'nginx-fleet'
file_sd_configs:
- files:
- '/etc/prometheus/targets/nginx_*.yml'
refresh_interval: 30s
Hedef dosyası şu formatta olur:
# /etc/prometheus/targets/nginx_web_tier.yml
- targets:
- 'web01:9113'
- 'web02:9113'
- 'web03:9113'
labels:
tier: 'web'
env: 'production'
datacenter: 'istanbul'
Yeni sunucu eklediğinizde sadece bu dosyayı güncellemeniz yeterli, Prometheus otomatik algılar.
Performans Etkisi
Exporter’ların kendi kaynak tüketimi genellikle ihmal edilebilir seviyededir. nginx-prometheus-exporter tipik bir sunucuda 5-10 MB RAM ve scrape başına birkaç milisaniye CPU kullanır. Ancak scrape aralığını 5 saniyenin altına düşürmeyin; bu, /stub_status endpoint’ine gereksiz yük bindirir ve faydalı ek bilgi sağlamaz. 10-15 saniyelik aralıklar çoğu senaryo için yeterli hassasiyeti sunar.
Sonuç
Nginx ve Apache metriklerini Prometheus ile izlemek, sistem yönetiminin reaktif olmaktan çıkıp proaktif hale gelmesi anlamına geliyor. Stub status’tan başlayan bu pipeline; exporter, Prometheus ve Grafana ile birleşerek gerçek zamanlı görünürlük sağlıyor. Aktif bağlantılar, worker doluluk oranları ve istek hızları gibi temel metrikler, bir sorun tam olarak patlamadan önce size sinyal veriyor.
Bu yazıda anlattıklarımız temel seviye; üzerine uygulama katmanı latency metrikleri, upstream sağlık kontrolleri ve log tabanlı hata oranı hesaplamaları eklendiğinde çok daha kapsamlı bir izleme altyapısına ulaşabilirsiniz. Başlangıç için stub_status ve mod_status’u devreye alın, alertleri kurun ve bir hafta boyunca normal trafik pattern’larını gözlemleyin. Baseline olmadan uyarı eşikleri belirlemek doğru olmaz; önce sistemin nabzını tanıyın, sonra uyarıları ince ayarlayın.
