はじめに
以前の記事で AWS Copilot で Phoenix と Aurora Serverless を立ち上げる方法を紹介しました
この場合のデータベースのリストア手順がややこしかったので記事にまとめておきます
Amazon RDS におけるバックアップについて
RDS では自動バックアップと手動スナップショットを使用できます
いずれのバックアップも DB インスタンスのストレージボリュームのスナップショットになっていて、個別にデータを出し入れするわけではなく、全体を復旧する形になります
特に注意しなければならないのが、 バックアップからのリストアはクラスター、インスタンスの作り直しになる という点です
既存のデータベースに対してデータを入れ込むのではなく、 スナップショットから新しいクラスター、インスタンスを作成します
また、自動バックアップはクラスター、インスタンスが削除されると、一緒に削除されてしまいます
バックアップを残しておきたい場合、手動スナップショットを取るか、自動バックアップをコピーする必要があります
CloudFormation における RDS の変更について
もう一点注意しなければならないのが、 CloudFormation で管理している(AWS Copilot の場合もこれに当たります) RDS を変更したとき、項目によっては クラスターが更新されるのではなく、新しく作られることです
公式ドキュメントにも特に注意する事項として書かれています
We highly recommend that you take a snapshot of the database before updating the stack. If you don't, you lose the data when AWS CloudFormation replaces your DB cluster.
和訳
スタックを更新する前にデータベースのスナップショットを撮ることを強くお勧めします。そうしないと、AWS CloudFormationがDBクラスターを置き換える際にデータが失われます。
クラスターが作り直しになるのはドキュメント上で Update requires: Replacement
と書かれている以下の項目です
- AvailabilityZones
- DatabaseName
- DBClusterIdentifier
- DBSubnetGroupName
- DBSystemId
- EngineMode
- KmsKeyId
- PubliclyAccessible
- RestoreToTime
- RestoreType
- SnapshotIdentifier
- SourceDBClusterIdentifier
- SourceRegion
- StorageEncrypted
- UseLatestRestorableTime
例えば後から StorageEncrypted: true
に設定しようとすると、データベースが作り直されてデータは全て消えます
しかも前述の通り、自動バックアップはクラスターと道連れに消えてしまうため、バックアップも消えます
リソースの保護
うっかり消えてしまうことを防ぐため、対象となるクラスターに以下の指定を加えましょう
- DeletionPolicy: Retain
CloudFormation の stack を削除してもリソースは残るようになります - UpdateReplacePolicy: Retain
リソースの更新時に作り替えになったとしても、古い方のリソースが残るようになります
XXXDBCluster:
Metadata:
'aws:copilot:description': 'The XXX Aurora Serverless v2 database cluster'
Type: 'AWS::RDS::DBCluster'
+ DeletionPolicy: Retain
+ UpdateReplacePolicy: Retain
Properties:
...
XXXDBWriterInstance:
Metadata:
'aws:copilot:description': 'The XXX Aurora Serverless v2 writer instance'
Type: 'AWS::RDS::DBInstance'
+ DeletionPolicy: Retain
+ UpdateReplacePolicy: Retain
Properties:
...
ただし、リソースが消えなくなるため、不要になったら削除するのを忘れないようにする必要があります
CloudFormation からのリストア
クラスターのプロパティーとして SnapshotIdentifier
を指定します
...
XXXDBCluster:
Metadata:
'aws:copilot:description': 'The XXX Aurora Serverless v2 database cluster'
Type: 'AWS::RDS::DBCluster'
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
Engine: 'aurora-postgresql'
...
Port: 5432
+ SnapshotIdentifier: "<リストアしたいスナップショットのID>"
...
この状態で環境をデプロイすればリストアされます
copilot env deploy
UpdateReplacePolicy: Retain
を指定していない場合、この時点で古いクラスター(リストア前)が消え、アプリケーションでは DB 接続エラーが発生します
UpdateReplacePolicy: Retain
を指定している場合、古いクラスターは残っているため、アプリケーションは古いクラスターに接続したままになります
リストア先は新しいクラスターになるため、アプリケーションのコンテナ上にある接続情報(環境変数等)を更新する必要があります
コンテナ自体は何も変わっていないので --force
で強制更新します
copilot svc deploy --force
重要な注意点があります
一回 SnapshotIdentifier
を指定した場合、データベースの状態を保つには次回以降も同じスナップショットのIDを指定し続ける必要があります
リストア後に SnapshotIdentifier
を消して再度デプロイすると、データベースは空の状態で再び作成されてしまいます
データベースの変更・リストア手順
ここまでのことを踏まえて、 StorageEncrypted: true
への設定変更など、クラスターの作り替えが発生するような場合、以下の手順を実施することになります
システムメンテナンスをアナウンスする
データベースのスナップショット取得、リストアが必要なため、一時的にシステムの利用を停止します
UpdateReplacePolicy: Retain
の指定によってデータベースの切替自体は無停止で実行可能ですが、スナップショット取得後にユーザーが行った操作をリストアできないため、利用停止します
システムを利用停止状態にする
「工事中」的な表示にして利用できないようにします
手動スナップショットを取得する
AWS CLI の場合、以下のようにしてスナップショットを取得できます
aws rds create-db-cluster-snapshot \
--db-cluster-identifier $DB_CLUSTER_ID \
--db-cluster-snapshot-identifier $DB_CLUSTER_SNAPSHOT_ID
変更を CloudFormation に適用し、SnapshotIdentifierを指定する
適用したい内容と同時に SnapshotIdentifier によってスナップショットからのリストアを指定します
デプロイする
デプロイし、データベースの作り替え、接続情報の更新を実施します
copilot env deploy
copilot svc deploy --force
稼働確認
DB の設定、接続先、データの内容、システム動作を確認します
旧クラスターの削除
動作に問題ないことが確認できたら変更前のクラスターを削除します
まとめ
AWS Copilot は簡単にアプリケーションを管理・デプロイできますが、実際に中で動いている CloudFormation や RDS の仕様を理解していないと、うっかり重要なデータを消してしまう可能性があります
公式ドキュメントなどを読み込み、意図しない動作が発生しないようにしましょう