0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Heroku PostgresのバックアップをHeroku PGBackupsから自前実装による論理バックアップに切り替えてHeroku Schedulerで定期実行する方法

Posted at

Heroku Postgresのバックアップ手法

Heroku Postgresのバックアップを行うには以下の方法があります。


物理バックアップの制限

「物理バックアップ」の機能は「Standard」以上のプランの場合のみ利用可能なようなので、今回は「論理バックアップ」にフォーカスして説明していきます。

スクリーンショット 2025-03-02 8.43.41.png
「Heroku Postgres」の「Durability」の画面にて
スクリーンショット 2025-03-02 8.48.23.png
「Heroku Postgres のデータの安全性と継続的保護」より抜粋

論理バックアップの制限

Heroku Postgres には 「Heroku PGBackups」というバックアップ機能が提供されており、バックアップを定期実行する場合も簡単に設定可能です。

ただし、「Heroku PGBackups」には「データベースのサイズが20GBまで」という制限があるようです。
今回、「Heroku PGBackups」の利用をやめて自前実装に切り替える理由はこれです。
「Heroku PGBackups」の機能を利用して定期バックアップを行っていたつもりが、実はバックアップに失敗していましたといったことがないように注意しましょう。

スクリーンショット 2025-03-02 9.11.43.png
「Heroku Postgres の論理バックアップ」より抜粋
スクリーンショット 2025-03-02 9.12.05.png
「Heroku PGBackups」より抜粋

Heroku PGBackupsの仕組み

自前実装を始める前に、Heroku PGBackupsの仕組みについて理解していきます。

Heroku PGBackups を使用した小さなデータベースでの論理バックアップの取得」で説明されているとおり、 heroku pg:backups の実体は pg_dumppg_restore です。

heroku pg:backups でバックアップのIDを取得し、どこに保存されているかを確認すると、Amazon S3に保存されていることがわかります。

$ heroku pg:backups --app アプリケーション名
=== Backups

 Id   Created at                Status                              Size   Database 
 ──── ───────────────────────── ─────────────────────────────────── ────── ──────── 
 b001 2025-03-01 23:22:23 +0000 Completed 2025-03-01 23:22:25 +0000 1.93KB DATABASE 

=== Restores

No restores found. Use heroku pg:backups:restore to restore a backup

=== Copies

No copies found. Use heroku pg:copy to copy a database to another
$ heroku pg:backups:url b001 --app アプリケーション名
https://xxxxx.s3.amazonaws.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/2025-03-01T23%3A22%3A23Z/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=xxxxxxxxxxxxxxxxxxxx%2F20250302%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250302T001750Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Heroku Postgresの定期バックアップを自前実装するための仕様

Heroku PGBackupsの仕組みを踏まえて、以下のような仕様で実装を行っていきます。

  • バックアップ処理はシェルスクリプト(bash)で実装する。
  • PostgreSQLのバックアップコマンドである pg_dump を利用する。
  • pg_dump で出力されたダンプファイルを gzip コマンドで圧縮する。
  • gzip圧縮したファイルファイルをAmazon S3にアップロードする。
  • Heroku Schedulerを利用してバックアップ処理を定期実行する。

事前準備

  • Amazon S3の操作が可能なIAMアカウントを準備します。
  • Heroku buildpack for the AWS CLI」の手順に従って、ビルドパックを追加します。
    • この手順内でHerokuのConfig VarsにS3を操作可能なIAMアカウントの「 AWS_ACCESS_KEY_ID 」、「 AWS_SECRET_ACCESS_KEY 」、「 AWS_DEFAULT_REGION 」を追加します。
  • HerokuのConfig VarsにS3のバケット名を「 AWS_S3_BUCKET 」として追加します。
  • HerokuのConfig Varsの登録状況を確認します。
    • スクリーンショット_2025-03-02_9_57_14.png
    • DATABASE_URL 」については、Heroku Postgresを利用している場合は自動的に追加されています。
  • Heroku SchedulerをAdd-onsとして追加します。

