heroku-postgresqlのアップグレードをしてみました

はじめまして、昨年の12月からフレクトにお世話になっている、おっぴーです。 前職ではオンプレミスのサーバーでアプリケーションの運用をしていたので、フレクトにはいってから本格的にHerokuをさわりはじめました。 この情報見れないの!?等色々もどかしい思いをしつつ、その便利さに感動しています。

さて、今回はheroku-postgresqlのアップグレードについて書いてみたいと思います。

記事の要点を3行で。

  • heroku-postgresqlのUpgradeにはデータ移行が必要です
  • Upgradeの方法は3つあります
  • pg:copyを使った方法はdowntimeを伴います

Herokuへアプリケーションをデプロイするとheorku-postgresqlをHobby Devという無料のプランで自動追加してくれます。 このプランは無料で利用できるものの、レコード数による制限があるなど、開発環境といえども使い続けるのに不便を感じることがあります。 そんなときには、レコードの数の制限のない有償のバージョンにアップグレードをおこないたくなります。 が、その際は、Papertrailなどようにupgradeのコマンドを打つだけ!ではなく、少し手間のかかる作業、データ移行が必要になります。

下記に参考のURLをご紹介していますが、HerokuのDevCenterで紹介されているheroku-postgresqlのアップグレードの方法は全部で3つあります。 今回は、開発中には最も一般的な方法(と思われる方法)をご紹介します。

ちなみに今回、ご紹介する方法の他には、

  • followerとして新たにPostgresqlを追加してchangeoverする方法
  • pg:upgradeを利用する方法

の2つがありますが、これらの詳しい方法と使いみちなどについては、下記の参考URLでご確認ください。

pg:copyを用いたheroku-postgreqlのアップグレード方法

今回は、Hobby Devプランでつかっていたものを、レコード件数制限がないStandard-0プランにあげるという想定で流れをご紹介します。 下記では、記事を公開するために架空のアプリケーション名やWorker dyno名をコマンドで指定していますので、ご自身で試される際は適宜、ご自身の環境にあわせて実行してください。

アップグレードしたプランのheroku-postgreqlを追加する

まずはアップグレードしたプランを適用したheroku-postgresqlを追加します。 今回の場合は、hobbyプランをstandard-0プランにしたいので、standard-0プランを追加します。 なお、有償プランを利用する場合は、あらかじめ支払情報の登録が必要になります。

下記のコマンドにより、standard-0プランのheroku-postgresqlが追加されます。 なお、--version はheroku-postgresqlのversionを指定するときに利用します。現状で、指定をしなければ9.3のpostgreqlが追加されます。 また、--appは対象のアプリを指定するコマンドです。作業するherokuアカウントが複数のアプリケーションをHeroku上にデプロイしている場合は、アプリケーション名の指定を求められるのため今回もつけています。

 
heroku addons:add heroku-postgresql:standard-0 --version 9.3 --app geisya

新たにheroku-postgreqlを追加した場合、利用可能になるまで時間がかかります。 下記のようにpgのwaitコマンドを利用すると、プロビジョニングが完了すると通知してくれます。

 
heroku pg:wait --app geisya

Dynoを停止してメンテナンスモードにする

あたらしいDatabaseの準備完了したら、データ移行の準備を開始します。 まずは、データ移行中にDatabaseが更新されないようにします。

ひとまず現状のDynoの状態を確認します。 psコマンドを入力するとアプリの現状に合わせて、Dynoのプロセスが表示されます。 なお「※Prodfileの起動コマンドが表示されます※」という部分にはProcfileに定義されている起動コマンドが表示されます。

 
heroku ps --app geisya
=== geisya_worker (1X): `※Prodfileの起動コマンドが表示されます※`
gisya_worker.1: starting 2015/04/13 15:41:58 (~ 3s ago)
=== web (1X): `※Prodfileの起動コマンドが表示されます※`
web.1: up 2015/04/13 14:47:22 (~ 54m ago)
web.2: up 2015/04/13 14:47:19 (~ 54m ago)

上記を見ると、Worker Dynoが1つとWeb Dynoが2つ起動しています。 これからWorker Dynoを停止し、Web Dynoをメンテナンスモードにします。

 
heroku maintenance:on --app geisya

次に、Worker Dynoを停止しましょう。

 
heroku ps:scale gisya_worker=0 --app geisya

ちなみに、gisya_worker=0 のworker部分はProcfileで指定した名前を指定しましょう。 たとえば、hoge_workerとProcfile上で指定している場合は、上記のコマンドは、下記のように変更になります。

 
heroku ps:scale hoge_worker=0 --app geisya

もしも、Worker Dynoをご利用の場合、ご自身のProcfileの内容に従って、コマンドを変更してください。

追加したDatabaseに既存のデータをコピーする

メンテナンスモードになり、データ更新がされない状態になったら、コピー元のDatabaseのデータを新たに作成したDatabaseにコピーしましょう。 下記のコマンドは、DATABASE_URLで指定されている既存のDatabaseのデータを、新たに作成したHEROKU_POSTGRESQL_BLUEに移行すること意味します。

 
heroku pg:copy DATABASE_URL HEROKU_POSTGRESQL_BLUE --app geisya

