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çinpg_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_connectionsdeğ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.
