スナップショットから復元したAurora MySQLをCloudFormation管理下に加える&外す方法
こんにちは。システム開発部のsonohaです。ニフティ温泉のWEBサイトの開発全般を担当しています。
先日、AWSのAurora MySQLをスナップショットから復元する機会がありました。
スナップショットからDBを復元する方法、復元したDBを既存のCloudFormation管理に加える方法、元のDBを既存のCloudFormation管理から外す方法、それぞれについていくつか引っかかったポイントがあったため、この記事で手順と注意事項などをまとめていきます。
目次
モデルケース
次のようなケースを想定しています。
- RDS(DBCluster, DBInstance)をCloudFormationで管理している
- RDSのスナップショットを手動で復元し、CloudFormation管理外にDBが作成された
- 復元した新DBをCloudFormation管理に含め、元のDBをCloudFormation管理から外したい
これに対し、3つのステップに分けて手順・引っかかりポイント・対策を解説していきます。
- step1. スナップショットからDBを復元する
- step2. 復元したDBをCloudFormation管理下に含める
- step3. 元のDBをCloudFormation管理下から外す
step1. スナップショットからDBを復元する
手順
AWS公式ドキュメントに従うと、次のとおりです。
引用元:https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_RestoreFromSnapshot.html
- AWS Management Console にサインインし、Amazon RDS コンソール (https://console.aws.amazon.com/rds/) を開きます。
- ナビゲーションペインで、[Snapshots] を選択します。
- 復元の元にする DB スナップショットを選択します。
- [アクション] で、[スナップショットの復元] を選択します。
- [Restore snapshot] (スナップショットの復元) ページで、[DB instance identifier] (DB インスタンス識別子) に、復元された DB インスタンスの名前を入力します。
- 割り当てられたストレージサイズなど、その他の設定を指定します。各設定の詳細については、「DB インスタンスの設定」を参照してください。
- [DB インスタンスの復元] を選択します。
この手順を完了すると、1つのDBクラスターに1つのDBインスタンス(ライターインスタンス)が紐づいた状態になります。
このDBクラスターにリードレプリカを追加したい場合は、RDSコンソールで対象のDBクラスターに対し [リーダーの追加] を選択することでリーダーインスタンスを作成できます。
詳しくはAWS公式ドキュメントの「DBクラスターにAuroraレプリカを追加する」を参照ください。
引っかかりポイント
AWS Management Consoleから手動でスナップショットを復元する場合、デフォルトでは元のDBのパラメータグループ・オプショングループの設定は引き継がれません。
例えば、パラメータグループにはDBエンジンのタイムゾーンを指定する項目が含まれています。
元のDBではJSTを使用していたのに復元後にはUTCになってしまい、レコードのタイムスタンプが変わってしまった、といった事故が発生する可能性があります。
これについては、AWS公式ドキュメントの「パラメータグループに関する考慮事項」および「オプショングループに関する考慮事項」に記載がありますが、AWS Management Console上では見逃しやすい箇所に設定項目があるため、注意が必要です。
対策
対策は大きく2つあります。
①手動での復元時に、適切な設定を指定する
先に述べたAWS Management Consoleの「追加設定」の項目を忘れず確認し、元のDBで使用していたパラメータグループやその他の設定を指定することで、思わぬ事故を防げます。
②手動ではなく、CloudFormationからスナップショットを復元する。
CloudFormationテンプレートのAWS::RDS::DBClusterドキュメントを参照すると、CloudFormationからのスナップショット復元方法に関する注意書きがあります。
⚠️Important
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. To preserve your data, perform the following procedure:
引用元:https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rds-dbcluster.html
- Deactivate any applications that are using the DB cluster so that there’s no activity on the DB instance.
- Create a snapshot of the DB cluster. For more information, see Creating a DB Cluster Snapshot.
- If you want to restore your DB cluster using a DB cluster snapshot, modify the updated template with your DB cluster changes and add the
SnapshotIdentifier
property with the ID of the DB cluster snapshot that you want to use.
After you restore a DB cluster with aSnapshotIdentifier
property, you must specify the sameSnapshotIdentifier
property for any future updates to the DB cluster. When you specify this property for an update, the DB cluster is not restored from the DB cluster snapshot again, and the data in the database is not changed. However, if you don’t specify theSnapshotIdentifier
property, an empty DB cluster is created, and the original DB cluster is deleted. If you specify a property that is different from the previous snapshot restore property, a new DB cluster is restored from the specifiedSnapshotIdentifier
property, and the original DB cluster is deleted.- Update the stack.
この方法で復元を行うと、元のDBの設定をすべて引き継いで復元されるようです。
step2. 復元したDBをCloudFormation管理下に含める
手順
CloudFormationの「スタックへの既存リソースのインポート」の機能を用いて、復元したDBをCloudFormation管理下に含めます。
- CloudFormationテンプレートに次のような変更を加える。
DeletionPolicy: Retain
を指定したAWS::RDS::DBCluster
リソースを追記するDeletionPolicy: Retain
を指定したAWS::RDS::DBInstance
リソースを追記する- いずれのリソースも、スナップショット元のリソースの設定内容に揃える
- AWS Management Console上で該当のCloudFormationスタックを選択し、 [スタックアクション] から [スタックへのリソースのインポート] を選択する。
- 先のCloudFormationテンプレートをアップロードし、識別子を入力する。
- 変更セットがDBClusterとDBInstanceのImportのみであることを確認し、インポートを実行する。
この手順を完了すると、既存のCloudFormationスタック内に元のDBと復元したDBの両方が含まれている状態になります。
引っかかりポイント
インポートと同時にリソースの作成や変更はできない
スナップショットからDBを手動復元するとDB本体のリソースは作成されますが、関連する他のリソース(例えば、DBのメトリクス監視用のCloudWatch Alarmなど)は作成されません。
DBをCloudFormationスタックへインポートする際にCloudFormationテンプレートを変更するため、ついでに他の関連リソースの作成もそのテンプレート変更に加えたいと思ってしまいますが、インポートするリソース以外の変更が含まれていると変更セット作成時にエラーとなります。
ただし、リソースとは直接関係のないCloudFormationテンプレートのパラメータやメタデータは、インポート時にも追加や削除が可能です。
インポート後に元のリソースのDeletionPolicyを変更しようとするとエラーになる
The security token included in the request is invalid.
次のような順序でスタックを更新しようとしたところ、2のときに上記エラーが発生しました。
- 既存スタックに対して、復元したDBをインポート
- 既存スタックを更新し、元のDBに
DeletionPolicy: Retain
を指定 ←ここでエラー発生 - 既存スタックを更新し、元のDBをCloudFormationスタックから削除
このエラーは一般的には操作ユーザーの資格情報が不正な場合に発生するものですが、今回は資格情報に不備は無さそうだったため詳細な原因は不明です。
対策
前述の注意事項を踏まえ、リソースの追加・インポート・削除の手順を細かく分解し、実施順序を整理する必要があります。
参考までに、今回私が対応したリソースについては、次の順序で実施すると上手くいきました。
- 既存スタックを更新し、元のDBに
DeletionPolicy: Retain
を指定 - 既存スタックに対して、復元したDBをインポート
- 既存スタックを更新し、復元したDBに関連する追加のリソースを作成
- 既存スタックを更新し、元のDBとそれに関連するリソースをCloudFormationスタックから削除
step3. 元のDBをCloudFormation管理下から外す
手順
CloudFormationの「スタックテンプレートの変更」の手順に則り、スタックからDBと関連リソースを削除します。
(ただし、元のDBをCloudoFormation管理から外す際にリソース本体が削除されないようにするためには、前述のとおり、step2を実施する前に元のDBにDeletionPolicy: Retain
を指定しておく必要があります。)
- CloudFormationテンプレートに次のような変更を加える。
- 元の
AWS::RDS::DBCluster
リソースを削除する - 元の
AWS::RDS::DBInstance
リソースを削除する - 上記に紐づく関連リソースを削除する
- 元の
- AWS Management Console上で該当のCloudFormationスタックを選択し、 [更新] を選択する。
- 変更セットを確認し、更新を実行する。
この手順を完了すると、既存のCloudFormationスタック内には復元したDBだけが含まれている状態になります。
引っかかりポイント
元のDBをCloudFormationから削除するようなスタック更新をする場合、事前にドリフトが発生していると失敗することがあります。
ドリフトとは、CloudFormationで定義されているリソースの設定と、実在するリソースインスタンスの実際の設定との間に、何かしらの差分がある状態を指します。
ドリフトが発生していると、リソースをスタックから削除する処理中にDBのいずれかのプロパティのバリデーションに引っかかり、処理が途中で異常終了する場合があります。
私が遭遇したのは、AWS::RDS::DBInstance
のMonitoringInterval
プロパティがテンプレート上と実際の設定とでずれていたという事象で、これによりスタック更新中にエラーが発生しました。
また、DeletionPolicy: Retain
が指定されている関係で、スタック更新が失敗した際のロールバックも失敗することがあります。
対策
step3を開始する前に、事前に「CloudFormationスタック全体のドリフトを検出する」を参考にしてドリフトを検出しておくことをお勧めします。
ドリフトが発生していた場合には、先に解消しておきましょう。
スタック更新のロールバックに失敗した場合は、個々のケースによって対応が異なります。
手動で失敗の原因を取り除けるようであれば、「更新のロールバックを続ける」に従ってロールバックを正常終了させることも可能ですので、ご参考ください。
まとめ
以上をまとめると、DB復元からスタック管理下のリソース入れ替えまでの完全な流れは次のとおりです。
- スナップショットから、追加設定項目に注意しつつDBを復元
- 既存スタックに対して、ドリフトの検出を実行
- (ドリフトがあれば)既存スタックに紐づくリソースのドリフトを解消
- 既存スタックを更新し、元のDBに
DeletionPolicy: Retain
を指定 - 既存スタックに対して、復元したDBをインポート
- 既存スタックを更新し、復元したDBに関連する追加のリソースを作成
- 既存スタックを更新し、元のDBとそれに関連するリソースをCloudFormationスタックから削除
以上、ご参考になりましたら幸いです。
最後までお読みいただきありがとうございました!
掲載内容は、記事執筆時点の情報をもとにしています。