上記のようにコマンドを打つと確認のため、対象のアプリケーションの名前を入力を求められます。 アプリケーションの名前(今回の場合はgeisya)を、入力するとデータの移行が始まります。

データのコピーには1Gごとに約3分程度かかります。今回のようにhobbyプランの場合、データの容量がそもそも大きくないためすぐに完了するはずです。 今回も10秒もかからずコピーは完了しました。 完了すると「Copy completed」と表示されます。

データがちゃんとコピーされているか、ざっと見たい方は、ここでheroku-posregsqlにつなげてデータの状況を見てもよいでしょう。

ちなみに、プロダクションの環境で大容量のデータをコピーする場合は、事前にどれだかかるかテストすることをHerokuのDevCenterの記事では推奨しています。 テストの方法は、単純です。 これからご紹介する手順をDatabaseの昇格なしで実行し、処理時間を計測する、というものです。 なお、昇格についてはのちほど、ご説明します。

なお、pg:copyはpgbackupsが削除されたことに伴い、pgbackups:transferの代わりとしてheroku-postgresqlに加えられた機能です。

コピーが完了したらDatabaseを昇格させ、メンテナンスモードを解除する

すべてのデータが新しいDatabaseにコピーされたら、新しいDatabaseを昇格させましょう。 昇格とは、新しく加えたDatabaseをアプリケーションから使うように設定を切り替える行為を指します。 具体的には、Heroku上でDatabaseのURLを指定する環境変数であるDATABASE_URLの値が書き換えられます。

下記のコマンドで、新しいDatabaseが昇格し、これ以降アプリケーションからは新しいDatabaseが使われるようになります。

 
heroku pg:promote HEROKU_POSTGRESQL_BLUE --app geisya
Promoting HEROKU_POSTGRESQL_BLUE_URL to DATABASE_URL... done

ちなみに、ちゃんと昇格されているか、に関しては下記のコマンドで確認できます。

 
heroku pg:info --app geisya
=== HEROKU_POSTGRESQL_BLUE_URL (DATABASE_URL)
Plan:               Standard 0
Status:             Available
Data Size:          9.0 MB
Tables:             10
PG Version:         9.3.6
Connections:        3/120
Fork/Follow:        Available
Rollback:           earliest from 2015-04-13 05:54 UTC
Created:            2015-04-13 05:47 UTC
Maintenance:        not required
Maintenance window: Tuesdays 21:00 to Wednesdays 01:00 UTC

新しく追加した、HEROKU_POSTGRESQL_BLUE_URLの横に (DATABASE_URL)が表記されており、昇格したことが確認できます。

その後、メンテナンスモードを解除します。 まずは、Worker Dynoを元に戻します。

 
heroku ps:scale geisya_worker=1 --app geisya
Scaling dynos... done, now running geisya_worker at 1:1X.

worker=1の1の部分は、追加するDyno数です。今回は1つで動かしていたので、1を指定して元に戻しました。 ご自身の環境では、運用状況に従って、Dyno数を指定してください。

Worker Dynoのあとは、Web Dynoのメンテナンスモードを解除します。

 
heroku maintenance:off --app geisya
Disabling maintenance mode for geisya... done

上記のコマンドを実施することで、新しいDatabaseを利用した状態でアプリケーションがデプロイされた状態になります。

念のため、アプリケーションのDyno状況を見てみましょう。 ここでもpsコマンドを利用します。

 
heroku ps --app geisya
=== geisya_worker (1X): `※Prodfileの起動コマンドが表示されます※`
geisya_worker.1: up 2015/04/13 15:49:26 (~ 14s ago)
=== web (1X): `※Prodfileの起動コマンドが表示されます※`
web.1: up 2015/04/13 15:48:28 (~ 1m ago)
web.2: up 2015/04/13 15:48:27 (~ 1m ago)

Worker Dynoが1つ、Web Dynoが2つ動いていることが確認できます。 この状態ですと、Web Dynoが問題なく動いているか、という点は確認できていません。 ですので、アプリケーションのログなどをみて、動作に問題がないことを確認したら、古いheroku-postgresqlの方は削除してください。

既存Databaseの削除は、Addonから該当のheroku-postgresqlを削除することになります。 下記のように、addonsのremoveコマンドはで削除対象のheroku-postgresqlの環境変数(今回の場合は、HEROKU_POSTGRESQL_CYAN_URL)を指定します。

 
heroku addons:remove HEROKU_POSTGRESQL_CYAN_URL --app geisya

removeコマンドを入力すると、削除の実行を確認するためアプリケーション名(geisya)の入力を求められるので、入力します。 以上で、heroku-postgresqlのプランのアップグレードは完了です。

いかがでしたでしょうか。 新しいDatabaseの追加→データのコピー→Databaseの昇格という一連の流れをご理解いただけたでしょうか。 実際の本番運用では、前もってサイジングを行うはずですので、なかなかheroku-postgresqlのプランをアップグレードをすることはないかもしれませんが、開発環境では利用されることもあると思うので、ご参考になれば幸いです。

記事を読んで、ご質問やご指摘がございましたら、ぜひコメントもしくはメールでお知らせください。 これからも自分とみなさまにとって役に立ちそうな記事を作成してゆきますので、コメントをいただけますと幸いです。

参考情報


コメント(1)