Sionの技術ブログ

SREとして日々の学習を書いて行きます。twitterは@sion_cojp

RDS MySQLをAuroraに移行したお話

f:id:sion_cojp:20210618154937p:plain:w0

はじめに

チカクのまごちゃんねるというサービスでMySQLをAuroraに移行したお話です

中間のpendingタイムを除けば、仕様把握含め2ヶ月くらいですね。

TL;DR

  • メンテナンスモードを作った
  • 無駄に分割していたRDSも1つに統合した
  • MySQLからAuroraに移行した

Why

Aurora?

その他の改善項目

  • stgとprodで仕様が違うので統一したい
    • prodだけなぜかRDS分割して運用してる -> 1つに統一したい
    • DBの名前が違う
  • ユーザのパスワードの強化、接続元の制限をしたい
  • RDS接続用のprivateドメインを作ってインフラ側で制御できるようにしたい

過去に1回チャレンジして失敗している

一度prodのaurora移行にチャレンジしたとき、AWS DMS を使ってデータを移行しようとしたら、インデックスが正常に移行できずに失敗したという背景がありました。

また同じことする不安を持つより、今回は下記のような判断にしました

  • MySQLからAuroraリードレプリカを作成 -> 昇格させる
  • 他RDSからのDB移行は、昇格させたAuroraにmysqldumpで移行

How

進め方

f:id:sion_cojp:20210616162917p:plain

github issueをベースに進めました。会議で話した内容、手順など全てがこのissueに載ってます。

移行中のデータ欠損対策

メンテナンスモードがないため、移行中にリクエストがきてデータ欠損する懸念がありました。

またサービスダウンが発生するので、その時の表示がユーザに不親切な状態になります。

対策としては、s3hosting / ALBを介したapi の2つメンテナンスモードを用意して、slackからON/OFF出来るようにしました。

f:id:sion_cojp:20210616171759p:plain:w300

f:id:sion_cojp:20210616171812p:plain:w300

peeringの確認

VPCと新VPCが存在する環境なので、そこのpeering状況の確認が必要です。

動作チェックとして、どちらのVPCからもAuroraリードレプリカに対してアクセスできるかを確認しました。

RDS接続用のprivateドメインを作ってインフラ側で制御する

VPC内のみ利用するprivateドメインを作成しました。

これをすることで、RDSを切り替える際のdeployを省き、

またTTL=0(接続するたびにドメイン解決)にすることで、インフラ側で接続先を切り替えることができます。

その分速度は若干遅くなりますが、運用メリットのほうが大きいです。

terraformで書くとこんな感じですが、terraformだとTTL=0にセットできないので、コンソールで設定してterraformに反映します。

/* private ドメイン作成 */
resource "aws_route53_zone" "private" {
  name = "private"

  vpc {
    vpc_id = data.aws_vpc.xxxx.id
  }
}


/* DBのwriterの例 */
resource "aws_route53_record" "rds-xxx-writer" {
  zone_id = aws_route53_zone.private.zone_id
  name    = "rds-xxx-writer"
  type    = "CNAME"
  ttl     = "0" # providerが対応してないため、1に設定 -> 手動で0に設定し、terraformも0にする対応をしてる
  records = [data.aws_rds_cluster.xxx.endpoint]
}

dumpの手順

コマンド自体は簡単で、気をつけるのは --single-transaction でロックかけないようにdumpしましょう。

大きなDBに対し事前にdumpがどれくらいかかるか検証したほうが良いでしょう。

-- DB全体の容量確認
SELECT 
    table_schema, sum(data_length) /1024/1024 AS mb 
FROM 
    information_schema.tables  
GROUP BY 
    table_schema 
ORDER BY       
    sum(data_length+index_length) DESC;

-- 今回の移行対象 + 一番大きなDBでdumpして時間を測る
-- UserName / HostName / xxx は適宜変えてください
mysqldump -uUserName -hHostName -p --quote-names --opt --single-transaction --skip-column-statistics --hex-blob -R --order-by-primary xxx > xxx.sql

-- ちなみに流し込む時のコマンド
-- UserName / HostName / Password / DBName / xxx は適宜変えてください
mysql -uUserName -hHostName -p Password DBName < xxx.sql

DB名を変更する手順

DB名を変更するためには、移行先のDBを用意し、RENAMEコマンドで対応しました。

RENAMEはcopyが走らないのですぐ終わります。

-- NewDBName / OldDBName は適宜変えてください
create NewDBName

RENAME TABLE OldDBName.TableName TO NewDBName.TableName

ユーザ通知や社外調整

こちらは然るべき方からよしなにやりました。

手順書

実際の手順書は下記となりました。(具体的な内容と、題目も若干伏せます)

# 事前作業
- ユーザ作成
- auroraリードレプリカを作成(2日目)

# 当日作業1日目
- 1. s3 hostingをメンテにする
- 2. 各batch止める
- 3. Lamdaのトリガーを無効化する
- 4. ALBをメンテにする
- 5. 動画のキューが0なことを確認
- 6. スナップショットを取る
- 7. 5.6 -> 5.7にmysqlをあげる
- 8. 確認作業
- 9. Lamdaのトリガーを有効化する
- 10. メンテ解除

# 当日作業2日目
- 1. s3 hostingをメンテにする
- 2. 各batch止める
- 3. Lamdaのトリガーを無効化する
- 4. ALBをメンテにする
- 5. 動画のキューが0なことを確認
- 6. mysqldump
- 7. auroraをmasterに昇格
- 8. dumpファイルをRDSにDBを流し込む
- 9. DB名変更
- 10. Route53で一気にドメイン切り替える
- 11. DB名、ユーザ、パスワード、ホスト名変更デプロイ
- 12. 確認作業
- 13. Lamdaのトリガーを有効化する
- 14. メンテ解除

想定外のトラブル集

5.6だとAuroraリードレプリカが作成できない

5.7から対応してるので、一旦5.6 -> 5.7にmysqlを上げる必要がありました。

スナップショットに時間がかかった

stgだけスナップショットに1時間かかりました。

これはインスタンスサイズが低すぎて時間がかかった可能性がありますね。

prodが5.7になるまで時間がかかった

2時間経っても終わらなかったです。

こちらはawsに問い合わせたところ、aws側のトラブルだと判明し、そこから迅速に対応していただけました。

default parameterだと設定値が変更できない

一時的にアップデートした5.7のときにdefaultパラメータを利用したのですが、

max_connections値が少なく2日目に行くまでに若干エラーが発生しました。

defaultなので変更できず、上限値と通常のリクエストを見て1日は許容という判断になりました。

最後に

状況把握をするのにかなり時間を費やしたと思います。

terraformに残ってなかったので、awsのコンソールとgithubを見ながら現状を把握するのはとても大変でした。

そこからissueを立て、流れや手順を書いた後、関係者に的確にレビューしていただいたので、スムーズに終わることが出来たのがとても感謝です!