MySQL ve PostgreSQL Metriklerini Toplama: Exporter Rehberi

Veritabanı sunucularını izlemek, sistem yöneticiliğinin en kritik görevlerinden biri. MySQL ya da PostgreSQL çöktüğünde veya yavaşladığında, genellikle ilk haberdar olan son kişi oluyoruz. Prometheus ekosisteminin exporter mekanizması tam da bu sorunu çözüyor: veritabanının içinden metrikleri çekip Prometheus’a sunuyor, Grafana da bunları güzel dashboard’lara dönüştürüyor. Bu yazıda hem MySQL Exporter hem de PostgreSQL Exporter’ı sıfırdan kurarak production ortamında nasıl çalıştıracağını göstereceğim.

Genel Mimari: Ne Nereye Bağlanıyor?

Önce kafada netleştirelim. Prometheus pull-based bir sistem, yani metrikleri kendisi gelip alıyor. Exporter’lar bu süreçte aracı görevi yapıyor. Veritabanına bağlanıyor, iç metrikleri sorgulıyor, sonra /metrics endpoint’i üzerinden HTTP olarak sunuyor. Prometheus da belirlediğin aralıklarla bu endpoint’i scrapiyor.

Akış şu şekilde ilerliyor:

  • Veritabanı iç istatistiklerini kendi tablolarında tutuyor (MySQL için information_schema, performance_schema; PostgreSQL için pg_stat_* view’ları)
  • Exporter bu tablolara bağlanıp sorgu atıyor ve metriklere dönüştürüyor
  • Prometheus exporter’ın endpoint’ini periyodik olarak çekiyor
  • Grafana Prometheus’u data source olarak kullanıp görselleştiriyor

Şimdi kolları sıvalım.

MySQL Exporter Kurulumu

Gerekli MySQL Kullanıcısını Oluşturma

Exporter’ın veritabanına bağlanmak için bir kullanıcıya ihtiyacı var. Asla root kullanma. En az yetkili kullanıcı prensibi burada çok önemli. Monitoring için ayrı bir kullanıcı oluşturup sadece gerekli izinleri ver.

mysql -u root -p

MySQL konsoluna girdikten sonra:

CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'GucluBirSifre123!' WITH MAX_USER_CONNECTIONS 3;

GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost';

GRANT SELECT ON performance_schema.* TO 'exporter'@'localhost';

FLUSH PRIVILEGES;

MAX_USER_CONNECTIONS 3 kısmı önemli. Exporter’ın çok fazla bağlantı açmasını engelliyorsun. REPLICATION CLIENT yetkisi replication metriklerini toplamak için gerekiyor; eğer replication kullanmıyorsan bu yetkiyi atlayabilirsin.

Exporter Binary’sini İndirme

# Son sürümü kontrol et: https://github.com/prometheus/mysqld_exporter/releases
cd /tmp
wget https://github.com/prometheus/mysqld_exporter/releases/download/v0.15.1/mysqld_exporter-0.15.1.linux-amd64.tar.gz

tar xvf mysqld_exporter-0.15.1.linux-amd64.tar.gz

sudo mv mysqld_exporter-0.15.1.linux-amd64/mysqld_exporter /usr/local/bin/

sudo chmod +x /usr/local/bin/mysqld_exporter

# Versiyon kontrolü
mysqld_exporter --version

Kimlik Bilgileri Dosyası

Şifreyi komut satırına yazmak güvenlik açığı yaratır. Bunun yerine .my.cnf formatında bir dosya kullan:

sudo mkdir -p /etc/mysqld_exporter
sudo nano /etc/mysqld_exporter/.my.cnf

Dosya içeriği:

[client]
user=exporter
password=GucluBirSifre123!
host=localhost
port=3306
sudo chmod 600 /etc/mysqld_exporter/.my.cnf
sudo chown nobody:nogroup /etc/mysqld_exporter/.my.cnf

Systemd Servis Dosyası

sudo nano /etc/systemd/system/mysqld_exporter.service
[Unit]
Description=MySQL Exporter for Prometheus
After=network.target mysql.service
Wants=mysql.service

