オミカレでテックリードをしております、高橋です。 ちなみにその任も後2週間足らずで終わりです。 3月からは別の会社で働く事になっておりますが、これは転職 or 退職エントリでは無いのでまたの機会に..!
いやぁーーー、この2〜3ヶ月、本当に色んなタスクを倒してきたなーーー!
— ikkitang (@ikkitang) 2021年2月11日
DMS撤退に始まり数十万円単位でのインフラリソースの削減等も完了出来る状態になった。思い残す事は何も無い。
という事で本日、高橋は最終出社日でございます!
さて、表題の通りですが、この度 オミカレでの最後の大仕事として DMS撤退、Aurora撤退を決めてきたので どんな風に進めてきたか、みたいなのをアウトプットしようかと思います。
意思決定プロセスみたいなのも僕の能力で実現出来る限り言語化してみようと思うのでなにかご参考になれば嬉しいな、と思う限りです。
ちなみに、書いてみるとDMS撤退だけでそこそこのボリュームになったので Aurora撤退編とDMS撤退編とで分割しようと思います。
今回は Aurora撤退 という事で後編です。 前編はこちら ↓
前提の記述
フィードバックを頂きましたので明示しておきまーーす。
※ この記事内では、 Aurora と記述がある場合は 明示がない限りは Amazon Aurora MySQL v1.x として扱う事とします。
※ この記事では 移行先の文脈で言及している際の PostgreSQLは RDS PostgreSQL の事を指してます。 Amazon Aurora PostgreSQL ではありません。
オミカレとAurora
Amazon Aurora (MySQL) は 皆さんご存知 AWS が開発した MySQLと互換性のあるRDBの一種ですね。
Amazon Aurora MySQL は 標準のMySQLデータベースと比べて最大で5倍高速である、という性能を誇っており、また クラスターという概念を用いて高可用性を担保しつつ柔軟なスケールシステムを搭載している、というようなのが概要かと思います。
オミカレでは、以前 普通のRDS MySQL を使用していたのですが RDSの負荷が上がり過ぎていて、サービスの可用性を担保出来ないとう問題から採用に至った、と聞いています。
何故Auroraを撤退する必要があるのか
さて、このAuroraですが オミカレのサービスとしては、もはや役目は終えているといっても過言は無い状態でした。 前編の DMS撤退でも言及しましたが、今オミカレでは DBリファクタリングによって メインのDBを Amazon Aurora MySQLからRDS PostgreSQL側へ変更するプロジェクトが進んでいます。 現状、メインのテーブルは割とPostgreSQLへの参照に切り替わっており、サービスの高負荷によって影響を受けるのはほぼほぼPostgreSQL側です。
オプション的なサブのデータに対してAuroraを採用するというのは、ちょっとこう 宝の持ち腐れ 感があります。 という事でAurora部分をずっとRDS MySQLにしたい欲がずっとありました。
ですが、DMSがAuroraに密接に結びついている関係で着手出来ない状態が続いていました。この度、DMS撤退が正常に完了した為、Aurora撤退に踏み切れる状態になったので、エイや! でやる決定をしました。(まあこれは相談して決めたんだけど)
Aurora撤退の方針
スケジュール的には大体一週間ぐらいで準備をするみたいなスケジュール感でした。(これは、無理言って短くしてもらった)
一週間後に深夜メンテを入れて(ここ重要)、アプリケーション内のMySQLの接続先をAuroraのRDSインスタンスからMySQLのRDSインスタンスに変えて、Auroraを削除する、というのがこのプロジェクトのゴールです。
アサインされた人は 自分含めて3人。その中でチームのスキルセットを頭に入れながら安全に進めないといけません。 意思決定の軸としては、なるべくコンソール内で完結するようにするという事を意識していました。
理由としては自分自身もあまりなれていないので、ミスをする危険性がある、という話と、失敗した時に今後残ったチームのメンバーに引き継ぎをするという事も考えるとAWS側になるべく任せる方針で進みたい、という意図でした。
という事で色々なのを考えてたのでメモ程度の紹介します。
ケース1: ダンプ => リストア
DBのバージョンアップ等で良く取られる手法の一つです。
今回の意思決定の軸と照らし合わせると RDSのインスタンスのスナップショットを取る
事と スナップショットから新しいRDSのインスタンスを作る
はコンソール内で完結します。 新しいRDSさえ作ってしまえば、残りはエンドポイントさえ書き換えてやれば完了するので後はいい感じになりそうです。
が、これはコンソール上では実現出来ませんでした。 MySQLのスナップショットからAuroraのインスタンスを作る事は出来そうだったのですが、逆はダメでした。 ただ、まあ結果的にこの方法は スナップショットで実現出来たとしても採用しなかったと思います。
まず、50~100GBぐらいのデータ量を持っていたのでメンテの時間が長くなる事が懸念点としてありました。
また、メンテのタイミングでRDSのインスタンスを用意する、という事であればメンテ当日に動作テストを行う事となってしまい、深夜にやるには非常にリスクです。デバッグ・修正の意思決定を的確にやるには 深夜には向いていない、と自分は思っています。大体ミスるし、ちゃんと準備していたとしても想定外の事は起こるというのが深夜対応なので、確実に想定外が発生しうる案を採用するのは無しかな、と思いました。
では、逆に予めダンプ=>リストアでRDSを用意しておくか? という観点もありますが、コスト観点でそれが許容されるのであれば 別の案を採用した方が良いだろう、という思いがありました。
という事で実際に採用したのがケース2のパターンです。
ケース2: レプリケーションによって新RDSインスタンスを用意する
こちらもDBのバージョンアップ等で良く取られる手法の一つかな、と思います。
ただし、AuroraからMySQLへの "異種DB間のレプリケーション" なんて出来るのかな? というのが懸念です。 はい、という事でここで出てくるのが "DMS" ですね。
オミカレ社には約3年間のDMSの運用知見が あります。 また、Aurora撤退完了後はDMSは不要になるので、DMS撤退の時に考えていたDMSを引き継ぐ時の考慮も考えなくても良さそうです。やっと、DMSを本来の使用用途として使用出来る事が出来ます。
- MySQLのRDSインスタンスを作る
- AuroraからMySQLへ全テーブルデータを移行するDMSタスクを設定する ( AuroraからMySQLへレプリケーションされる)
これがコンソール上で実現出来るわけです。
本番と同じデータが入ったMySQLが予め用意出来る事で嬉しい事として、メンテ前に Staging環境を使用して新規のDB接続の動作チェックを日中に検証出来ます。発生した問題は、落ち着いてデバッグして対処する事で深夜メンテ前に安全に進める事ができそうです。
という事でこの方針で進める事としました。
Aurora撤退にあたって解決したりとか見ておいた方が良い問題
DMSをつかう時の注意点
テーブル定義はAuroraから持ってくるようにする
DMSはデフォルトの挙動として、データを移行する際に移行先のテーブルをDROPしてから再作成する動きをします。この時の動作として、DMSはデータの移行に重きをおいてたりする(という認識)ので、制約等の類は移行してくれません。例えば、Auto Increment とかも移行されません。
ので、テーブル定義は予め Auroraから持ってきておいて復元する事で生成しました。
mysqldump -h ~~ --single-transaction --no-data -u ~~ -p hoge > table_definition.sql
上記を設定した上で、以下のターゲットテーブル作成モードを 何もしない
or TRUNCATE
を選択します。
後々の設定として 何もしない
を選択する事となります。
外部キー制約の為にレプリケーション実行順序を設定する
まず、 外部キー制約が指定されているテーブルは TRUNCATE出来ない、という問題がありました。 先述しましたが、ターゲットテーブル作成モードは 「何もしない」 を選択する事としました。
設定変更の後、実行をすると、外部キー制約違反によりエラーが発生しました。 レプリケーションタスクはデフォルトの動作として8つのテーブルを並列でレプリケーションしていきます。この際、動作の順序は保証されてないので、外部キー参照元が移行されている事は担保されていません。
その為、選択ルールをいじる必要があります。上記を参考にして設定しました。
外部キー参照元のテーブルは load-order
を 高く設定する事で先に移行されるように設定しました。
つまり、 外部キー参照として設定されている元のテーブルが全てレプリケーションされたら残りをレプリケーションするという順序になる事をDMSレベルで担保したという感じです。
いやーーー、これは僕がDMSを使用した3年ほど前にはまだ無かった機能なんですよね。昔はこれが無かったので レプリケーションタスクを分割して自分でレプリケーションタスクを開始する順番をずらして実行していました。本当に神アプデです!!
MySQL 8.0 を扱うにあたって気をつける事
ユーザー認証プラグインについて
MySQL 8.0 からユーザー認証プラグインが変更になっています。 クライアント側が対応していない場合に接続出来なくなる問題が発生します。
RDSではデフォルト値は 従来どおり mysql_native_password
となっているのでここは問題ありませんでした。
MySQL8.0から予約語になったキーワードを調整
MySQL 8.0で予約語が増えた
ことも話題に上がってたりするらしいですね。
今回結構な箇所で発生しました。 対処法としては バッククォートで囲めばOKです。
オミカレでは特に rank
が予約語になっている事で発生するエラーが多かったです。
GROUP BY id DESC
syntax error near by GROUP BY id DESC
ってエラーが出てました。
察して()
Aurora撤退によっての学びポイント
結果的にはAurora撤退の作業は30分程度で完了しました。
issueを予め作って 当日のやる作業を書き出していた事もあったりで、準備を入念に出来たのがデカかったな、と思います。結果として大きな問題もなく、作業が進められました。
深夜作業はそれから2時間後とかに終わったのですが、それは Auroraの消し方がわからず、困ったからでした()
でも、皆次に動く事を意識しながら議事録的なのを残しながら作業を進められたのは良かったなぁ、という感じでしたね。
この issue はまたこういった作業がある時に作業者が参考にして、歴史が作られていくんだよな、という気持ちがありました。
まとめ
これにて、オミカレでの全ての仕事が終わりました。 本当もうお腹いっぱいです。
大きなコストカットで良い貢献ができればよいな・・!
という事で次のエントリは転職or退職エントリになるかと思います。としようかな、長文読んでくださりありがとうございました!!