Timee Product Team Blog

タイミー開発者ブログ

Aurora MySQLのアップグレード後ロールバック方法を検討してみた

エンジニアリング本部 プラットフォームエンジニアリング1G 橋本です。我々のグループでは業務の柱の一つとして、クラウドインフラの構築・運用を行っています。その中でAmazon Aurora MySQL(以下、AuroraもしくはAurora MySQL)のアップグレードがビジネスインパクトが大きい作業となりました。本記事はAurora MySQLアップグレード方法の検討について記述した投稿になります。

この記事のまとめ

  • 比較的大きなデータで且つ更新量の多いAuroraクラスターのアップグレードで且つダウンタイムが少ないロールバック方式を検討していました
  • ダウンタイム最小化の部分で大きな課題感があったが、Auroraの機能追加により大きく緩和できることが分かりました
  • この記事では、ダウンタイム最小化を軸にした場合のロールバックに関する課題感と解決方法を追加された当該機能に触れながら紹介します

前提情報や課題感について

Blue/Green Deploymentsによるアップグレードとは

Auroraの機能により既存クラスタをベースに無停止で新規クラスターをBlue/Green Deploymentsという機能を用いて作成することができます。なお、Green側クラスターにはEngineVersion(8.0.mysql_aurora.3.02.0, 5.7.mysql_aurora.2.11.2 etc.)や、パラメータグループを既存クラスターと異なるものを適用できるので、アップグレードや新規設定の適用をダウンタイム少なく行うことができます。

切替自体はワンクリックで可能でSwitchOverという命令を与えると、1分程度のダウンタイムは発生しますが特に難しいことはなくGreenクラスターに切り替えることができます。この際にアプリケーションサーバー等が参照しているエンドポイントも自動で切り替わります。

B/Gデプロイメントのイメージ

もしもの場合はロールバックしたい

この記事のテーマはGreenクラスターに切り替えたあとにアプリケーションサーバー等で不具合があった場合に、元のクラスター(Blueクラスターそのもの or 同等の構成のもの)にロールバックできるかどうか、その手法についてになります。

ロールバックの可能性はそれほど高くないと考えています。当然事前に動作検証はテスト環境で行い、アップグレードに臨みます。しかし、何らかの不具合が本番環境でのみ発生する可能性はゼロではない為、万が一の備えであってもロールバックの手法はコンティンジェンシープランとして持っておく必要があります。弊社でもサービスの中核にAurora MySQLを利用しているため、事業継続性の観点でも重要なものとなります。

ロールバックから戻せるか?

検討したロールバック手法

当初は次の表の3つの方式を検討しました。なおダウンタイムはできれば数分、長くても30分程度のダウンタイムを許容(◯)として考えています。

この比較は更新頻度や量が多く、ダウンタイムを極小化したいユースケースでAurora MySQLを使用している前提としています。たとえば、分析用DBであったり、小規模のDBであったりすると許容できるポイントが変わると思われます。

方式名 ダウンタイム 互換性 容易さ 特徴
AWS Database Migration Service(DMS) データ互換性の担保が難しい
GreenのバックアップデータをBlueへリストア ダウンタイムはデータ量に比例
GreenからBlueへの逆方向レプリケーション(没案) ロールバック時のダウンタイムに加えて、SwitchOver前にダウンタイムが必要

DMS方式

AWS DMSを利用してGreenクラスタの更新情報をロールバック用クラスターに同期する方式です。当初この方式での移行を検討していました。流れは以下の通りになります。

  • ★ 事前準備
    • 予めロールバック用クラスターを既存クラスターと同じ定義で作成しておく
    • DMSでGreenからロールバック用クラスターに変更データキャプチャ(CDC)により適宜データ同期が行われる構成にしておく
  • ★ SwitchOver!
  • ★ 問題発生!ロールバック開始 - ダウンタイム
    • サービス・メンテナンス状態にする(=DBの更新が行われないようにする)
    • DMS定義を削除する
  • ★ ロールバック終了 - サービス再開
    • アプリケーション・サーバーの接続先をロールバック用クラスターに変更してサービスを再開する

この方式はDMSの設定をしてしまえば複雑な操作・設定を必要とせず、簡単にロールバックができるところが特徴になります。この点が最大の魅力であり、当初の採用理由だったのですが、テストを行っているとデータ互換性の担保が難しいことに気づきました。

特に、DMSのユーザーガイドに記載されている制限やデータ型の変換が大きな問題となりました。

