はじめまして。
サーバーエンジニアの下川です。
弊社の 子育て家族アプリFamm は先日、データベースを Amazon RDS for MySQL から Amazon Aurora へと移行しました。
こちらではその手順やポイントを紹介したいと思います。
経緯
Fammではリリース当初からMySQL5.5を使用していました。
常に新しい機能を提供していくサービスですので、テーブルへのカラム追加等、テーブル定義の変更は避けられません。また、ダウンタイム無しでの運用を重視しており、MySQL5.6のオンラインDDL機能はFammにはとても魅力的でした。
今回、上記の通りMySQL5.6へアップグレード検討をしている際、Auroraの以下の点に惹かれ、同時にAuroraへの移行に踏み切りました。
- ストレージのシームレスな拡張
- SSDベースのディスクで10GBから64TBまでダウンタイム無しで自動で拡張される
- 99.99%の可用性
- 3AZに6つのコピーデータを作成、2つのディスクが利用不能でも読み書き可能。3つのディスクが利用不能の場合読み込みのみ可能。
- 既存のRDSを簡単に移行できること。
- 数クリックで移行が可能。
- 5倍の処理性能
前準備
現在の構成
まずは、現行のデータベース周りの構成です。
アプリケーションからの書き込みと、読込専用レプリカによる負荷分散として、Read Replicaを複数台用意しています。
また、分析や運用作業のための読込専用レプリカが1台あります。
これらは全てEC2-Classic内に配置されています。
MySQL5.6へのアップグレード
Auroraに移行できるのはMySQL5.6からとなりますので、まずはMySQL5.6へのアップグレードをします。
MySQL5.6へのアップグレードはほぼダウンタイム無しで可能となります。
MySQL5.6にアップグレードするRead Replicaを作成し、コンソールから作成したRead ReplicaのDBエンジンのバージョン変更します。MySQLのバージョンがマスターがMySQL5.5、Read ReplicaのみMySQL5.6という状態になりますが、レプリケーションは正常に行われます。ここまでの作業はサービス運用中でも安全に行う事ができます。
なお、MySQL5.6へのアップグレード作業のみであれば、このDBインスタンスをマスター昇格するだけで完了です。
Auroraへの移行
今回はスナップショットを取得して移行する方法を選択しました。
これを選択した理由は、コンソールを使って簡単にできそうという理由もありますが、移行元マスターのユーザにスレーブ読み取り権限が付与されていなかった事が大きいです。
他社の移行計画を拝見しますと、移行元マスターからAuroraのWriterにレプリケーションさせて、ダウンタイムをほぼゼロで移行させている文献がありますが、Fammの移行元インスタンスはMySQL5.5のため、マスターユーザにREPLICATION SLAVE権限が付与されておらず、RDSの管理外のレプリケーションを貼ることができないためです。
※RDSのマスターユーザのデフォルト権限は以下に記載があります。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/CHAP_MySQL.html
最新のスナップショットの移行
ここからの作業はサービスをメンテナンスにする必要があります。
移行元インスタンスのRead_onlyをTrueにしてから、スナップショットの取得を行います。
次に、「最新のスナップショットの移行」を選択し、Aurora Writerを作成します。
Auroraレプリカの作成
Aurora WriteからAuroraレプリカを作成します。
ここまででデータベース単体の移行は完了です。
クラシックリンクの設定
前述でもある通り、FammのインスタンスはEC2-Classicに配置されています。
AuroraはVPC内に配置されるため、このままではEC2インスタンスから接続することはできません。
EC2インスタンス自体をVPCに移行するという選択肢もありますが、今回はEC2-Classicインスタンスは現状のままとし、VPC内のAuroraにクラシックリンクを利用して接続する方法を選択しました。
クラシックリンクは以下のとおり、個々のインスタンスからVPC内のセキュリティグループに向けてリンクを貼ります。
アプリケーションのデータベース接続先を変更
データベース接続先を変更します。
単純にアプリケーションが参照するエンドポイントを置き換えて終了ですが、ここで「Aurora DBクラスター」という新しい概念を踏まえて検討する必要があります。
クラスターエンドポイント
クラスターエンドポイントは DB クラスターのプライマリインスタンスに接続します。
以下の図の例では、プライマリインスタンスがfamm001.xxx.comを指しており、読み取りと書き込みの両方のオペレーションを実行できます。
クラスターエンドポイントとは別に、個別のインスタンスに接続できるエンドポイントもあります。
こちらについてはRDS for MySQLと変更はありません。
以下の図のように、famm001.xxx.comに障害が発生した場合、フェイルオーバーが発生し、famm002.xxx.comがプライマリインスタンスに昇格します。
この際、クラスターエンドポイントであるfamm.cluster.xxx.comを変更することなく読み取りと書き込みオペレーションが実行できます。
なお、RDS for MySQLのMulti-Azでもフェイルオーバーが発生するとマスターのエンドポイントに変更なく読み取り、書き込みオペレーションが可能でしたが、Auroraではこのフェイルオーバーにかかる時間が1分程度と、Muti-Azの時の10分と比較して格段に短くなっています。
また、Multi-Azの際はインスタンスの料金が倍かかっていましたが、Auroraの場合セカンダリインスタンスも読み取り専用として使用できるので、コスト面でも利点があります。
読み取りの負荷分散
Fammでは読み取りの負荷分散として、書き込みの接続はMasterに、読み込みの接続はRead Replicaに向けていました。
同じ考えで書き込み接続はDBクラスターエンドポイントを設定し、読み取り接続をReaderへのインスタンスエンドポイントを設定することは可能です。
しかし、プライマリインスタンスに障害が起こった場合、Readerがプライマリインスタンスに昇格し、書き込みも読み取り専用の接続も1インスタンスに集中する結果となってしまい、せっかくフェイルオーバーをしても高負荷な状態となってしまうことが懸念されます。
以下の図では、すべての接続が1インスタンスに集中した例を示しています。
また、FammではReaderの1台を分析や運用系で使用しています。
運用系では高負荷なSQLが走行する場合もあります。
運用系で気軽に走行したSQLが実はサービスに影響を及ぼしたなど、考えたくはありません。
例えばフェイルオーバーしないインスタンスを設定できれば簡単に解決できますが、現状そのような設定はありません。
以下のページで上記課題についての記載があります。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Aurora.BestPractices.html#Aurora.BestPractices.ReadScaling
現状での解決方法は、サービスとは別のDBクラスターを新規で作成し、手動でレプリケーションを設定するというものになりますが、こちらはまだ問題があるような記述もあり、サービスで使用するのはちょっと怖いかな、と考えています。
本課題についてはアプリケーション側でも解決のしようはありますが、今までMulti-Azで構築してきたシステムが何も考えずにAuroraに移行できるような仕組みが追加されることを祈ります。
まとめ
Auroraに移行して2週間程経ちますが、現状全く問題なく稼働しています。
苦労することも多く、個人的な反省点も多いですが、なんとか移行できてよかった・・・。
人としても少し成長できた気がしてます。
昔はシステム移行って本当に大変だったのに、今やコンソールぽちぽちでここまで出来るようになったのかと、クラウドってすごい。
あとは真面目なこと書くと、MySQL5.6の新機能もまだまだ検証できてないので、その辺も今後触っていきたいな、とか、EC2インスタンスもVPCに?とかそんなことも考えたりしています。
直近としてはPairyという弊社のもう一つのサービスもAuroraに移行したい・・・!
ユーザ数増えることで考える事が増えるってサーバーエンジニアとしての醍醐味ですよね。
スケールできるサービスの土台作りを今後も構築していきたいと考えています!
================
子育て家族アプリFamm、カップル専用アプリPairyを運営する Timers inc. では、現在エンジニアを積極採用中!急成長中のサービスの技術の話を少しでも聞いてみたい方、スタートアップで働きたい方など、是非お気軽にご連絡ください!
採用HP : http://timers-inc.com/engineerings