Nginx ile Prometheus Metrics ve Grafana İzleme Kurulumu

Production ortamında bir Nginx sunucusu çalıştırıyorsunuz, trafik geliyor, istekler işleniyor. Peki sunucunuzun gerçekten sağlıklı olup olmadığını, kaç isteği reddettiğini, yanıt sürelerinin ne durumda olduğunu biliyor musunuz? “Bir şeyler ters gidince bakarız” yaklaşımı sysadmin’in en büyük düşmanıdır. Bu yazıda Nginx metriklerini Prometheus ile toplamayı ve Grafana üzerinde anlamlı dashboardlar oluşturmayı adım adım ele alacağız.

Genel Mimariyi Anlamak

Önce büyük resmi görelim. Bu izleme zinciri şu şekilde çalışır:

  • Nginx: stub_status modülü ile temel metrikler sunar veya nginx-prometheus-exporter daha zengin veri sağlar
  • Prometheus Exporter: Nginx’ten metrikleri çekip Prometheus’un anlayacağı formata çevirir
  • Prometheus: Metrikleri düzenli aralıklarla “scrape” eder ve zaman serisi veritabanında saklar
  • Grafana: Prometheus’u veri kaynağı olarak kullanarak görselleştirme yapar

Bu zincirde en kritik halka exporter katmanıdır. Nginx kendi başına Prometheus formatında veri üretmez, bu yüzden bir aracıya ihtiyaç duyarız.

Nginx Stub Status Modülünü Aktif Etmek

Her şeyden önce Nginx’in stub_status modülünün aktif olup olmadığını kontrol edin:

nginx -V 2>&1 | grep -o with-http_stub_status_module

Eğer çıktı with-http_stub_status_module dönüyorsa hazırsınız. Ubuntu/Debian üzerinde nginx paketi genellikle bu modülle birlikte gelir. CentOS/RHEL için nginx resmi reposundan kurulum yapmanızı öneririm.

Şimdi Nginx konfigürasyonuna stub_status endpoint’i ekleyelim:

sudo nano /etc/nginx/conf.d/stub_status.conf
server {
    listen 127.0.0.1:8080;
    server_name localhost;

    location /nginx_status {
        stub_status on;
        access_log off;
        # Sadece localhost ve monitoring sunucusuna izin ver
        allow 127.0.0.1;
        allow 10.0.0.0/8;    # İç ağ subnet'iniz
        deny all;
    }
}

Bu konfigürasyonda dikkat edilmesi gereken nokta: stub_status endpoint’ini public internete açmayın. Sadece monitoring sunucunuzun IP’sine izin verin. Konfigürasyonu test edip reload edelim:

sudo nginx -t && sudo systemctl reload nginx

Endpoint’in çalıştığını doğrulayalım:

curl http://127.0.0.1:8080/nginx_status

Çıktı şöyle görünmeli:

Active connections: 42
server accepts handled requests
 1024 1024 8192
Reading: 2 Writing: 5 Waiting: 35

Bu ham veriler Prometheus için uygun değil, burada exporter devreye giriyor.

Nginx Prometheus Exporter Kurulumu

nginx-prometheus-exporter, Nginx’in stub_status çıktısını Prometheus formatına dönüştüren hafif bir Go uygulamasıdır. GitHub üzerinden binary olarak indirip kullanabiliriz.

# En güncel versiyonu GitHub'dan kontrol edin
cd /tmp
wget https://github.com/nginxinc/nginx-prometheus-exporter/releases/download/v1.1.0/nginx-prometheus-exporter_1.1.0_linux_amd64.tar.gz
tar -xzf nginx-prometheus-exporter_1.1.0_linux_amd64.tar.gz
sudo mv nginx-prometheus-exporter /usr/local/bin/
sudo chmod +x /usr/local/bin/nginx-prometheus-exporter

Exporter’ı sistemd servisi olarak çalıştıralım:

sudo nano /etc/systemd/system/nginx-prometheus-exporter.service
[Unit]
Description=Nginx Prometheus Exporter
After=network.target

[Service]
Type=simple
User=prometheus
Group=prometheus
ExecStart=/usr/local/bin/nginx-prometheus-exporter 
    -nginx.scrape-uri=http://127.0.0.1:8080/nginx_status 
    -web.listen-address=:9113 
    -web.telemetry-path=/metrics
Restart=on-failure
RestartSec=5s
NoNewPrivileges=yes
ProtectHome=yes
ProtectSystem=strict

[Install]
WantedBy=multi-user.target

Prometheus kullanıcısı mevcut değilse oluşturun:

sudo useradd --no-create-home --shell /bin/false prometheus
sudo systemctl daemon-reload
sudo systemctl enable --now nginx-prometheus-exporter
sudo systemctl status nginx-prometheus-exporter

Exporter’ın metrik üretip üretmediğini kontrol edin:

curl http://localhost:9113/metrics | head -30

nginx_connections_active, nginx_http_requests_total gibi metrikler görüyorsanız her şey yolunda demektir.

Prometheus Kurulumu ve Konfigürasyonu

Eğer ortamınızda Prometheus zaten varsa bu bölümü atlayabilirsiniz. Yoksa hızlıca kuralım:

cd /tmp
wget https://github.com/prometheus/prometheus/releases/download/v2.48.0/prometheus-2.48.0.linux-amd64.tar.gz
tar -xzf prometheus-2.48.0.linux-amd64.tar.gz
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 mkdir -p /etc/prometheus /var/lib/prometheus
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 /var/lib/prometheus

Prometheus ana konfigürasyon dosyasını düzenleyelim:

sudo nano /etc/prometheus/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s
  scrape_timeout: 10s

alerting:
  alertmanagers:
    - static_configs:
        - targets: []

rule_files: []

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

  - job_name: 'nginx'
    static_configs:
      - targets: ['localhost:9113']
    metrics_path: /metrics
    scrape_interval: 10s
    # Nginx sunucusunu etiketle
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance
        replacement: 'web-server-01'

Birden fazla Nginx sunucusu izliyorsanız targets listesini genişletin:

  - job_name: 'nginx'
    static_configs:
      - targets:
          - '10.0.0.10:9113'
          - '10.0.0.11:9113'
          - '10.0.0.12:9113'
    metrics_path: /metrics
    scrape_interval: 10s

Konfigürasyonu doğrulayın:

promtool check config /etc/prometheus/prometheus.yml

Prometheus’u systemd servisi olarak başlatın ve birkaç dakika bekledikten sonra http://sunucu-ip:9090/targets adresinden scrape durumunu kontrol edin. Nginx job’ının “UP” durumunda olması gerekiyor.

Gerçek Dünya Senaryosu: Çoklu Nginx Instance İzleme

Diyelim ki yük dengeleyici arkasında 3 adet uygulama sunucusu var. Her birinde Nginx çalışıyor ve farklı servislere proxy yapıyor. Bu durumda her sunucuya exporter kurup Prometheus’a ekliyoruz, ancak etiketleri doğru yönetmek kritik:

  - job_name: 'nginx-web-cluster'
    static_configs:
      - targets: ['10.0.1.10:9113']
        labels:
          environment: 'production'
          role: 'frontend'
          datacenter: 'istanbul-dc1'
      - targets: ['10.0.1.11:9113']
        labels:
          environment: 'production'
          role: 'api-gateway'
          datacenter: 'istanbul-dc1'
      - targets: ['10.0.1.12:9113']
        labels:
          environment: 'staging'
          role: 'frontend'
          datacenter: 'ankara-dc2'

Bu etiket yapısı Grafana’da filtreleme ve karşılaştırma yapmayı çok kolaylaştırır.

Grafana Kurulumu

# Ubuntu/Debian için
sudo apt-get install -y apt-transport-https software-properties-common
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt-get update && sudo apt-get install grafana
sudo systemctl enable --now grafana-server

Grafana varsayılan olarak 3000 portunda çalışır. İlk giriş için admin/admin kullanıcı adı ve şifresiyle giriş yapın, ardından şifreyi değiştirmeyi unutmayın.

Prometheus Veri Kaynağı Ekleme

Grafana web arayüzünde:

  • Sol menüden Connections > Data Sources seçin
  • Add data source butonuna tıklayın
  • Prometheus’u seçin
  • URL alanına http://localhost:9090 girin (Prometheus aynı sunucudaysa)
  • Save & Test butonuna basın

