AWS RDSをオンプレのPostgreSQLデータベースのバックアップで使用する

# 背景
通常は初めからクラウド上に全て構築すると思いますが、オンプレミスのベアメタルサーバーで構築したデータベースのバックアップ先として、クラウドサービスのAWS RDSを利用すると言う話です。
以下のような利点に合致する場合を想定しています。

- 組織の施設内にオンプレミスのベアメタルサーバーを主として利用している。
- ベアメタルサーバーが物理故障した場合、新たに調達する為には予算や時間が必要。
- バックアップ用に別のベアメタルサーバーを用意するコストを抑えたい。
- 自然災害や、火災、事故などを想定して、施設外にバックアップを用意したい。
- オンプレミス側が停止した場合、一時的にクラウド側も利用可能

# 動作環境

## オンプレミス側(メイン)
- OS:CentOS7
- データベース：PostgreSQL

## クラウド側(バックアップ)
- AWS RDS
- データベース：PostgreSQL

# AWS RDSの設定

データベースサービスに特化したコンソールが無いEC2という感じですので、基本的にはEC2に準拠した設定になります。

## AWS RDSの料金

- [Amazon RDS for PostgreSQL の料金](https://aws.amazon.com/jp/rds/postgresql/pricing/)

詳細は公式サイトを参照して下さい。
今回のバックアップに利用する場合、データ転送はデータ転送受信（イン）は無料なので、基本サービスの利用時間、ストレージ使用量が主な課金内容になると思います。

## データベースの作成

AWSのダッシュボードからRDSを選択して、データベースを作成します。
作成時の「接続」オプションで「パブリックアクセス可能」を「あり」に選択変更しておきます。
<img width="797" alt="aws-rds-4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35898/146f722e-5875-43a1-faa9-4d61a0433b3d.png">


作成した後からでも変更は可能です。
<img width="617" alt="aws-rds-2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35898/24854d08-50f1-8b9c-b619-9bcc1c98529a.png">

データベース作成後のステータスに、エンドポイントとポート番号が表示されます。
これが外部からAWS RDSに接続する値になります。

![aws-rds-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35898/0d46d2fa-3822-c634-531c-45d77a4a30be.png)

## セキュリティグループの設定

EC2と同じ様に外部から接続出来るように設定します。
特定のIPアドレス番号だけ許可するように制限しましょう。
<img width="838" alt="aws-rds-3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35898/abb888b9-c3a8-98a0-cbf4-a13cd993f1a7.png">


## データベース接続確認

「pgAdmin」などのソフトでもAWS RDSデータベースに接続が可能ですので、事前確認してみましょう。


# オンプレミス側PostgreSQLの設定

既存のPostgreSQLが稼働している事が前提です。
バックアップファイルを作成して、作成したバックアップファイルからAWS RDS側へリストアする事でバックアップします。
バックアップファイルが正しく復元リストアされる事の検証にもなって一石二鳥だったりします。

## ローカルバックアップ

PostgreSQLのデータをローカルにバックアップする為に、「pg_dump」コマンドを使用します。
バックアップ形式には２種類があります。

- スクリプト形式：SQLのプレーンテキスト。直接編集可能で他への移行がし易い。
- アーカイブ形式：バイナリで編集不可だが個別の復元が可能。またアーカイブ方法として「tar形式」とデフォルトで圧縮される「custom形式」がある。

それぞれにメリット・デメリットがありますが、ファイルサイズが小さく内容が見えない点がクラウド側へデータ転送するメリットなので、今回はアーカイブ(custom)形式を使用します。
また定期的にバックアップを実行する様にシェルスクリプトにしてcronで定期実行させます。

形式

```
$ pg_dump -Fc -w --host=127.0.0.1 --dbname=[データベース名] --dbusername=[ユーザー名] > [出力ファイル名とPATH]
```

例

```:backup.sh
#/bin/bash
pg_dump -Fc -w --host=127.0.0.1 --dbname=db1 --dbusername=postgres > ~/db1-backup.custom
```

適当にcronの定期実行を設定

```:
$ crontab -l
00 0 * * * /home/pg-user/backup.sh 2>&1
```

## AWS RDSへのリストアバックアップ

先に設定したAWS RDSのPostgreSQLデータベースに、ローカルバックアップしたファイルからリストアを実行します。
それに先立って、AWS RDS側への接続認証に関する設定ファイルを作成します。
シェルスクリプトで実行する際にパスワード入力待ちで停止してしまう事をこれで回避します。

形式

```:~/.pgpass
[AWS RDSのエンドポイント] : [ポート番号] : [データベース名] : [ユーザー名] : [パスワード]
```

例

```:~/.pgpass
xxx.yyy.ap-northeast-1.rds.amazonaws.com:5432:db1:postgres:password
```

ファイル属性をオーナー読み取りに制限しておきます。

```
$ chmod 600 ~/.pgpass
```

復元するリストアのコマンド「gr_restore」を使用します。
また定期的にバックアップを実行する様にシェルスクリプトにしてcronで定期実行させます。

形式

```
$ pg_restore --host=[AWS RDSのエンドポイント] --username=[ユーザー名] -c -Fc --dbname=[データベース名] [バックファイル名PATH]
```

例

```:restore.sh
#/bin/bash
pg_restore --host=xxx.yyy.ap-northeast-1.rds.amazonaws.com --username=postgres -c -Fc --dbname=db1 ~/db1-backup.custom
```

適当にcronの定期実行を設定

```:
$ crontab -l
00 1 * * * /home/pg-user/restore.sh 2>&1
```