[Service]
User=nobody
Group=nogroup
Type=simple
ExecStart=/usr/local/bin/mysqld_exporter 
  --config.my-cnf=/etc/mysqld_exporter/.my.cnf 
  --collect.info_schema.processlist 
  --collect.info_schema.innodb_metrics 
  --collect.info_schema.tablestats 
  --collect.info_schema.tables 
  --collect.info_schema.userstats 
  --collect.engine_innodb_status 
  --collect.perf_schema.eventsstatements 
  --collect.perf_schema.eventsstatementssum 
  --collect.perf_schema.eventswaits 
  --web.listen-address=:9104

Restart=on-failure
RestartSec=5s

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

Çalışıp çalışmadığını test et:

curl -s http://localhost:9104/metrics | grep mysql_up

mysql_up 1 görüyorsan her şey yolunda.

PostgreSQL Exporter Kurulumu

PostgreSQL exporter biraz farklı çalışıyor. postgres_exporter olarak biliniyor ve son yıllarda Prometheus’un resmi exporter’ına dönüştü.

PostgreSQL Kullanıcısı Oluşturma

sudo -u postgres psql
CREATE USER exporter WITH PASSWORD 'PgExporterSifre456!';

-- PostgreSQL 10 ve üzeri için
GRANT pg_monitor TO exporter;

-- Eğer pg_monitor rolü yoksa (eski sürümler için):
GRANT SELECT ON pg_stat_database TO exporter;
GRANT SELECT ON pg_stat_bgwriter TO exporter;
GRANT SELECT ON pg_stat_activity TO exporter;

q

pg_monitor rolü PostgreSQL 10 ile geldi ve monitoring için gereken tüm izinleri kapsıyor. Bu rolü kullanabiliyorsan kesinlikle tercih et.

pg_hba.conf Ayarı

Exporter localhost’tan bağlanacaksa genellikle sorun olmaz, ama kontrol etmekte fayda var:

sudo nano /etc/postgresql/16/main/pg_hba.conf

Şu satırın mevcut olduğuna emin ol:

host    all             exporter        127.0.0.1/32            md5

Değişiklik yaptıysan PostgreSQL’i yeniden yükle:

sudo systemctl reload postgresql

Exporter Kurulumu

cd /tmp
wget https://github.com/prometheus-community/postgres_exporter/releases/download/v0.15.0/postgres_exporter-0.15.0.linux-amd64.tar.gz

tar xvf postgres_exporter-0.15.0.linux-amd64.tar.gz

sudo mv postgres_exporter-0.15.0.linux-amd64/postgres_exporter /usr/local/bin/

sudo chmod +x /usr/local/bin/postgres_exporter

Systemd Servis Dosyası

sudo nano /etc/systemd/system/postgres_exporter.service
[Unit]
Description=PostgreSQL Exporter for Prometheus
After=network.target postgresql.service
Wants=postgresql.service

[Service]
User=nobody
Group=nogroup
Type=simple
Environment=DATA_SOURCE_NAME=postgresql://exporter:PgExporterSifre456!@localhost:5432/postgres?sslmode=disable
ExecStart=/usr/local/bin/postgres_exporter 
  --web.listen-address=:9187 
  --log.level=info

Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

Şifreyi environment variable olarak tutmak yerine ayrı bir dosyada saklamak daha güvenli:

sudo nano /etc/postgres_exporter/env
DATA_SOURCE_NAME=postgresql://exporter:PgExporterSifre456!@localhost:5432/postgres?sslmode=disable
sudo chmod 600 /etc/postgres_exporter/env

Servis dosyasındaki Environment= satırını EnvironmentFile=/etc/postgres_exporter/env ile değiştir.

sudo systemctl daemon-reload
sudo systemctl enable postgres_exporter
sudo systemctl start postgres_exporter

# Test
curl -s http://localhost:9187/metrics | grep pg_up

Prometheus Konfigürasyonunu Güncelleme

