はじめに
インフラ基盤グループの大谷です。日頃はトクバイサービスの基盤運用を担当しています。
今回はRDS Aurora MySQL のアップグレード事例についてご紹介したいと思います。
先頃、AWSより、MySQL5.6互換のRDS Aurora MySQL version 1においてEOLが発表されました(Preparing for Amazon Aurora MySQL-Compatible Edition version 1 end of life)。
現時点でのAWSからアナウンスされているEOLのスケジュールは以下の通りです。
2022年9月27日以降
- 新たなRDS Aurora MySQL version 1(MySQL5.6互換)インスタンスを作成できなくなる
- 以下のみ可能
- スナップショットからのリストア
- リードレプリカの追加
- インスタンス構成の変更
- ポイントインタイムリストア
- 既存のバージョン1クラスターのクローン作成
2023年2月28日以降
- 2023/2/28以降のメンテナンスウィンドウにて強制的にRDS Aurora MySQL version 2(MySQL5.7互換)へアップグレードされる
ロコガイドでは珍しく EOLまでに時間を残してアップグレード作業を完了できたのでこれから作業をする人達に向けて知見を共有したいと思います。
これまでのAWSの傾向からするとEOLのスケジュールは延伸傾向にありますが、アップグレードするとJSON型を利用できるようになったり、より料金/パフォーマンスに優れたGraviton2インスタンスを使用できる(新しい Graviton2 インスタンスを使用して Amazon Aurora で最大 35% 優れた料金/パフォーマンスを実現)などのメリットも享受できるので早々に作業されることをおすすめします。
ロコガイドで実施した作業の流れ
ドキュメントチェック
まず初めに、作業に当たり参考にさせていただいた資料を紹介します。今回の作業に当たり、これらの記事には大変お世話になりました。これから作業に取り掛かる予定の人は一通りチェックすることをおすすめします。
AWS公式からアナウンスされているアップグレード手順
- Aurora MySQL DB クラスターのメジャーバージョンを 1.x から 2.x にアップグレードする
- Performing major version upgrades for Amazon Aurora MySQL with minimum downtime
各バージョンのCHANGELOG
参考にさせて頂いたブログ記事
作業手順の確定
次にアップグレード手順パターンの検討を行いました。 ざっくりと大きく分けて2パターンの手順にまとめられます。
パターン1. インプレースアップグレード
やり方
RDSのマネジメントコンソールからバージョンを変更して適用
pros
AWSが用意してくれた標準のアップグレード機能で信頼性も高くお手軽
cons
- ダウンタイムが長い
- アップグレード前の旧インスタンスが残らないので、万が一の切り戻しに一定の時間がかかる
パターン2. レプリケーション&スイッチオーバー手順
やり方
- 対象クラスタのスナップショットを取る
- 採取したスナップショットからクラスタを復元しインプレースアップグードを実行
- 対象クラスタらアップグレードしたクラスタへレプリケーションを張る
- アプリケーションの向き先をアップグレードしたクラスタへ切り替える
※レプリケーション・スイッチオーバーの方法にDMSやRDSProxyを採用するなどの方式もあり。
pros
- ダウンタイムが短い
- アップグレード前の旧インスタンスが残るためより迅速に切り戻しができる
- ただし、切替え中のクエリについてProxySQL等を途中に咬ませる等の切り戻し時に向けてのサポートは別途必要。
cons
- 検証コスト/作業コストがインプレースアップグレードよりも多くなる見込み
サービス全体をメンテナンスに入れる方針が許容されたこと、AWSの標準に乗ったほうが安心だろうということでインプレースアップグレードを採用しました。
事前準備/検証作業
ロコガイドでは複数のAuroraクラスタを運用しています。本番環境で悪影響が発生した場合にリスクが少ないAuroraクラスタから順次、事前準備と検証作業を行っていきました。
事前準備: パラメータグループの作成と差分チェック
事前準備として、デフォルトのパラメータグループと比較して、既存のパラメータグループに独自に設定しているパラメータの吸収と、アップグレードにより、意図しないパラメータグループが新たにtrueに設定されていないかの確認を行いました。
検証作業: ステージング環境での動作確認
検証作業としてざっくりと以下の作業を行いました。
- バックエンドエンジニアによるバージョンアップ影響のある実装の有無のチェック
- 本番環境からスナップショットを採取し検証クラスタの作成
- 検証クラスタにステージングアプリケーションを接続しCIと手動動作確認の実行
- アップグレード作業手順の確定と作業時間の見積もり
検証を通じて発見したエラーや問題については実装の変更や作業手順への反映で修正を吸収していきます。
また、作業手順を含めて検証を行うため、このステップで簡単に以下のような方針の作業手順を取りまとめました。
- メンテナンスモードによるメンテナンスページの掲出とリクエストの流入停止 - インプレースアップグレードの実行 - インプレースアップグレード中に生成されるSnapshotから、トラブル時用の切り戻しAuroraクラタの作成 - 各種動作確認 - 通常時よりも厚めに - 主要機能のクリティカルパスを改めて手動実行 - メンテナンスモードを解除
実際に発生した問題
アップグレード作業そのものや、予定していた作業後動作確認は無事完了したものの、メンテナンスモードを解除しサービスを開放した後に トクバイWEBにおいて特定の店舗ページのみ画面が表示できない
というトラブルが発生しました。
問題を検知してから行ったこと
原因特定のため以下の作業を実施しました。
- メンテナンスモードを有効化し、メンテナンスページの再掲出
- 改めてパラメータグループの総チェック
- Auroraクラスタのバージョン切り戻しの準備
- AWSサポートにHighPriorityで問い合わせ
どのように解決したか
入っていてよかったエンタープライズサポート
ロコガイドはAWSエンタープライズサポートを契約しています。 原因が特定できず、いよいよ切り戻し作業を始めようとしたタイミングで弊社担当のテクニカルアカウントマネージャーが以下の記事を提示してくれました。
原因はMySQLエンジンのアップグレードによりオプティマイザのデフォルトの挙動が変更されたことによるものでした。記事に記載の通り optimizer_switch のcondition_fanout_filterを無効化することで問題は収束しました。
事前にどうするべきだったか
今回発生したトラブルについて反省点は3つあります。
準備不足1. パラメータグループの確認不備
事前に設定差分の洗い出しはしていましたが 予期せぬ設定が有効化されていないか
を中心にチェックしていたため、設定がデフォルトで有効化され設定値もNULLであるパターンを見落としました。
パラメータグループはデフォルトで有効化されていることを念頭に、新たに増えた項目を含め全ての差分について入念にチェックすべきでした。
準備不足2. クエリの実行計画の確認・検証不足
実際に流れているクエリベースで、クエリの実行計画をチェックすべきでした。事前にslow_query.log/general.logを採取し、新旧のバージョンで実行計画の比較をするべきでした。
準備不足3. カナリアリリースを検討してもよかった
旧バージョン->新バージョンへのレプリケーションはMySQLのアップグレードで一般に行われることですし、Auroraでも同様に構成可能なため、WEBへのGETリクエストの一部のクエリだけでも新バージョンへ流せるようなカナリアリリース構成が取れれば今回の問題は事前検知できたはずです。 今後はカナリアリリースも視野に検討したいと思います。
最終的にやるべきことリスト
今回の経験を踏まえて、アップグレード時にやるべきことリストは以下のとおりです
1.ドキュメントを読もう - 推奨手順を確認しよう - CHANGELOGを確認しよう 2. 作業手順を確定しよう 3. 検証しよう - デフォルト設定も変更されていることを念頭にパラメータグループの差分を確認する - 影響がある実装が存在しないかチェックする - 動作検証を行う(CI&手動検証) - slow_query.log/general.logをベースにクエリの実行計画を確認する - カナリアリリースについて検討する 4.本番作業 - 迅速に切り戻せるようにしよう - 万が一の時のためにすぐにAWSに問い合わせられるようにしよう
さいごに
これからアップグレードを計画されているみなさん頑張ってください。 なお、今回アップグレードを行ったAurora version2(MySQL5.7互換)の次のバージョンとしてAurora version3(MySQL8互換)が既にリリースされていますが、ロコガイドではまだ移行を計画する予定はありません。少なくとも公式にインプレースアップグレードがサポートされた後かなと考えています。