Heroku Postgresをアップグレードする

少し前の話になるのですが、HerokuのPostgresのアップグレードを行いました。 ほぼ公式ドキュメントのままなんですが、ご参考までに。

公式のドキュメント(英語)

devcenter.heroku.com

経緯

今回アップグレードに至った経緯としては、利用していたPostgresのバージョンがサポートされなくなる*1ため、でした。
(サポートが切れる前にきちんとメールで案内が来るのは親切でよいですね。)

もし、対応しなかった場合でもそのまま使えなくなることはなく、自動的にアップグレードされます。ですので、セキュリティ的なリスクはありません。

とはいえ、勝手にアップグレードされると何かがあったときの対応が大変だったり、何よりアップグレードの作業中はダウンタイムが少なからず発生するため、手動で行ったほうがよいです。

アップグレードの方法

以下、2つの方法があります。

  • フォロワーDBを作成してアップグレードする方法
  • コピーDBを新しく作成する方法

フォロワーDBを作成する方がダウンタイムも少なくて推奨されている方法のようですが、Hobby DevとHobby BasicのHobbyプランでは利用できません。 今回は、Hobbyより上のプランで利用していたため、フォロワーDBを作成する方法で行いました。

手順

  1. フォロワーDBの作成
  2. フォロワー作成後、メンテナンスモードへ
  3. フォロワーDBをアップグレードする
  4. promoteする
  5. メンテナンスモード終了

準備

作業は全てコマンドで行うため、Heroku CLIをインストールしておく必要があります。

1) フォロワーDBの作成

まず、フォロワーDBを作成します。
今のDBのフォロワーを作成するため、常に同期されるDBとなります。

$ heroku addons:create heroku-postgresql:premium-0 --follow DATABASE_URL --app your-app-name

対象のDBのプランが premium-0 だったので、同じ premium-0 で作成しています。
(どのプランでも問題ないが、データのサイズより小さいものは不可)

作成まで少し時間がかかります。以下のコマンドで状況が確認できます。

$ heroku addons:info postgresql-tetrahedral-12345

postgresql-tetrahedral-12345 はDB名)

作成されたフォロワーDBは現状のDBそのままなので、バージョンも古いものになります。

2) フォロワー作成後、メンテナンスモードへ

フォロワーDBが作成されたら、アップグレードを実施する前に対象のアプリをメンテナンスモードにします。
(要するにDBへの書き込みが行われないようになればよい。今回はHerokuのメンテナンスモード機能を利用)

$ heroku maintenance:on -a your-app-name

3) フォロワーDBをアップグレードする

作成したフォロワーDBを heroku pg:upgrade でアップグレードします。

$ heroku pg:upgrade HEROKU_POSTGRESQL_AQUA -a your-app-name
 ▸    WARNING: Destructive action
 ▸    postgresql-tetrahedral-12345 will be upgraded to a newer PostgreSQL version, stop following HEROKU_POSTGRESQL_COBALT, and become writable.
 ▸
 ▸    This cannot be undone.
 ▸    To proceed, type your-app-name or re-run this command with --confirm your-app-name

> your-app-name
Starting upgrade of postgresql-tetrahedral-12345... heroku pg:wait to track status

HEROKU_POSTGRESQL_AQUA などはDBにつけられた名前です。
(ここではHEROKU_POSTGRESQL_AQUA が新しく作成したDB、 HEROKU_POSTGRESQL_COBALT が旧DBになっています。)
破壊的な変更のためアプリ名の入力を求められるので入力します。

pg:wait コマンドを使って、アップグレードの監視を行うことができます。

$ heroku pg:wait -a your-app-name
Waiting for database postgresql-tetrahedral-12345... ⣻ upgrading

アップグレードが完了すると、完了表示に切り替わります。

4) Promoteする

アップグレードが無事完了したら、pg:promoteします。

HerokuではDBの接続情報は環境変数に格納されます。DBはメンテナンスされるたびに接続情報が更新されるため、必ずこの環境変数から接続情報を取得して利用する必要があります(環境変数は自動で更新されます)。
このデフォルトの環境変数名は、 DATABASE_URL となっているのですが、pg:promote コマンドでこの DATABASE_URL に設定するDBを指定することが出来ます。

今回、新しく作成したDBをアップグレードしたため、 DATABASE_URL へ設定するDBを新しく作成したDBに指定してやる必要があります。

$ heroku pg:promote HEROKU_POSTGRESQL_AQUA -a your-app-name

5) メンテナンスモード終了

これでアプリ側からは新しく作成されたDBを参照するようになりましたので、メンテナンスモードを終了してアプリを復帰させます。

$ heroku maintenance:off -a your-app-name

以上でアップグレード完了です。

ロールバック

もし、新しく作成したDBが壊れていたり何かしらのエラーが発生した場合には、旧DBがまだ残っているためそちらへ接続を切り替えてやることでロールバックしてやることが可能です。

$ heroku pg:promote HEROKU_POSTGRESQL_COBALT -a your-app-name

最後に

このようにアップグレードもコマンドラインでそれなりに気軽に行うことが可能です。
Herokuのアプリ自体もクローンすることが可能なので、テスト環境がないものだったりする場合も、一時的にテスト環境を新しく作成してやることもそれなりに簡単にできたりします。

頻繁にする作業ではないのですが、だからこそこのくらいの作業で行えるのはすごく良いと思います。
もしアップグレードする機会があれば参考までにどうぞ。

*1:バージョンが9.4.24のものがあり、バージョン9.4のサポート終了にともない、アップグレードする必要があったた