例えば、上記ガイドに制約として 列の AUTO_INCREMENT 属性は、ターゲットデータベース列に移行されません。 と記載されています。AUTO_INCREMENTのような属性はMySQL独自の自動増分の機能であり、ターゲットデータベースがOracleやPostgreSQLなど異なる場合にも汎用的に移行可能なように引き継がれない仕様となっているようです。

同じく、例えばJSON型がCLOB型に型変換をして同期するデフォルトマッピングがあり、ソースとターゲットデータベースでデータ型が変わってしまう点も、MySQL to MySQLでの単純なデータコピーに使いたい用途としては考慮事項が多くデータ互換性という観点では☓(バツ)を付けざるを得ないと判断しました。

リストア方式

次に検討したのはMySQLのバックアップ・リストア機能を用いてロールバックをする方式です。互換性の維持を主眼にすると以下の方式は確実な方式となります。

  • ★ 事前準備
    • 予めロールバック用クラスターを既存クラスターと同じ定義で作成しておく
  • ★ SwitchOver!
  • ★ 問題発生!ロールバック開始 - ダウンタイム
    • サービス・メンテナンス状態にする(=DBの更新が行われないようにする)
    • GreenクラスタのDBバックアップを取得する
    • ロールバック用クラスターに先のバックアップデータでリストアを行う
  • ★ ロールバック終了 - サービス再開
    • アプリケーション・サーバーの接続先をロールバック用クラスターに変更してサービスを再開する

DBバックアップ取得やリストアはmysqldumpなどのバックアップツールを用います。マネージド・サービスを普段利用しているとCLIベースでのバックアップ・リストアには一定の習熟が必要となるため、”容易さ”は△としています。

この方式の最大の問題点はバックアップ・リストアに要する時間でした。1TB弱(数百GB)オーダーのデータを対象として事前にテストしたところ、mysqldumpでは数十時間かかることが分かり全く現実的ではありませんでした。

mysqlshを用いて並列度を上げることで高速化できますが、それでも4時間程度の時間を要することが分かりました。Aurora MySQLのデータ書き込みがボトルネックとなっておりインスタンスサイズを大きくするなどして検証しましたが、これ以上の高速化は見込めず採用が難しいと判断しました。

なお、データ量が100GB以下程度と比較的小さければ数分〜30分程度のダウンタイムを許容する限りは、この方式が確実ではないかと考えています。

逆レプリ方式(没案)

ここまで来て、最後の手段ではありますがGreenクラスターからのデータ同期にMySQLのレプリケーション機能(Primary/Secondary方式)を用いることができれば良いのではないかということに思い当たります。Auroraでレプリケーション設定が可能か分からなかったのですが、Cyber Agentさまの記事 にズバリ書いていたため参考にさせていただきました。流れは以下のようになります。

  • ★ 事前準備
    • Blueクラスターを利用するため、ロールバック用クラスターは”作成しない”
  • ★ 静止断面取得作業 - ダウンタイム
    • サービス・メンテナンス状態にする(=DBの更新が行われないようにする)
    • ★ SwitchOver!
    • GreenクラスターをPrimary、BlueクラスターをSecondaryとしたレプリケーションを設定して同期させる
    • サービス・メンテナンスを解除する
  • ★ サービス再開
  • ★ 問題発生!ロールバック開始 - ダウンタイム
    • サービス・メンテナンス状態にする(=DBの更新が行われないようにする)
    • Blueクラスターを昇格させる(レプリケーション設定を解除)
  • ロールバック終了 - サービス再開
    • アプリケーション・サーバーの接続先をBlueクラスターに変更してサービスを再開する

この方式は標準的なMySQLレプリケーションを用いるため、データ互換性に対する懸念は少ないことが期待できます。しかしながら、SwitchOverを行う前にサービスダウンを発生させる必要があることが問題となりました。サービスダウンが必要な理由は所謂、静止断面を作るためになります。

# ※前提: サービス停止(更新停止)をした状態でSwichOverを行う

# Greenクラスターで現在のポジション(静止断面)を取得する
[Green] > show master status;
+----------------------------+----------+--------------+------------------+-------------------+
| File                       | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------------------+----------+--------------+------------------+-------------------+
| mysql-bin-changelog.000133 |      941 |              |                  |                   |
+----------------------------+----------+--------------+------------------+-------------------+

# BlueクラスターでGreenクラスターをPrimaryとしたレプリケーション定義を行う(CHANGE MASTER TO相当)
CALL mysql.rds_set_external_master(
  'GreenクラスターのWriterEndpoint',
  3306,
  'replicationユーザ名',
  'replicationパスワード',
  'mysql-bin-changelog.000133',
  941,
  0);

