PostgreSQL監視:情報の「盲点」からプロフェッショナルなアラートシステム構築まで

Database tutorial - IT technology blog
Database tutorial - IT technology blog

午前2時の電話と「無機質な」数字たち

真夜中、デスクの上でスマートフォンが激しく震えました。Slackは 504 Gateway Timeout の通知で溢れかえっています。アプリケーションログを確認すると、Connection pool exhausted というエラーが延々と続いていました。急いでサーバーにSSHで入り、top コマンドを叩くと、CPU使用率は90%に跳ね上がっています。しかし、どのクエリがリソースを食いつぶしているのか、いくつのトランザクションがハングしているのか、全く分かりませんでした。

その時の感覚は、まるでヘッドライトなしで霧の中を高速走行しているようでした。もし十分な監視システムがあれば、1時45分の時点でコネクション数の急増に気づき、システムが「崩壊」する前に対処できていたはずです。この記事は、そんな苦い経験から得た教訓をまとめ、PostgreSQLに鋭い「目」を持たせるためのガイドです。

クイックスタート:5分でダッシュボードを構築

迅速なデバッグやテストには、Docker Composeが最適です。一つの設定ファイルだけで、複雑なインストール作業なしに監視スタック全体を構築できます。

# docker-compose.yml
version: '3.8'
services:
  postgres_exporter:
    image: prometheuscommunity/postgres-exporter
    environment:
      DATA_SOURCE_NAME: "postgresql://user:password@your_db_ip:5432/postgres?sslmode=disable"
    ports:
      - "9187:9187"

  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"

次に、データを取得するための最小限の設定を記述した prometheus.yml ファイルを作成します:

scrape_configs:
  - job_name: 'postgres'
    static_configs:
      - targets: ['postgres_exporter:9187']

docker-compose up -d コマンドを実行します。これで、exporterがメトリクスの収集を開始し、Prometheusに送信され、ポート3000のGrafanaで可視化する準備が整います。

動作の仕組み:postgres_exporterの役割

PostgreSQLは、デフォルトではPrometheusが要求する時系列(time-series)形式でデータを出力しません。そこで postgres_exporter が「通訳」の役割を果たします。データベースにアクセスし、SELECT * FROM pg_stat_activity などのSQLコマンドを実行して、その結果をコンピューターが理解できるメトリクスに変換します。

セキュリティのための専用ユーザー設定

本番環境の監視に postgres アカウント(スーパーユーザー)を絶対に使用しないでください。安全性を確保するために、権限を制限した専用ユーザーを作成すべきです:

-- 監視専用ユーザーの作成
CREATE USER monitoring WITH PASSWORD 'your_secure_password';
-- システム統計テーブルへのアクセス権限を付与
GRANT pg_monitor TO monitoring;

見逃せない4つの「ゴールデン」指標

何百ものグラフに圧倒されないでください。システムの健康状態を真に反映する重要な数値に集中しましょう:

  • Connections: 実際の接続数と max_connections を比較します。この数値が80%に達している場合、システムは危険水域にあります。
  • Transaction Throughput: Commit/Rollbackの比率を監視します。Rollbackが急増(例:5%以上)した場合、アプリケーションコードのロジックエラーやデータ競合が発生している可能性があります。
  • Buffer Cache Hit Ratio: RAMから読み取られたデータの割合です。この数値は95%以上を維持する必要があります。80%まで低下すると、ディスクI/Oが10倍に跳ね上がり、DBの速度が目に見えて低下します。
  • Database Size & Bloat: テーブルの肥大化を監視します。Autovacuumプロセスが効率的に動作していない場合、10GBのテーブルに最大4GBの「ゴミ」(デッドタプル)が含まれる可能性があります。

運用中、レポート作成のためにSQLデータを他の形式に素早く書き出す必要があることがよくあります。私はよく toolcraft.app の CSVからJSONへの変換ツール を利用しています。ブラウザ上で処理されるため、機密データが第三者のサーバーに漏れる心配がないのがメリットです。

アラートの設定:安眠を確保するために

ダッシュボードは、それを見ている時にしか役に立ちません。しかし、24時間365日画面に張り付いているわけにはいきません。アラート設定こそが、致命的な事態になる前に迅速な対応を可能にする「番人」となります。

アラートルールの設定例

アラートの閾値を定義するために alert_rules.yml ファイルを作成します:

groups:
- name: postgres_alerts
  rules:
  - alert: PostgresHighConnections
    expr: pg_stat_database_numbackends > (pg_settings_max_connections * 0.8)
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "{{ $labels.instance }} でDBのコネクションが不足しています"
      description: "接続数が5分間連続で制限の80%を超えました。"

  - alert: PostgresDown
    expr: pg_up == 0
    for: 1m
    labels:
      severity: fatal
    annotations:
      summary: "PostgreSQLがダウンしました!"
      description: "インスタンス {{ $labels.instance }} に接続できません。すぐに確認してください!"

SlackやTelegramと連携させれば、コネクションが増え始めた瞬間に通知を受け取ることができます。完全にハングアップしたDBを救出するよりも、この段階で「アイドル状態のコネクション(idle connections)」を整理する方がはるかに簡単です。

導入における実戦的なアドバイス

大規模システムのトラブルシューティングを何度も経験した結果、いくつかの重要な注意点をまとめました:

  1. コミュニティのダッシュボードを活用する: ダッシュボードをゼロから自作しないでください。Grafana Labsにアクセスし、ダッシュボードID 9628 をインポートしましょう。これはコミュニティで最も信頼され、標準化されているものです。
  2. データ取得の間隔 (Scraping Interval): 1秒間隔などの短すぎる設定は避けてください。メトリクスの取得は、その都度DBへのクエリ実行を伴うからです。15〜30秒の間隔が、精度とパフォーマンスの完璧なバランスです。
  3. ハードウェアも同時に監視する: DBの低速化は、ディスクI/Oのボトルネックが原因であることも多いです。node_exporter を追加でインストールし、サーバーのCPU、RAM、ディスク遅延(latency)も並行して監視しましょう。
  4. pg_stat_statements の併用: Prometheusは「DBが遅いこと」を教えてくれますが、pg_stat_statements は「どのSQLが犯人か」を正確に示してくれます。このエクステンションを有効にして、データを深掘りしましょう。

Share: