概要
仕事でAurora MySQLを3系にアップグレードで失敗してたくさんの学びを得たのでその振り返り
背景
Aurora MySQLのメジャーバージョンが標準サポートが終了するにあたって、社内のAurora MySQLを3系にバージョンアップグレードする必要があった。
対応流れ
- 影響範囲の洗い出し
- スケジュール決め
- テスト環境にてテストのアップグレードを行う
- 関係者にリスクと対応方針の説明会
- 実施
- 残対応
ざっくり上記の流れで進めていった。
やったこと - タイムライン -
前提としてEC2のRailsアプリケーションがAurora MySQLとコネクションを確立している。
1. 影響範囲の洗い出し
MySQLコミュニティ公式のドキュメントや、AWSの公式ドキュメントを読み込んで影響範囲を調査していった。
https://dev.mysql.com/doc/refman/8.0/ja/upgrading-from-previous-series.html
https://dev.mysql.com/doc/refman/8.0/ja/mysql-nutshell.html
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.MySQL80.html
自社のアプリケーションはtoBということもあり、COLLATIONに関する要件は高くないので特に設定等変えていない。
2. テストケースの用意と実施
テスト環境にて動作テストを行うためにテストケースを用意していった。
主要な機能のテストケースは特に丁寧にケースを洗い出して整理した。
テスト環境のAurora MySQLを3系にアップグレードして動作確認を進めていった。
3. アップグレード方法の検討
並行してアップグレード方法の検討をしていった。
当初はBlue/Green Deploymentを利用してアップグレードを考えていた。
その時はマルチAZのAurora MySQLはBlue/Green Deploymentできないと勘違いしており、インプレースアップグレードの検討をしていった。
ただ、事業部長などとも相談した結果、インプレースアップグレードだとサービスダウンの時間が長すぎるので別の方法を再検討した。
その時はマルチAZのAurora MySQLはBlue/Green Deploymentできないと勘違いしており
レプリケーションを使ってエンドポイントで切り替える方が良いかと考えていたが、再調査の結果上記が勘違いと分かり、Blue/Green Deploymentを使ってアップグレードを実施することに決定。
*マルチAZのRDSクラスターはBlue/Green Deploymentを利用できないが、AuroraクラスターはマルチAZであっても利用できる。
4. パフォーマンステスト
パフォーマンステストのために本番のRDSをクローンしてデータをマスクしていった。
クローンDBをテスト環境のEC2に接続し直すと、CPU使用率が100%で高止まりしてしまいテスト環境で動かせなかった。
原因としてはEC2のスペックが本番と同等になっていないこと。
EC2のスペックを検討して構築しなおした上でテストする時間がなかったため、Green環境でOPTIMIZE TABLE
を実行して実行計画を最適化した上で、移行後に遅いクエリがあったら適宜対応する方針で進めていった。
5. 移行テスト
Blue/Green Deploymentを利用して環境移行の動作確認を行なった。
確認してみると、Blue環境からGreen環境の切り替え時に10分間程度、Green環境のエンドポイントを参照できずにエラーとなる時間帯があった。
おそらくRails側でDBのコネクションキャッシュが効いている可能性があり、その時間はどうしてもサービスダウンせざるを得ないということ分かった。
6. 本番のBlue/Green環境作成
Blue/Green環境を作成し、Green環境でOPTIMIZE TABLE
を実行した。
7. 本番移行
深夜時間帯に自分一人でBlue/Green Deploymentを行なった。
8. 移行後のスロークエリを修正
COUNT(*)
系のクエリや集計系のクエリが重すぎてタイムアウトするという問い合わせが多発。
データが多い企業は画面を開くとタイムアウトするという報告が上がってきていた。
まず、発行されているクエリの実行計画を確認して、他のデータを使って対象件数を絞り込めないか検討してhotfixでリリース。
さらにBIツールのクエリもタイムアウトしていたので、クエリの実行計画を確認しながらクエリを最適化したり、ヒント句を使ってINDEXを使うように指定したりして対応した。
9. 移行後にGlueジョブからRDSのリーダーインスタンスに接続できない
Glueジョブで集計処理を行っており、RDSのリーダーインスタンスに接続して集計している。
その集計処理がタイムアウトしてしまっており、集計数値が欠損する事象も発生した。
ひとまずライターインスタンスに接続して集計処理を再開させ、過去文のデータをもとにGlueジョブ動かし、欠損した集計数値の復旧を行った。
10. テスト用に作成したRDSの削除
テスト用に作成したRDSを削除する必要があったので削除していった。
ここで誤って本番RDSを誤停止してしまい、1時間ほどサービスダウンさせてしまった。
すぐに復旧させたが、エンジニア人生で中々経験できないミスをしてしまった。
次同じ失敗を起こさないために
- 移行タスクはPJとして複数人で進めていくこと
- インフラ更新系は複数人で作業すること
- パフォーマンステスト環境を用意しておくこと
ここまでの作業はほぼ自分一人で進めてしまっており、移行日も当初の予定より遅れて実施した。
自分がリーダーポジションであり、チームメンバーも自分以外ジュニアで、PMもおらずという状況だったので、自分一人で背負いすぎてしまった感じが否めない。
これをタスクとして捉えてしまったのが良くなかった。こういったタスクはPJとして複数人を無理にでもアサインして進めるべきだった。
そうすれば、移行前の準備作業や予定日調整を行えるリソースの余白が生まれていたと思う。
ただ、詰まるところ自分の調整力不足の無さを痛感したので、この教訓を次に活かしたい。