Гайды

Мониторинг PostgreSQL: Prometheus, Grafana и postgres_exporter

Роль postgres_exporter, scrape в Prometheus, дашборды Grafana, pg_stat_statements и базовые алерты.

~16 мин чтения

Мониторинг PostgreSQL: Prometheus, Grafana и postgres_exporter

Типичный стек: postgres_exporter (метрики с /metrics) → Prometheus (scrape + хранение + правила) → Grafana (дашборды и алерты). Ниже — установка экспортера, job в Prometheus, импорт дашборда и минимальный набор алертов.


Архитектура

  1. postgres_exporter подключается к БД и экспортирует метрики в формате Prometheus (в т.ч. из pg_stat_*).
  2. Prometheus периодически опрашивает :9187/metrics, хранит временные ряды, может слать алерты в Alertmanager.
  3. Grafana использует Prometheus как data source и строит панели.

Пользователь только для мониторинга

sql
CREATE USER postgres_exporter WITH PASSWORD 'YOUR_PASSWORD_HERE';
ALTER USER postgres_exporter SET search_path TO postgres_exporter, public;
GRANT CONNECT ON DATABASE postgres TO postgres_exporter;
GRANT pg_monitor TO postgres_exporter;

Роль pg_monitor даёт чтение большинства нужных представлений. Для pg_stat_statements дополнительно включите расширение и выдайте SELECT (см. ниже).


Установка postgres_exporter (Linux amd64, пример v0.15.0)

bash
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 useradd --no-create-home --shell /bin/false postgres_exporter
sudo chown postgres_exporter:postgres_exporter /usr/local/bin/postgres_exporter

systemd unit

bash
sudo tee /etc/systemd/system/postgres-exporter.service > /dev/null << 'EOF'
[Unit]
Description=PostgreSQL Exporter
Wants=network-online.target
After=network-online.target

[Service]
User=postgres_exporter
Group=postgres_exporter
Type=simple
ExecStart=/usr/local/bin/postgres_exporter \
  --web.listen-address=:9187 \
  --web.telemetry-path=/metrics
Environment=DATA_SOURCE_NAME=postgresql://postgres_exporter:YOUR_PASSWORD_HERE@localhost:5432/postgres?sslmode=disable
Restart=always

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl start postgres-exporter
sudo systemctl enable postgres-exporter

Проверка: http://<host>:9187/metrics — метрики с префиксом pg_. Откройте порт в фаерволе при необходимости:

bash
sudo ufw allow 9187/tcp

Prometheus: scrape_configs

yaml
scrape_configs:
  - job_name: 'postgresql'
    static_configs:
      - targets: ['127.0.0.1:9187']
        labels:
          instance: 'prod-db-01'
          environment: 'production'

После reload/restart Prometheus в Status → Targets job должен быть UP.


Grafana

  1. Configuration → Data sources → Add → Prometheus — URL вашего Prometheus (http://prometheus:9090 и т.д.), Save & test.
  2. Dashboards → Import — можно импортировать популярные дашборды с grafana.com по ID (например, варианты под postgres_exporter периодически обновляются; проверяйте совместимость метрик и версию экспортера).

Примеры PromQL

  • Коммиты: rate(pg_stat_database_xact_commit{datname="mydb"}[1m])
  • Подключения: pg_stat_database_numbackends
  • Размер БД: pg_database_size_bytes
  • Cache hit (оценочно): отношение blks_hit к сумме blks_hit + blks_read через rate(...[5m])
  • Репликационный лаг: метрики семейства pg_replication_* / специфичные к вашему дашборду

Алерты

В Grafana (упрощённо)

Например, доля использованных подключений к лимиту — панель + alert rule с порогом 80% на 5+ минут.

В Prometheus (rules.yml, пример)

yaml
groups:
  - name: postgresql_alerts
    rules:
      - alert: PostgresHighConnections
        expr: (sum(pg_stat_database_numbackends) / max(pg_settings_max_connections)) * 100 > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "High connection usage on {{ $labels.instance }}"

Минимальный набор смысловых алертов:

АлертИдея
База недоступна для scrapeup{job="postgresql"} == 0 или отсутствие ключевых метрик
Высокая утилизация коннектовКак выше
Ошибки экспортераМетрики вида pg_exporter_last_scrape_error (если доступны в вашей версии)

pg_stat_statements

В postgresql.conf:

ini
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.track = all

Перезапуск кластера, затем в целевой БД:

sql
CREATE EXTENSION pg_stat_statements;
GRANT SELECT ON pg_stat_statements TO postgres_exporter;

На дашбордах появятся топы запросов по времени / I/O — без этого «слепые зоны» по SQL.


Kubernetes (набросок service discovery)

yaml
kubernetes_sd_configs:
  - role: pod
relabel_configs:
  - source_labels: [__meta_kubernetes_pod_label_app]
    regex: postgres-exporter
    action: keep

Типичные ошибки

СимптомЧто проверить
Target DOWNsystemctl status postgres-exporter, фаервол, URL в Prometheus
Нет части метрикОтдельный DSN на каждую БД, коллекторы / флаги версии экспортера
500 в логах экспортераscrape_interval, нагрузка на БД от частых запросов метрик
Пустой pg_stat_statementsshared_preload_libraries, перезапуск, CREATE EXTENSION, права

Альтернативы «в коробке»

  • pgwatch2 — сбор + хранение + готовые Grafana-дашборды.
  • Pigsty и др. — для крупных сред с множеством инстансов.

Итог

Начните с отдельного пользователя с минимальными правами, поднимите postgres_exporter как сервис, добавьте scrape в Prometheus, подключите Grafana и импортируйте проверенный дашборд. Затем включите pg_stat_statements и заведите алерты на доступность и saturation — иначе мониторинг декоративен.