PostgreSQL PITR復旧訓練ガイド: バックアップがあるのに戻せないを防ぐ実践手順
PostgreSQL運用で最も危険なのは「バックアップがある」という安心感です。実際の障害では、バックアップ自体より 復旧手順の不整合 で時間を失います。たとえば、WAL保管期間が足りず目標時刻に戻せない、暗号鍵が見つからず復号できない、復旧後の整合性確認が曖昧で再開判断ができない、といった問題です。
本記事では、PostgreSQLの Point-in-Time Recovery(PITR)を、机上ではなく本番レベルで回すための実装手順を解説します。pgBackRest を例にしていますが、考え方は他ツールでも共通です。
1. PITRの前提: 3つ揃わないと復旧できない
PITRは次の3要素で成立します。
- ベースバックアップ(フルまたは差分)
- WALアーカイブ(継続的)
- 目標時刻情報(いつまで戻すか)
どれか1つでも欠けると成立しません。特に本番で多いのは「WALが途中で消えていた」ケースです。S3保存していても、ライフサイクル設定や権限変更で欠落することがあります。
2. まず決めるべきRTO/RPO
技術論の前に、業務要件を決めます。
- RTO(復旧に許容される時間): 例 60分
- RPO(失ってよいデータ時間): 例 5分
この2つで設計が変わります。
- RPO 5分以内ならWALアーカイブ遅延監視が必須
- RTO 60分以内なら復旧訓練を定期実施し、手順を自動化する必要あり
要件不明のまま「毎日バックアップ」だけ実施しても、障害時に役立たないことが多いです。
3. 推奨アーキテクチャ(単一リージョンの最小構成)
- DBサーバ: PostgreSQL 15/16
- バックアップツール: pgBackRest
- 保存先: S3互換ストレージ(バージョニングON)
- 監視: Prometheus + Alertmanager
- 復旧先: 別ホスト(本番と同一ネットワーク)
重要なのは、本番DBと別ホストで実際に復旧できること を定期検証する点です。
4. 実装手順(pgBackRest)
4.1 PostgreSQL設定
postgresql.conf 例:
wal_level = replica
archive_mode = on
archive_command = 'pgbackrest --stanza=main archive-push %p'
max_wal_senders = 10
wal_compression = on
archive_command は失敗時に非0を返す必要があります。ここが曖昧だとWAL欠落に気づけません。
4.2 pgBackRest設定
/etc/pgbackrest/pgbackrest.conf 例:
[global]
repo1-type=s3
repo1-path=/pgbackrest
repo1-s3-bucket=prod-db-backup
repo1-s3-endpoint=s3.ap-northeast-1.amazonaws.com
repo1-s3-region=ap-northeast-1
repo1-retention-full=14
start-fast=y
process-max=4
compress-type=zst
[main]
pg1-path=/var/lib/postgresql/16/main
初期化:
|
|
4.3 WAL到達の監視
pg_stat_archiverのfailed_count- 最終成功時刻と現在時刻の差分
- repoの最新WALタイムスタンプ
例: 10分以上WALが更新されない場合にCriticalアラート。
5. 復旧訓練(Drill)を標準化する
運用で差が出るのはここです。訓練の目的は「復旧できること」ではなく、予測可能な時間で安全に復旧できること です。
5.1 月次ドリル手順(テンプレート)
- 目標時刻を決める(例: 当日 08:35:00 JST)
- 復旧専用ホストを初期化
- バックアップ + WALからリストア
- DB起動後、整合性チェックを実行
- アプリのスモークテストを実行
- RTO実測値と課題を記録
5.2 実コマンド例
|
|
PostgreSQL 12+では recovery.conf ではなく postgresql.auto.conf + standby.signal 形式に変わっている点に注意してください。
6. 復旧後の整合性チェック項目
「起動したからOK」は危険です。最低限、次を確認します。
- 主要テーブル件数(基準値との差分)
- 直近トランザクション時刻
- 重要集計値(売上、注文、在庫など)
- アプリの read/write スモークテスト
- レプリカ再構築可否
SQL例:
|
|
件数だけでなく「業務上重要な指標」を入れるのが実務的です。
7. 失敗しがちなポイントと対策
7.1 WAL保持期間が短すぎる
- 対策: RPO/RTOに基づき、最低でも7〜14日保持
- 削除はバックアップ整合性確認後に実行
7.2 暗号鍵・認証情報の保管ミス
- 対策: KMS/Secret Managerに分離保管
- 緊急時アクセス手順をRunbook化
7.3 手順が個人依存
- 対策: RunbookをGit管理
- ドリル時に“当番以外”が実行して再現性を検証
7.4 復旧はできるが遅すぎる
- 対策: 差分バックアップ頻度見直し
- 復旧先マシンスペックの最低保証
- リストア並列度(
process-max)調整
8. 自動化の実装例(CIでドリルを回す)
本番同等データを使えない場合は、匿名化済みスナップショットで定期検証します。
- 毎週日曜 03:00 に復旧ジョブ起動
- 復旧後にSQLチェック + APIスモーク
- 結果をSlack/Discordへ通知
- 失敗時は翌営業日のSRE定例でレビュー
この「半自動ドリル」を導入すると、障害時の初動が劇的に安定します。
9. 監査対応のための証跡
監査や顧客説明で必要になるのは、次の証跡です。
- バックアップ成功ログ(日次)
- WAL連続性の証跡
- 復旧ドリルの実行記録(日時、担当、RTO実測)
- 改善アクション履歴
「やっています」ではなく「この月にこの結果でした」と示せる状態を作っておきましょう。
10. 現場向けチェックリスト
- フルバックアップ成功率 99%以上
- WAL遅延アラートが有効
- 目標時刻指定の復旧手順がRunbook化
- 月次ドリル実施済み
- 復旧後整合性チェックSQLが整備済み
- KMS/鍵管理手順が文書化済み
このチェックリストを満たして初めて「PITR対応」と言えます。
まとめ
PITRは設定項目の話ではなく、復旧可能性を継続的に検証する運用 です。
- RTO/RPOを先に決める
- バックアップ + WAL + 監視をセットで設計する
- 月次ドリルで実測し、Runbookを改善する
- 復旧後整合性チェックまで標準化する
バックアップがあることはゴールではありません。障害時に「何分で、どこまで戻せるか」を言える状態こそが、プロダクション品質です。
付録: 実運用で使えるPITRドリル手順(90分版)
以下は、現場でそのまま回せる最小ドリル手順です。月次で固定化すると、障害対応の心理的負荷を下げられます。
- 開始宣言(5分)
- 担当者、開始時刻、目標RTO/RPOをチケットに記録
- 復旧環境準備(15分)
- 復旧先PostgreSQLを起動
- バックアップ世代と目標復旧時刻(例: 10:32:00 JST)を確定
- リストア実行(25分)
pg_restoreもしくはベースバックアップ展開- WAL適用完了ログを保存
- 整合性検証(20分)
- 件数チェックSQL、外部キー整合性、直近注文IDの連続性を確認
- APIスモーク(ログイン/一覧/作成)を実施
- 振り返り(25分)
- 実測RTO/RPOを記録
- 失敗ポイントをRunbookに即反映
重要なのは「成功したか」だけではなく、どこで何分消費したかを毎回残すことです。これを3回続けるだけで、復旧手順のボトルネックがかなり明確になります。