Her iki exporter’ı da Prometheus’a eklemen gerekiyor. prometheus.yml dosyasını düzenle:

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

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

  - job_name: 'mysql'
    static_configs:
      - targets: ['localhost:9104']
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance
        regex: '([^:]+)(?::d+)?'
        replacement: '${1}'

  - job_name: 'postgresql'
    static_configs:
      - targets: ['localhost:9187']
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance
        regex: '([^:]+)(?::d+)?'
        replacement: '${1}'
# Konfigürasyonu validate et
promtool check config /etc/prometheus/prometheus.yml

# Prometheus'u yeniden yükle
sudo systemctl reload prometheus

Prometheus UI’da http://localhost:9090/targets adresine gidip her iki target’ın da UP durumda olduğunu doğrula.

Takip Etmen Gereken Kritik Metrikler

MySQL için Önemli Metrikler

Production ortamında mutlaka gözlemlemeniz gereken MySQL metrikleri:

  • mysql_global_status_threads_connected: Anlık bağlantı sayısı. max_connections değerine yaklaşıyorsa alarm.
  • mysql_global_status_slow_queries: Toplam yavaş sorgu sayısı. Sürekli artıyorsa sorun var.
  • mysql_global_status_innodb_buffer_pool_read_requests: Buffer pool hit oranını hesaplamak için kullanılır.
  • mysql_global_status_innodb_buffer_pool_reads: Disk’ten okunan veri miktarı. Bu değer yüksekse buffer pool boyutunu artır.
  • mysql_global_status_aborted_connects: Başarısız bağlantı girişimleri. Güvenlik açısından da önemli.
  • mysql_global_status_questions: Saniyedeki sorgu sayısı (QPS).
  • mysql_slave_status_seconds_behind_master: Replication lag. Sıfır olmalı.

Buffer pool hit oranını Grafana’da hesaplamak için şu PromQL sorgusunu kullanabilirsin:

(mysql_global_status_innodb_buffer_pool_read_requests - mysql_global_status_innodb_buffer_pool_reads) 
/ mysql_global_status_innodb_buffer_pool_read_requests * 100

Bu değer %95’in altına düşmeye başlarsa buffer pool’u büyütmeyi düşün.

PostgreSQL için Önemli Metrikler

  • pg_stat_database_numbackends: Veritabanına açık bağlantı sayısı.
  • pg_stat_database_xact_commit: Commit edilen transaction sayısı.
  • pg_stat_database_xact_rollback: Rollback sayısı. Bu değer yüksekse uygulama hatası var demek.
  • pg_stat_bgwriter_buffers_checkpoint: Checkpoint sırasında yazılan buffer sayısı.
  • pg_stat_database_blks_hit: Cache hit sayısı.
  • pg_stat_database_blks_read: Disk’ten okunan blok sayısı.
  • pg_database_size_bytes: Veritabanı boyutu. Disk dolmadan haber al.
  • pg_stat_replication_pg_wal_lsn_diff: Replication lag byte cinsinden.

Cache hit oranı için PromQL:

pg_stat_database_blks_hit / (pg_stat_database_blks_hit + pg_stat_database_blks_read) * 100

Gerçek Dünya Senaryosu: Bağlantı Havuzu Tükenmesi

Geçen ay bir e-ticaret sitesinde tam alışveriş saatlerinde site yavaşlamaya başladı. Grafana dashboard’una baktığımda mysql_global_status_threads_connected metriğinin max_connections değeri olan 150’ye dayandığını gördüm. Yeni gelen bağlantılar “Too many connections” hatasıyla reddediliyordu.

Sorunun kaynağı şuydu: PHP uygulama sunucularından biri connection pool’u düzgün kapatmıyor, bağlantıları sızdırıyordu. Bu durumu ancak bu metriği izlediğimiz için fark edebildik ve olayı tespit ettiğimizden sonraki 10 dakikada çözüme kavuşturduk.

Bunun için Prometheus’a şu alert kuralını ekledim:

