Amazon S3に保存されているDBバックアップを練習のためHerokuのステージング環境にリストアする手順


## 目的
万一本番環境でDBのリストアが必要になった場合、素早く、そして間違いなくリストアするため、ステージング環境を使ってAmazon S3からのリストアが問題なく実施できることを定期的に確認する。(リストアテスト)

## 前提条件
- Herokuのステージング環境にアクセスできる権限があること
- 保存先のAmazon S3にアクセスできる権限とツールがあること
 - ここではツールとして[S3Fox Organizer](http://www.s3fox.net/)の利用を前提とする
 - S3へは"pgbackups"と"heroku_backup_task"でdumpファイルが転送されていることを前提とする ([参考](http://psandvs.com/posts/7))
- 間違って本番環境を壊したりしてしまわないよう、他のメンバーと一緒に作業すること (ペアオペ)
- `--remote staging`のようなオプションでHerokuのステージング環境を指定できること
 - これは推奨条件なので、`--app awesome-app-staging`のような指定方法でも可
 - [参考: herokuでStagingとProductionの２つを同じレポジトリで管理しているときに便利にherokuコマンドを打つ方法](http://blog.mat-aki.net/heroku-staging-production-command-remote)

## 本番環境で実施する際の注意点
この手順はステージング環境でリストアをするための手順だが、本番環境でもほぼ同じような手順になる。
本番環境で実施する場合は以下の点に注意すること。

- 以下の手順にある`--remote staging`を`--remote production`に変更する。
- 実施前にロストするデータの範囲(時間帯)を確認する
 - ただし、S3ではアップロード日時しか確認できないため、正確な範囲は特定が難しい。
- 外部に顧客がいる場合は、作業実施前の通知と確認、実施後の通知を行う。
 - 実施前の通知内容: 障害の原因、停止時間、ロストするデータの範囲
- Herokuのpgbackups内に有効なバックアップデータが残っている場合は、それを利用する。

## 手順
### 1. ステージング環境のバックアップ
ステージング環境を最後に元の状態に戻すため、ステージング環境のDBをバックアップする。

````
$ heroku pgbackups:capture --expire --remote staging

HEROKU_POSTGRESQL_WHITE_URL (DATABASE_URL)  ----backup--->  b154

Capturing... done
Storing... done
````

上の出力結果から、バックアップデータのIDは`b154`、DBの名前(色)は`WHITE`だとわかる。

#### 備考
aで始まるデータは自動バックアップ、bで始まるデータは手動バックアップによって作成されたデータを表している。

### 2. S3に保存されているdumpファイルのURLを取得する
Amazon S3にアクセスし、復元用のdumpファイルのURLを取得する。
このとき、S3Fox Organizerで対象データを右クリックし、"Get Pre-signed Urls"を選択して、dumpファイルのURLを取得する。

ここでは以下のようなURLを取得できたと仮定する。

````
http://awesome-app-backup.s3.amazonaws.com/b322.dump?AWSAccessKeyId=XXXX&Expires=1362516166&Signature=XXXX
````

### 3. データをリストアする
S3のdumpファイルからステージング環境のDBへデータをリストアする。
破壊的な操作になるので、間違いが無いように十分注意すること。

````
## メンテナンスモードON
$ heroku maintenance:on --remote staging
Enabling maintenance mode for awesome-app-staging... done

## リストア実行
$ heroku pgbackups:restore HEROKU_POSTGRESQL_WHITE 'http://awesome-app-backup.s3.amazonaws.com/b322.dump?AWSAccessKeyId=XXXX&Expires=1362516166&Signature=XXXX' --remote staging

HEROKU_POSTGRESQL_WHITE_URL (DATABASE_URL)  <---restore---  b322.dump

 !    WARNING: Destructive Action
 !    This command will affect the app: awesome-app-staging
 !    To proceed, type "awesome-app-staging" or re-run this command with --confirm awesome-app-staging

> awesome-app-staging

Retrieving... done
Restoring... done

## 復元されたデータの確認(確認内容は任意)
$ heroku run console --remote staging
Running `console` attached to terminal... up, run.4513
irb(main):001:0* User.count
   (1.5ms)  SELECT COUNT(*) FROM "users" 
=> 1834
irb(main):002:0> exit

## メンテナンスモードOFF
$ heroku maintenance:off --remote staging
Disabling maintenance mode for awesome-app-staging... done
````

### 4. アプリケーションの確認
ステージング環境のアプリケーションにアクセスし、dumpファイルのデータがステージング環境に反映されていることを確認する。

#### 備考
- carrierwaveで保存された画像データ等はステージング環境のままなので、データの整合性が崩れてシステムエラーや表示崩れなどの原因になる可能性がある。

### 5. ステージング環境を元の状態に戻す
ステージング環境のバックアップデータをステージング環境のDBにリストアする。

````
## メンテナンスモードON
$ heroku maintenance:on --remote staging
Enabling maintenance mode for awesome-app-staging... done

## リストア実行
$ heroku pgbackups:restore HEROKU_POSTGRESQL_WHITE b154 --remote staging


HEROKU_POSTGRESQL_WHITE_URL (DATABASE_URL)  <---restore---  b154
                                                            HEROKU_POSTGRESQL_WHITE_URL (DATABASE_URL)
                                                            2013/03/05 10:05.01
                                                            217.5KB

 !    WARNING: Destructive Action
 !    This command will affect the app: awesome-app-staging
 !    To proceed, type "awesome-app-staging" or re-run this command with --confirm awesome-app-staging

> awesome-app-staging

Retrieving... done
Restoring... done

## 復元されたデータの確認(確認内容は任意)
$ heroku run console --remote staging
Running `console` attached to terminal... up, run.4513
irb(main):001:0* User.count
   (1.5ms)  SELECT COUNT(*) FROM "users" 
=> 16
irb(main):002:0> exit

## メンテナンスモードOFF
$ heroku maintenance:off --remote staging
Disabling maintenance mode for awesome-app-staging... done
````

ステージング環境のアプリケーションにアクセスし、リストアテスト前の状態になっていればOK。

お疲れ様でした！！

## 参考資料
- [PG Backups](https://devcenter.heroku.com/articles/pgbackups)
- [Heroku SchedulerでAmazon S3に定期的にDBバックアップ](http://psandvs.com/posts/7)