Yeşil “Data source is working” mesajı görmelisiniz.

Grafana’da Nginx Dashboard Oluşturma

Grafana’nın hazır dashboard ekosistemi çok güçlü. Nginx için en popüler dashboard ID’si 9614‘tür (NGINX Prometheus Exporter). Bunu import etmek için:

  • Sol menüden Dashboards > Import seçin
  • Import via grafana.com alanına 9614 yazın
  • Load butonuna basın
  • Veri kaynağı olarak eklediğiniz Prometheus’u seçin
  • Import edin

Bu hazır dashboard ile anında birçok metriği görebilirsiniz. Ancak production ortamı için özelleştirilmiş paneller oluşturmanızı öneririm.

Kritik PromQL Sorguları

Grafana panel oluştururken kullanacağınız PromQL sorgularını paylaşayım:

Saniyedeki istek sayısı (RPS):

rate(nginx_http_requests_total[5m])

Aktif bağlantı sayısı:

nginx_connections_active

Bağlantı durumlarına göre breakdown:

nginx_connections_reading
nginx_connections_writing
nginx_connections_waiting

Son 1 saatteki toplam istekler:

increase(nginx_http_requests_total[1h])

Accept oranı ile handled oranı karşılaştırması (drop’ları yakalar):

rate(nginx_connections_accepted_total[5m])
rate(nginx_connections_handled_total[5m])

Bu iki değer arasındaki fark, düşürülen bağlantı sayısını gösterir. Production’da bu farkın sıfır olması gerekir. Fark varsa worker_connections limitine takılıyorsunuzdur.

Alerting: Kritik Uyarılar Oluşturma

Görselleştirme güzel ama asıl önemli olan sorunları erkenden yakalamak. Prometheus’a alert kuralları ekleyelim:

sudo nano /etc/prometheus/nginx_alerts.yml
groups:
  - name: nginx_alerts
    interval: 30s
    rules:
      - alert: NginxDown
        expr: nginx_up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Nginx servis durdu - {{ $labels.instance }}"
          description: "{{ $labels.instance }} üzerindeki Nginx 1 dakikadır yanıt vermiyor."

      - alert: NginxHighConnectionDrop
        expr: rate(nginx_connections_accepted_total[5m]) - rate(nginx_connections_handled_total[5m]) > 0
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "Nginx bağlantı kaybı tespit edildi"
          description: "Saniyede {{ $value }} bağlantı düşürülüyor. worker_connections limitini kontrol edin."

      - alert: NginxHighActiveConnections
        expr: nginx_connections_active > 1000
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Nginx aktif bağlantı sayısı yüksek"
          description: "Aktif bağlantı sayısı {{ $value }} seviyesinde. Kapasite planlaması gerekebilir."

      - alert: NginxRequestRateSpike
        expr: rate(nginx_http_requests_total[5m]) > 10000
        for: 3m
        labels:
          severity: warning
        annotations:
          summary: "Nginx istek oranı spike yapıyor"
          description: "Saniyede {{ $value }} istek geliyor. DDoS veya anormal trafik olabilir."

Bu kural dosyasını prometheus.yml‘e ekleyin:

rule_files:
  - /etc/prometheus/nginx_alerts.yml

Prometheus’u reload edin:

sudo systemctl reload prometheus
# veya
curl -X POST http://localhost:9090/-/reload

Nginx Log’larını da İşin İçine Katmak

Stub_status sadece toplam sayıları verir, HTTP durum kodlarına göre breakdown görmez. Bunun için iki seçeneğiniz var:

1. Seçenek: Nginx Plus (ticari, extended status)

2. Seçenek: VTS modülü (nginx-module-vts, community)

VTS modülü varsa çok daha zengin metrikler elde edersiniz. Ubuntu’da şöyle kurabilirsiniz:

sudo apt-get install libnginx-mod-http-vhost-traffic-status

Nginx konfigürasyonuna ekleyin:

http {
    vhost_traffic_status_zone;
    
    server {
        location /status {
            vhost_traffic_status_display;
            vhost_traffic_status_display_format prometheus;
            allow 127.0.0.1;
            deny all;
        }
    }
}

