はじめに
昨年、Amazon Aurora MySQL を 5.6 から 5.7 へアップグレードした。
MySQL 8.0 へアップグレードするときに参考にできるおうに今回の作業をまとめておく。
アップグレード方法の検証
どんな方法があるかのか把握するのには、次の記事が非常に参考になった。 https://developers.cyberagent.co.jp/blog/archives/29438/
ここからインプレースアップグレードと、レプリケーション&スイッチオーバーの手法をそれぞれ検証した。
インプレースアップグレード
アップグレード対象のRDSクラスタを一度止めてアップグレードし、再起動する方法。
AWS RDS コンソール画面からポチポチ操作することでアップグレードできる。 https://aws.amazon.com/jp/about-aws/whats-new/2021/01/amazon-aurora-supports-in-place-upgrades-mysql-5-6-to-5-7/
いいところ
作業工数が少ない
影響が少ない
RDSクラスタを別名で作り直すことはないので、RDSクラスタ名やエンドポイントが変わらない。
このため- アプリケーションが参照するRDSのURLは変更不要
- TerraformなどでRDSクラスタを管理している場合は、変更された部分だけ変えて import し直すだけでいい。
- RDSのスナップショットをAthenaで検索しているようなシステムがあっても影響を与えない。
わるいところ
- サービス断の時間が長め
- 完了時間が見積もれない
検証では、15分ほどで完了することもあれば、2時間ほどかかったこともあった。 - 切り戻しに時間がかかる
インプレースアップグレード中に生成されるスナップショットからRDSを作り直す必要がある
レプリケーション&スイッチオーバー
Blue & Green で切り替える方法
https://aws.amazon.com/jp/blogs/database/performing-major-version-upgrades-for-amazon-aurora-mysql-with-minimum-downtime/
いいところ
- サービス断の時間が短い
- 完了時間が見積もれる
- 切り戻しがすぐにできる 切り替え後、古いRDSクラスタをレプリカとして、新しいRDSクラスタとレプリケーションしておくことで、いつでも切り戻すことができる
わるいところ
- アプリケーションなどへの影響が大きい RDSクラスタの名前もエンドポイントも変わるため。
- 準備や後片付けに工数がかかる
検証の結論
メンテナンス時間が見積もれて、切り戻しも早くできる、レプリケーション&スイッチオーバーを選択した。
インプレースアップグレードは工数が短いので非常に魅力的だったが、クリティカルなシステムなので安全側に倒した。
バージョンアップによる影響の確認
バージョン間の違いの調査
事前にしっかり情報収集して調査にあたる必要がある。
MySQL 5.6と5.7のパラメータグループのデフォルト値の差分を確認
sql_mode
のデフォルト値の影響確認 (Aurora MySQL はsql_mode=0
なので影響なかった)
どれも影響はなさそうだった。
全SQLの動作確認
アプリケーションから実行されているすべてのSQLが MySQL 5.7 で正常に動作するか確認した。
全SQLを動作確認する目的
- バージョン間の挙動の違いの影響確認
- 予約語への対応
MySQL バージョンアップのたびに予約語がかなり増えるため、全SQLのチェックが必要になる。 予約語を一つ一つチェックしていられないので、SQLを実行してみて問題なく実行できれば良しとした。 MySQL 5.7 の予約語はこちら。
やったこと
- アプリケーションの Repository 層のユニットテストが H2 を使って SQL を実行するようなテストだったので、それを開発環境に立てた Aurora MySQL 5.7 データベースへ向けて実行した。
こまったところ
- アプリケーションがかなりの数あるので、準備と設定に結構な時間がかかった
- Repository層のユニットテストのカバレッジがわからないので、目検で全 Repository のメソッドをチェックして、足りないテストを洗い出した。
かなり大変だったので、次回までにカバレッジを自動計測しておこうと思う...
動作確認
開発環境の RDS クラスタをバージョンアップして、エンドツーエンドテストを実行して影響ないことを確認した。
また、数日様子をみておかしなことがおきないことを確認した。
他にも、使っているDBマイグレーションツールなどがきちんと動くことを確認した。
パフォーマンス検証
MySQL のバージョンが変わって実行計画が変わることがあるので、パフォーマンス検証が必要になる。
問題があった場合、修正に時間がかかるため早めにテストしておいたほうが良い。 ただ今回はこのが認識が甘く、直前に確認することになってしまった。
次回は実行計画に気をつける必要があるSQLを洗い出して、事前にテストしておこうと思う。
RDSクラスタ名が変わることによる影響の調査
影響を受けるものは以下だった
アプリケーション
- RDSクラスターのエンドポイント URLを持っている
Github Actions や Lamdbda で作られたスクリプト
- 一部エンドポイントURLを持っていた
RDSのスナップショットを使うシステム
- データ集計しているシステムが RDS のスナップショットを Athena で集計していた
アップグレード手順の検証と確立
検証
基本的には、AWSのブログの手順を踏襲した。 https://aws.amazon.com/jp/blogs/database/performing-major-version-upgrades-for-amazon-aurora-mysql-with-minimum-downtime/
この手順に次のような内容を追加し、
- メンテナンス
- アプリケーションのデプロイ
- 動作確認
- 復旧手順
開発環境のRDSクラスタを使ってアップグレード手順を検証した。
手順書の整備
RDSクラスタ数がそこそこあるので、チームメンバーで分担して作業する必要があった。
このため、アップグレード手順書をきちんと整備して誰でも作業できるようにした。
また、先行して試験的に影響が少ないRDSクラスタをアップグレードし、手順書の精度をあげていった。
メンテナンス時間の見積もり
開発環境で予行演習してメンテナンス時間を見積もった。
1RDSクラスタのメンテンナス時間は10分程度だが、RDSクラスタ数が多いため1時間ほどの作業になってしまった。
アップグレード実施
夜間帯にメンテナンス時間を設けて、チームメンバーと共に粛々と実施していった。
振り返り
無事にアップグレードを終えることができた。
今回はサービス断を伴うメンテナンス時間が長くなってしまったので、次回はメンテナンス時間を短くしたい。
なお、アップグレードが終わった頃に、Amazon Aurora と Amazon RDS でのフルマネージド型 Blue/Green Deployments が発表された。 次回はこれを使えば、かなり工数削減と、メンテナンス時間の削減ができるのでは?と思ってる。
反省点としては、パフォーマンス検証がしっかりできていたとは言えないので、次回は予定に組み込みたい。
謝辞
安全のためとはいえ、かなり準備作業と夜間作業が多くなってしまった。 一緒に作業してくれたチームメンバーの方々に感謝します。