DMSを使って非暗号化RDS MySQLから暗号化Auroraに無停止で移行する

セクションナイン吉田真吾@yoshidashingo)です。

DB無停止移行は人類の夢

暗号化していないRDS MySQLから暗号化済みのAuroraに移行したいけど、スナップショットの復元でもAurora Read Replicaのマスター昇格でも一発ではリソース暗号化ができませんが、そんなときに便利なのがDatabase Migration Service(DMS)です。

DMSを使えばどちらかがリソース暗号化されたデータベースであってもフルデータロード+継続レプリケーションができます。

今回はDMSからの接続に必要な移行元のbinlogのフォーマットを変えずに(DMSでレプリケーションできないDBが移行元であっても)レプリケーションするために、間にAurora Replicaを用いて実装してみます。

f:id:yoshidashingo:20170509204051p:plain

利用する特徴

  • Aurora Read Replicaはbinlog_formatがROWでないRDS MySQLから簡単に継続レプリケーションできる
  • DMSは非暗号化<->暗号化データベース間の読み書きをサポートしている
  • DMSのターゲットデータベースのロジカルレプリケーションはターゲットへの書き込みもできる

少しAWSに覚えのある方であればこの特徴だけでどうやればよいかわかると思うので、後は読まなくても大丈夫です、これを組み合せることで無停止で移行します。

手順

説明用の3種類のデータベースインスタンス名は以下のような名前になっています。

  • 移行元データベース(MySQL) mydbinstance
  • 中間データベース(DMSのソースデータベース: Aurora) mydbinstance2
  • 移行先データベース(DMSのターゲットデータベース: Aurora) mydbinstance3

移行元データベース(MySQL)

移行元のRDS MySQLではデフォルトのパラメータグループを作成している想定です。

f:id:yoshidashingo:20170509210044p:plain

バックアップは1日以上(今回の場合は2日)設定されているものとします。ストレージ暗号化はされていないので、この状態からでは暗号化済みのAuroraに一発で移行することはできません。

f:id:yoshidashingo:20170509210535j:plain

中間データベース(Aurora Read Replica)

CDCを利用した継続レプリケーションを行うために、移行元のRDS MySQLのAurora Read Replicaを作成します。

Auroraのbinlogからレプリケーションを有効にするためにDBクラスターパラメータグループの設定変更をします。デフォルトのものは設定変更ができないので、あらかじめ新規にDBクラスターパラメーターグループを作成して以下の値を変更しておき、Aurora Read Replicaの作成時にこれを適用してインスタンスを作成します。

  • binlog_checksum NONE
  • binlog_format ROW

f:id:yoshidashingo:20170509211020p:plain

また、mysqlクライアントで接続し、binlogの保持期間の変更を行っておきます。エラーでレプリケーションが止まっても十分に対応できる程度の時間にしておきましょう。今回は12時間に設定しておきました。

mysql> CALL mysql.rds_set_configuration('binlog retention hours', 12);

移行先データベース(暗号化済みAurora)

移行先は(せっかくの機会なので)暗号化しときましょう。デフォルトのDBクラスターパラメータグループだと後で設定を返るときに不便ですが今回は無視します。こちらのbinlogは今回不要です。

f:id:yoshidashingo:20170509212314j:plain

DMS

適当なサイズでDMSインスタンスを作っておきます。

ちなみにこの状態だとMySQLとAurora Read Replicaのテーブルにはデータが入ってますが、ターゲットにはデータが入っていない状態になります(上から1号機/2号機/3号機)

f:id:yoshidashingo:20170509213904p:plain

ソース/ターゲットデータベースに接続する

f:id:yoshidashingo:20170509212944p:plain

タスクを作成して実行する

対象のスキーマを指定してマイグレーションタスクを投入します。マイグレーションタイプには初期データのフルロードと継続レプリケーションを選択しましょう。

f:id:yoshidashingo:20170509213302p:plain

このタスクを実行すると、フルデータロードされてターゲットにもデータが同期されます。

f:id:yoshidashingo:20170509214019p:plain

このタイミング、あるいはフルデータロード後に一時停止しておいて一度「Analyze Table」しておきましょう。

継続レプリされているか確認する

もう一行挿入して継続レプリされているか確認しましょう。

f:id:yoshidashingo:20170509214311p:plain

アプリ切替

移行元ではなくターゲットに直接データを書き込んでみましょう。

f:id:yoshidashingo:20170509214636p:plain

ターゲットにのみデータが書き込まれました。

移行元にデータを書き込む

この状態で一部のトランザクションが移行元側に入ってしまっても、ターゲットにまで伝搬するので問題ありません。

f:id:yoshidashingo:20170509215125p:plain

よって、複数のアプリの切替が必要な場合でも、このレプリケーションが継続レプリケーションを行い始めた後であれば、それぞれ任意のタイミングで切替が可能になりうるということが分かります。

まとめ

手順を見れば分かるとおり、同一レコードへのトランザクションが移行元/移行先に別々に入ってしまう場合や、Auto Increment属性が付与されているテーブルに移行元/移行先に別々に入ってしまう場合などについての考慮は必要になりますが、そういう条件が発生しえない場面においては、レプリケーションを切り離すタイミングとアプリの切替を同期する必要がなくなるのは嬉しい方法ではないかと思います。

また、統計情報の再作成のためのAnalyze Tableのタイミングについては今回適当に継続レプリケーション中に行いましたが、実際はターゲットデータベースにかかるワークロードを考慮したタイミングを精査しておく必要があると思います。実際DMSではフルデータロード後で継続レプリケーションを開始する直前に一時停止させることができるので、そのタイミングでAnalyzeさせることも可能です。

また、データベースの移行・切替は非常にセンシティブな作業ですので、実際に作業する時は事前に十分な検証したうえで実行しましょう。

参考

docs.aws.amazon.com

docs.aws.amazon.com