Bu durumda exporter’a gerek kalmaz, doğrudan Prometheus /status endpoint’ini scrape edebilir. Bu metriklerle durum kodu bazlı hata oranı gibi kritik göstergeleri izleyebilirsiniz.

Grafana Dashboard’ını Özelleştirmek

İyi bir Nginx dashboard’u şu panelleri içermelidir:

  • RPS (Request Per Second): Anlık yük durumu
  • Aktif Bağlantılar: Zaman serisi grafiği, peak’leri görmek için
  • Reading/Writing/Waiting: Bağlantı durumu dağılımı (stacked area)
  • Accepted vs Handled: Drop rate tespiti için
  • Uptime: Nginx’in ne zamandır ayakta olduğu
  • Alert durumu: Hangi alertların aktif olduğu

Her panel için Stat, Time series, Gauge widget tiplerini duruma göre kullanın. Anlık değerler için Stat, trend analizi için Time series idealdir.

Panel düzenleme sırasında şu ayarlara dikkat edin:

  • Thresholds: Kritik değerlere kırmızı renk atayin (örneğin aktif bağlantı 800’ü geçince sarı, 1000’i geçince kırmızı)
  • Alert rules: Panel bazında Grafana alert’ı da ekleyebilirsiniz
  • Refresh interval: Production dashboard’ları için 30 saniye makul bir değer

Güvenlik Notları

Bu kurulumda dikkat etmeniz gereken birkaç güvenlik konusu var:

  • stub_status endpoint’i: Kesinlikle sadece internal ağa açın, nginx.conf üzerindeki allow/deny direktiflerini doğru yapılandırın
  • Exporter portu (9113): Firewall’da sadece Prometheus sunucusunun erişimine izin verin
  • Prometheus (9090): Dışarıya açmayın, Grafana’nın internal’dan erişmesi yeterli
  • Grafana (3000): Reverse proxy arkasına alın, HTTPS kullanın
# UFW ile exporter'ı sadece Prometheus sunucusuna aç
sudo ufw allow from 10.0.0.5 to any port 9113 comment 'Prometheus scrape'
sudo ufw deny 9113

Sorun Giderme

Kurulum sürecinde sık karşılaşılan sorunlar:

Exporter “connection refused” hatası veriyorsa:

# stub_status'ün dinlediği portu kontrol et
ss -tlnp | grep 8080
# Nginx konfigürasyonunu test et
sudo nginx -t
# Exporter loglarına bak
sudo journalctl -u nginx-prometheus-exporter -f

Prometheus’ta target “DOWN” görünüyorsa:

# Exporter'ın ayakta olup olmadığını kontrol et
curl http://localhost:9113/metrics
# Firewall kurallarını kontrol et
sudo iptables -L -n | grep 9113

Grafana’da “No data” görünüyorsa:

# Prometheus'ta metriğin var olduğunu doğrula
curl 'http://localhost:9090/api/v1/query?query=nginx_connections_active'
# Zaman aralığını ve job adını kontrol et

Sonuç

Nginx’i Prometheus ve Grafana ile izlemek başlangıçta birkaç kurulum adımı gerektirse de kazanımları çok büyük. Artık sunucunuzda neler döndüğünü gerçek zamanlı görüyor, anormalliklerden anında haberdar oluyorsunuz. “Müşteri şikayet etti, biz de fark ettik” dönemini geride bırakıyorsunuz.

Bu mimarinin güzel yanı ölçeklenebilirliği: 1 sunucu izlemek için kurduğunuz yapıya 50 sunucu eklemek sadece Prometheus konfigürasyonuna birkaç satır eklemek anlamına geliyor. Etiket sistemi sayesinde ortam, lokasyon, rol gibi boyutlarda filtreleme yapabiliyorsunuz.

Bir sonraki adım olarak blackbox_exporter ile HTTP endpoint kontrolü ve alertmanager ile Slack/PagerDuty entegrasyonu kurmanızı öneririm. O zaman gerçekten proaktif bir izleme altyapısına kavuşmuş olursunuz. Production’da “her şey yolunda” demek için ekranda yeşil ışıklar yanıyor olmalı, tahminlere değil.

Yorum yapın