Green, Blueクラスターは、それぞれ異なるbinlogファイル・ポジションを保持しているため、BlueクラスターにとってGreenクラスターのどのポジションから読み出しにいくべきか?、レプリケーション開始時点のポジションが必要になります。

上記のコマンド例のように、show master status; コマンドによりポジション取得を行うためには書き込みを一旦停止する必要があり、これがSwitchOver前にサービス・メンテナンスを行う理由となります。

結果的には、本案は没案となりました。そもそもロールバックは万が一の備えであるため、その備えのための事前作業でサービス停止が100%発生することは許容できなかったからです。

困った。どうしよう?

ここまで長々と各方式の説明をしてきましたが、これ!という方式が見つかりません。大きめのデータを持つAuroraをダウンタイム少なくロールバックする手法を確立すべく検討をしていましたが、行き詰まってしまいました。

タイムリーな機能を教えてもらえた?

AWSの方にも相談をしながら検討をしていたのですが、24’ 8/6に公開されたこのブログポストを紹介していただきました。先ほど没案となった逆レプリ方式を改善できる一手になる!という手応えを得て検証を開始しました。

SwitchOver時に静止断面を教えてくれる

ポイントはSwitchOverでGreenクラスターに切り替わった瞬間のポジションを静止断面として教えてくれることにあります。次の図のようにSwitchOverしたときにクラスターEventとしてバイナリファイルとポジションがメッセージに出力されます。

一見すると地味な機能ですが、先に没案の課題として述べたとおり通常はサービス停止をしなければ取得できない情報が無停止で取得できるので、とても強力な機能です。

SwitchOver時のイベントメッセージ

あとは次の図のように、もともとあったBlueクラスターをSecondaryとしたレプリケーション設定を行います。なお、ブログ執筆時点では記事中の設定に誤りがあり、BlueクラスターのWriterEndpointを指定する記述になっています。正しくはここに記載したように”GreenのEndpoint”を指定する必要があるのでご注意ください。

詳細の手順は先のAWSブログポストにすべて記載されていますので、ここではこれ以上の詳細は割愛します。気になった方は是非ご参照ください。

逆レプリケーションのイメージ

逆レプリ(新案)はどうなるのか?

逆レプリ(新案)は以下のような流れになります。SwitchOverを行ったあとに逆レプリ設定をして同期を行っておく点がポイントになります。

  • ★ 事前準備
    • Blueクラスターを利用するため、ロールバック用クラスターは”作成しない”
  • ★ SwitchOver!
    • クラスターEventに出力された静止断面のポジションを確認する
    • GreenクラスターをPrimary、BlueクラスターをSecondaryとしたレプリケーションを設定して同期させる
  • ★ 問題発生!ロールバック開始 - ダウンタイム
    • サービス・メンテナンス状態にする(=DBの更新が行われないようにする)
    • Blueクラスターを昇格させる(レプリケーション設定を解除)
  • ★ ロールバック終了 - サービス再開
    • アプリケーション・サーバーの接続先をBlueクラスターに変更してサービスを再開する

いままでの方式案との比較

上記を踏まえて、他案との比較を行いました。あくまで弊社環境においてダウンタイムは30分以内という条件で選んだ場合、この逆レプリ(新案)方式はベストな選択となりました。

1点、容易さが△としているのは、Aurora MySQLの運用において普段はあまり行わないCLIベースでの操作を行うことであったり、binlogによるレプリケーション同期の機序について理解する必要がある点に起因しています。

組織的な対応強度を備えるために一定の学習コストがかかりますが、一つの技術習得としてじっくりと時間をかけて取り組んでいこうと考えています。

方式名 ダウンタイム 互換性 容易さ 特徴
AWS Database Migration Service(DMS) データ互換性の担保が難しい
GreenのバックアップデータをBlueへリストア ダウンタイムはデータ量に比例
GreenからBlueへの逆方向レプリケーション(没案) ロールバック時のダウンタイムに加えて、SwitchOver前にダウンタイムが必要
GreenからBlueへの逆方向レプリケーション(新案) 没案の事前ダウンタイムが克服された!

まとめ

この投稿では弊社でAurora MySQLアップグレードを行う際に、データ量が比較的多いデータベースで、ダウンタイムを極小化してロールバックを行う方式について検討した軌跡についてシェアをしました。

同じような課題に突き当たった方もいるのではないかなと思います。この記事が課題解決の参考になれば幸いです。