バックアップスクリプトを実装

  • 処理の流れ
    • Config Varsで登録済みの各環境変数の必須入力チェックを行う。
    • pg_dump コマンドでダンプファイルを出力する。
      • より大規模なデータベースでの論理バックアップの取得」では、オプションに「 -F c 」が指定されていますが、圧縮については gzip コマンドを利用するので、プレーンテキストとするために「 -F p 」を指定しました。
      • -F c 」を利用すると、ダンプファイルの中身をテキストエディタで開いて確認するといったことができなくなるため、今回は「 -F p 」を採用しました。
    • 出力されたダンプファイルを gzip コマンドで圧縮する。
    • gzip圧縮されたファイルをAWS CLI( aws s3 cp )でAmazon S3にアップロードする。
    • 本番環境の場合であれば、成功・失敗時のSlackなどへの通知処理については実装しておいた方がよいですが、今回は処理を簡素化するために実装内容から割愛しています。
$ cat pgbackup.sh 
#!/bin/bash

set -eu
set -o pipefail

# 環境変数の必須入力チェック
if [ -z "${DATABASE_URL:-}" ]; then
    exit 1
fi
if [ -z "${AWS_S3_BUCKET:-}" ]; then
    exit 1
fi
if [ -z "${AWS_ACCESS_KEY_ID:-}" ]; then
    exit 1
fi
if [ -z "${AWS_SECRET_ACCESS_KEY:-}" ]; then
    exit 1
fi
if [ -z "${AWS_DEFAULT_REGION:-}" ]; then
    exit 1
fi

BACKUP_FILE_NAME="dump_$(TZ=Asia/Tokyo date +%Y%m%d_%H%M%S).sql.gz"
BACKUP_FILE_PATH="/tmp/${BACKUP_FILE_NAME}"

# データベースのダンプ処理
if ! pg_dump -F p --no-acl --no-owner --quote-all-identifiers "${DATABASE_URL}" | gzip > "${BACKUP_FILE_PATH}"; then
    exit 1
fi

# AWS_S3_BUCKETの末尾に「/」が含まれる場合は「%/」により削除する
S3_BUCKET_PATH="${AWS_S3_BUCKET%/}/${BACKUP_FILE_NAME}"

# S3へのアップロード処理
if ! aws s3 cp "${BACKUP_FILE_PATH}" "${S3_BUCKET_PATH}"; then
    exit 1
fi

exit 0

バックアップスクリプトを反映

$ git add pgbackup.sh 
$ git commit -m "add pgbackup script"
$ git push heroku main

バックアップスクリプトを手動実行して動作確認

利用している「Heroku-24 Stack」は「Ubuntu 24.04」をベースにしているため、「 sh pgbackup.sh 」と実行するとdashが実行されるはずなので、明示的に「 bash pgbackup.sh 」として実行しています。

$ heroku run bash pgbackup.sh 
Running bash pgbackup.sh on ⬢ アプリケーション名... up, run.9667
upload: ../tmp/dump_20250302_104213.sql.gz to s3://バケット名/dump_20250302_104213.sql.gz

shebangに #!/bin/bash と記述しているので、「 sh pgbackup.sh 」と実行しても実際には問題ないかもしれませんが、実行権限を付与して以下のように実行することも可能です。

$ chmod +x pgbackup.sh
$ heroku run ./pgbackup.sh 
Running ./pgbackup.sh on ⬢ アプリケーション名... up, run.7937
upload: ../tmp/dump_20250302_105126.sql.gz to s3://バケット名/dump_20250302_105126.sql.gz

Amazon S3にアップロードされていることを確認

上記の手動実行により、2つのファイルがアップロードされています。

スクリーンショット_2025-03-02_10_54_22.png


Heroku Schedulerによる定期実行の設定

Heroku Schedulerの画面で「Create Job」をクリックします。

スクリーンショット 2025-03-02 10.59.41.png

Job Editorの画面で以下のように昼の12時(JST)に実行されるように設定します。

スクリーンショット 2025-03-02 11.02.44.png

Jobの登録に成功すると以下のように一覧画面に表示されます。

スクリーンショット 2025-03-02 11.04.24.png


Heroku Schedulerにより定期実行されていることを確認

指定していた「昼の12時(JST)」になると定期処理が実行され、S3にファイルがアップロードされています。

スクリーンショット_2025-03-02_12_01_30.png

Heroku SchedulerのJob一覧画面には次回の実行タイミングが更新され「翌日の昼の12時(JST)」が表示されています。

スクリーンショット 2025-03-02 12.05.31.png


以上がHeroku PGBackupsから自前実装による論理バックアップへの切り替え作業になります。
バックアップ実行時の通知処理の実装やS3のライフサイクル設定などについては割愛しましたが、ひとまずこれで定期バックアップ自体は実現可能かと思いますので、Heroku Postgresのサイズが20GB以上になりそうな場合は参考にしてみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?