sudo nano /etc/prometheus/rules/mysql_alerts.yml
groups:
  - name: mysql_alerts
    rules:
      - alert: MySQLHighConnectionUsage
        expr: mysql_global_status_threads_connected / mysql_global_variables_max_connections * 100 > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "MySQL bağlantı kullanımı yüksek"
          description: "{{ $labels.instance }} üzerinde bağlantı kullanımı %{{ $value | printf "%.0f" }}'e ulaştı."

      - alert: MySQLDown
        expr: mysql_up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "MySQL sunucusu erişilemiyor"
          description: "{{ $labels.instance }} üzerindeki MySQL'e erişilemiyor."

      - alert: MySQLSlowQueriesHigh
        expr: rate(mysql_global_status_slow_queries[5m]) > 0.5
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Yüksek sayıda yavaş sorgu"
          description: "Son 5 dakikada saniyede {{ $value | printf "%.2f" }} yavaş sorgu çalışıyor."
sudo nano /etc/prometheus/prometheus.yml

rule_files bölümüne ekle:

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

Birden Fazla Veritabanı Sunucusu Yönetimi

Tek sunucu için exporter kurmak kolay, ama 10-15 sunucu varsa işler karmaşıklaşıyor. Bu senaryoda her sunucuya ayrı exporter kurup Prometheus’ta file_sd_config ya da static_configs ile hedef listesini yönetmek en pratik yaklaşım.

sudo mkdir -p /etc/prometheus/targets
sudo nano /etc/prometheus/targets/mysql_targets.json
[
  {
    "targets": ["db01.example.com:9104", "db02.example.com:9104"],
    "labels": {
      "env": "production",
      "role": "mysql"
    }
  },
  {
    "targets": ["db-staging.example.com:9104"],
    "labels": {
      "env": "staging",
      "role": "mysql"
    }
  }
]

prometheus.yml içinde:

- job_name: 'mysql'
  file_sd_configs:
    - files:
        - '/etc/prometheus/targets/mysql_targets.json'
      refresh_interval: 30s

Bu yöntemle Prometheus’u yeniden başlatmadan yeni sunucu ekleyip çıkarabiliyorsun.

Güvenlik Notları

Production’da exporter’ların dışarıya açık olmaması gerekiyor. Prometheus ve exporter’lar arasındaki iletişimi mümkünse internal network’te tut. Eğer farklı sunuculardaysa firewall kuralı ekle:

# Sadece Prometheus sunucusunun erişimine izin ver
sudo ufw allow from 10.0.1.50 to any port 9104 comment "Prometheus MySQL scrape"
sudo ufw allow from 10.0.1.50 to any port 9187 comment "Prometheus PostgreSQL scrape"

# Dışarıdan erişimi engelle
sudo ufw deny 9104
sudo ufw deny 9187

Exporter’ları TLS ile çalıştırmak da mümkün. --web.config.file parametresiyle TLS sertifikası tanımlayabilirsin, ama bu ek konfigürasyon gerektiriyor. İç network’te genellikle buna gerek olmaz.

Sonuç

MySQL Exporter ve PostgreSQL Exporter’ı doğru şekilde kurduğunda veritabanı sunucularının içini gerçek zamanlı olarak görebiliyorsun. Bağlantı sayıları, sorgu hızları, cache hit oranları, replication lag, disk kullanımı – bunların hepsi Grafana dashboard’larında canlı olarak izlenebilir hale geliyor.

En önemli nokta şu: exporter’ları kurmak işin sadece başlangıcı. Asıl değer, anlamlı alertler yazıp bu metrikleri production sorunlarıyla ilişkilendirmeyi öğrenmekten geliyor. “Disk dolmadan 24 saat önce uyar” gibi basit kurallar bile gece yarısı krizlerini önleyebiliyor.

Bir sonraki adım olarak Grafana’da hazır dashboard template’lerini kullanmayı deneyebilirsin. Grafana Dashboard Library’de MySQL için 7362, PostgreSQL için 9628 ID’li dashboard’lar topluluk tarafından çok kullanılan ve iyi hazırlanmış seçenekler. Import edip üzerine kendi ihtiyaçlarına göre düzenlersen zaman kazanırsın.

Benzer Konular

Bir yanıt yazın

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