こんにちは、インフラのテックリードをしている沼沢です。
この記事は、株式会社asken (あすけん) Advent Calendar 2024 の11日目の記事です。
また、「あすけんの Aurora 2 → Aurora 3 へのメジャーバージョンアップ軌跡」の第1弾の記事です。
あすけんは AWS 上で動いており、データベースには RDS Aurora を利用していて、各社同様にメジャーバージョンを上げなければならない状況でした。
しかし、その道のりは決して簡単なものではありませんでした。
本稿は、そんな Aurora メジャーバージョンアップ完了までの軌跡をお伝えする記事の第1弾です。
こんな話は今さら需要が無いかもしれませんが、今現在 RDS 延長サポートに突入し、メジャーバージョンアップをこれから行う予定の方々の参考になれば幸いです。
序章
2022〜2023年
この時インフラチームでは Aurora 2 の EOL は把握していたので早めに対応を進めたかったのですが、対応はインフラエンジニアだけではできません。
メジャーバージョンアップを進めるためには、プログラム側の影響調査や修正を行う必要もあるため、バックエンドエンジニアも巻き込む必要がありました。
ただ、まだ EOL まで1年以上ある状態で、他案件を止めてでもこの対応に時間を割いてもらう必要性をうまく説明できず、説得ができずにいました。
また、この時はまだ RDS の延長サポートについては発表されていない時期だったこともあり、「1年以上あるが間に合わなかったらどうしよう」という焦りがジワジワと募っていったのを覚えています。
そんな中、2023年9月に Aurora の延長サポートが発表されました。
https://aws.amazon.com/jp/about-aws/whats-new/2023/09/amazon-aurora-rds-extended-support-mysql-postgresql-databases/
対象となるマイナーバージョンに上げておけば、自動的に延長サポートに入ることがわかり、少し安心材料を得ることができました。
ただ、延長サポートの料金はかなり高く、いつまでも延長サポートでいるわけにはいかないため、なんとか EOL である2024年10月31日までに対応を終わらせなくてはならないと考えていました。
〜2024年6月ごろ
その後、インフラのチームにバックエンドのメンバーがジョインしてくれたことをきっかけに、メジャーバージョンアップ対応が進み始めました。
Aurora 2 (MySQL 5.7 互換) → Aurora 3 (MySQL 8.0 互換) にメジャーバージョンアップした時のバックエンドプログラム側の修正箇所の洗い出しと修正対応、テスト等、バックエンドのメンバーによって着々と進められていきました。
…ここまでで私のようなインフラエンジニアは何をしていたのか?
それは、バージョンアップ方法の検討と検証です。
バージョンアップ方法の検討
RDS Aurora のメジャーバージョンアップを行うためには以下の方法が選択肢として挙げられます。
- 対象のクラスタを直接バージョンアップするインプレースアップグレード
- Blue/Green Deployment 機能を使った新旧バージョンの切り替え
- レプリケーションを使った新旧バージョンの切り替え
- mysqldump などのツールを使った export / import によるデータ移行
あすけんはサービス開始から17年が経過し、現在のデータ量は膨大なサイズです。
データ量から、4 による手法は何時間もかかることが想定されること、実行中はサービスを停止をしなければならないことから現実的では無いため、自然と選択肢から外れます。
次にサービスを無停止もしくは短時間の停止で移行を実現する方法として 2 または 3 が選択肢として有力ですが、これもコスト面から見送りました。
3 の場合もですが、2 も内部的には RDS Clone による複製を作る(※1)ため、ストレージコストはそこまでネックではない(※2)のですが、本番稼働中のインスタンスと同スペックのインスタンスを用意する必要があり、並行して稼働している期間のコストがかかるためです。
※1 https://aws.amazon.com/jp/blogs/news/new-fully-managed-blue-green-deployments-in-amazon-aurora-and-amazon-rds/ を参照
※2 https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Managing.Clone.html#Aurora.Managing.Clone.Protocol を参照
と言った具合で選択肢を絞っていき、メンテナンス時間は 2, 3 と比べると長くなりますが、最終的には 1 のインプレースアップグレードによるバージョンアップを選択しました。
2024年6月ごろまでには、ステージング環境においてインプレースアップグレードによるメジャーバージョンアップが問題なく実施できることの検証が完了していました。
そのため、あとはプログラム側の対応が終わればバージョンアップのメンテナンススケジュールを計画できる状態であり、待ちの状態でした。
絶望の始まり
2024年7月
いよいよ本番環境のメジャーバージョンアップのスケジュールを調整する段階となりました。
ここまで順調に進んできたのですが、想定外の事態が待ち受けていました。
メンテナンス時間を決めるのにインプレースアップグレードの実行時間を図るため、本番環境の Aurora クラスタを Clone してインプレースアップグレードを試みた時のことです。
本番環境の Aurora クラスタ Clone では、インプレースアップグレードがエラーで失敗するのです。
そして、ここから様々な困難に直面していくことになりますが、まずはこのエラーについて説明します。
失敗原因
インプレースアップグレード実行時には、AWS にて事前チェックが実施されます。
https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.upgrade-prechecks.html
事前チェック結果は upgrade-prechecks.log
というファイルに出力され、エラーになった場合はこのログファイルを確認してエラーを解消していくことになります。
失敗の原因となったのは以下の内容です。(upgrade-prechecks.log
より抜粋)
{ "id": "schemaInconsistencyCheck", "title": "Schema inconsistencies resulting from file removal or corruption", "status": "OK", "description": "Error: Following tables show signs that either table datadir directory or frm file was removed/corrupted. Please check server logs, examine datadir to detect the issue and fix it before upgrade", "detectedProblems": [ { "level": "Error", "dbObject": "xxxx_db.yyyy_table", "description": "present in INFORMATION_SCHEMA's INNODB_SYS_TABLES table but missing from TABLES table" } ] }
このエラーはデータディクショナリの破損などによって検出されるものです。
MySQL 5.7 および Amazon Aurora MySQL バージョン 2 では、DDL が突然中断されると、データディクショナリが不整合なテーブルが発生する可能性があります。
(Amazon Aurora MySQL バージョン 2 (MySQL 5.7 互換) からバージョン 3 (MySQL 8.0 互換) へのアップグレードのチェックリスト、パート 1 より引用)
解決策の検討
この問題を解決してアップグレードを進めるには、上記ブログに記載の以下の方法のいずれかで進める必要がありそうでした。
- mysqldump などのツールを使った export / import によるデータ移行
- binlog レプリケーションを貼ったレプリカクラスタがある場合は、レプリカ側に同じ問題が存在するか確認し、存在しなければそれを使ってアップグレードする
- ポイントインタイムリカバリ(PiTR)で不整合発生前の状態のクラスタを復元できる場合は、復元されたクラスタに対して差分を移行し、アップグレードする
しかし、この3つの方法はどれも困難です。
1 は前述の通りデータ量の多さから難しい。
2 は、そもそもbinlog レプリケーションを貼ったレプリカクラスタを持っていないため不可能。
3 に至っては、不整合の原因となっているテーブルが数ヶ月以上前に削除したテーブルであることがわかっており、PiTR やスナップショットからの復元ができないため不可能。
この時点で敗戦ムードが漂い始めました。
ダメ元で AWS サポートにも他に方法が無いか問い合わせてみたところ、以下の方法を提示いただきました。
- スナップショットやポイントインタイムリカバリから DB クラスタを作成し、エラーとならずにアップグレードできるか確認
- 新規に Aurora MySQL 3 クラスタを作成し、mysqldump や バイナリログレプリケーション等でデータを移行
- 新規に Aurora MySQL 3 クラスタを作成し、AWS DMS を使ってデータを移行
1 は前述の通り不整合発生前に戻ることができないため不可能。
2 は可能ではあるが、これもデータ量の点で非常に厳しい。
3 では DMS (Database Migration Service) を使ってはどうかという提案でしたが、これも結局 2 と同様にデータ量の点で厳しい。
という結果となり、もはやデータ量の多さから避けてきた方法(データ移行+レプリケーション)を数ヶ月単位の長期戦覚悟でやるしかない状況に追い込まれました。
第2弾 希望篇 へ続く。
We are hiring !
askenを一緒に盛り上げてくれる仲間を絶賛募集中です!