Amazon AuroraでVPC間DB移行をできるだけ短いダウンタイムで実現する

Increments × cyma (Ateam Inc.) Advent Calendar 2020 の16日目は、株式会社エイチーム EC事業本部の@shimura_atsushiが担当します。
# 初めに
サイマではアプリケーションが利用するDBとしてAamzon RDSのAurora MySQLを採用しています。
VPCを跨ぐデータベースの切り替えが必要となりました。
本稿では行ったDBの移行手順をご紹介いたします。

# 参考資料
本稿ではRDSのVPC間レプリケーションを手軽に実施できることを目的としてますが
より詳細にRDSのレプリケーションについて知りたい方は以下のAWS公式ドキュメントを併せてご覧ください。
[Aurora と MySQL との間、または Aurora と別の Aurora DB クラスターとの間のレプリケーション (バイナリログレプリケーション)]
(https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Replication.MySQL.html)


# メンテナンス構成
DB移行はまず稼働中DBからスナップショットから移行先のDBを復元します。復元後のデータ同期のためにレプリケーションを行います。
レプリケーションの簡単な構成は以下の図のとおりです。
![aws_rds_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311437/f47d52a1-e962-69f8-05f6-25729e97b2ce.png)

# バイナリログの有効化
バイナリログを用いたレプリケーションを行うのでバイナリログを作成する設定を有効にします。
対象のDBクラスターを選択したのち`設定`タブから`DBクラスターパラメータグループ`をクリックすることでDBクラスターのパラメータグループ設定画面へ遷移できます。
![aws_rds_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311437/1ccbbb28-fd55-6331-a395-4c8b403cfddf.png)

バイナリログを出力するには`binlog_format`の値を変更する必要があります。
初期状態は`OFF`となっていますので特定のバイナリログ形式の必要性がない限りMIXEDを選択します。

![aws_rds_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311437/38a5c62a-1a89-39cb-17d9-ea56b3b73fc8.png)

# インスタンス再起動
変更を適用するにはクラスタの再起動を行う必要があります。
レプリケーション元となるインスタンスの再起動をします、再起動は1分ほどで終了するでしょう。
このときDBが止まるのでサービスを止めることになります。

再起動が完了したら`binlog_format`の設定を確認してみましょう。
指定した値に変更されていることが確認できます。

``` sql
mysql> SHOW GLOBAL VARIABLES LIKE 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | MIXED |
+---------------+-------+
```


### バイナリログの保持期間設定
最大90日まで設定できるようですがバイナリログを作成し始めてからレプリケーションを開始させるまでの十分な余裕を持った設定すればよいと思います。

``` sql
mysql> CALL mysql.rds_set_configuration('binlog retention hours', XXX);
```

## スナップショット&レプリケーションポイントを取得する
### スナップショット取得
バイナリログを用いてレプリケーションをかける前にレプリケーションのベースとなるインスタンスのスナップショットを取得します。
AWSのコンソール、RDSのスナップショットのメニューから`スナップショットの取得`を押下してDBスナップショットの作成します。
このときスナップショットはクラスターのwriterインスタンスから取得してください。
![aws_rds_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311437/8a7a2606-b436-f093-313b-7195fab53888.png)


### スナップショットからDBの復元
作成したスナップショットからレプリケーション先のDBを復元します。
![aws_rds_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311437/1b7a03bb-0dee-d645-1e19-d33f0166d9d6.png)

暫くすると指定したスナップショットからDBが復元されます。
復元が完了したらDBのライターインスタンスを選択して`ログとイベント`タブから`最近のイベント`欄までスクロールしてください。
そうすると`システムノート`の項に「Binlog position from crash recovery is mysql-bin-changelog.00XXX XXX」と表示されてるはずです。

![aws_rds_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311437/ff2094b8-d960-31d6-f8a7-c4259385f6cf.png)

| バイナリログのファイル名 | ポジション |
|:-----------------------:|:--:|
| mysql-bin-changelog.00002 | 485 |
この2点を確保しておきます。

## レプリケーションを設定する
###レプリケーションユーザの作成と権限の設定
レプリケーション元のDBでレプリケーション専用のユーザと権限の設定を行います。

``` sql
mysql> CREATE USER 'repl_user'@'%' IDENTIFIED BY 'hogehoge';
mysql> GRANT REPLICATION CLIENT, REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
```
`%`の箇所はアクセスを許可するhostになるので細かく制御しても良いかと思いますが今回は`%`を用いて全ホストからのアクセスを許可しています。

## レプリケーションを設定する
DBを復元する際に確保しておいたバイナリログファイル名とポジションを用いてレプリケーションの設定および開始を行います。

``` sql
mysql> CALL mysql.rds_set_external_master ('$REPLICATION_ORIGEN_INSTANCE', 3306, '$USER', '$PASS', 'mysql-bin-changelog.000002', 485, 0);
mysql> CALL mysql.rds_start_replication;
```
2つ目のコマンドを実行した時点からレプリケーションが開始されます。

# レプリケーションの停止
同期をとるためにマスターへのデータの流入を止めます。
このときサービスを止めてユーザがサイトへの訪問が止まったこととレプリケーションによりマスター・スレーブ間のデータの差分がなくなったことを確認した後レプリケーションを止ます。
`SHOW SLAVE STATUS`コマンドの`Seconds Behind Master`の項が`0`であればマスター・スレーブ間のラグが無いことを表します。

レプリケーションは以下のコマンドで停止することができます。

``` sql
mysql> mysql.rds_stop_replication
```

# DBの切り替え
レプリケーションの停止したらDB参照のエンドポイントを切り替えることでDBの切り替えを行います。
サイマでは`Amazon Route53`でエンドポイントのエイリアスを作成していたのでエイリアスの設定を変更することでDBの切り替えることができました。

エイリアスの設定が完了したらサービスを再開して作業は終了です。

# まとめ
紹介の手順で2回のサービス停止を伴いました、合計のダウンタイムは17分でした。
この17分が長いのか短いのかはサービスの規模や種類によって変わってくると思いますがサービスの状態がどうあれダウンタイムを設けることなくメンテナンスを終えることが理想です。
システムの構成によってはメンテナンスの内容によってダウンタイムがどうしても避けられない場合があります。
今回のメンテナンスは過去の技術的負債によってダウンタイムを余儀なくされましたが
技術的負債を抱えた中でいかに短いダウンタイムでのメンテナンスを実現する技術も重要かと思います。
そして技術負債を抱えないための構成を構えることができる技術と知見も培って行きたいと思います


[Increments × cyma (Ateam Inc.) Advent Calendar 2020](https://qiita.com/advent-calendar/2020/increments-cyma) の17日目は、Increments株式会社の@mziyutさんがお送りします。