この記事はfreee 基盤チーム Advent Calendar 2023 の24日目の記事です。
はじめに
はじめまして! kanno と申します。freee SREで、freeeサインのプロダクトSREを担当しておりAWSインフラの改善や運用を主に行っています。初回の投稿で拙い文章になりますが、直近で実施したfreeeサインのAWSリージョンを移行した話を書こうと思います。
背景
元々、freeeサイン(旧ninja-sign)はHeroku上にアプリケーションをデプロイしていましたが、2022年の年末頃にAWSに移行しています。その際、元々のHerokuがus上で稼働していたことが影響して、AWSのバージニアリージョンに移行された状態でした。私がfreeeのサインチームにjoinしたのがこの時で、AWSリージョン移行を担当することになりました。
AWSリージョン移行のモチベーション
AWSリージョン移行を実施するに至った課題感やモチベーションについて記載します。
主に下記の3点があります。
①パフォーマンス改善
freeeサインのユーザーは大部分が日本国内のユーザーですが、通信経路に非効率なところがありました。日本のユーザーがfreeeサインを利用する際には、海底ケーブルを通って北米に通信が到達して応答が戻ってくる状態で、パフォーマンス面で改善の余地がありました。リクエストを投げてから応答が返ってくるまでの時間を事前に計測していましたが、約800msの応答時間が国内のユーザーに毎回かかっていました。これを東京リージョンに移行することで約100msになるので、大体1/8の応答時間になるため体感的にも早くなったと感じる程度の改善が見込まれていました。
移行前: 約800ms
移行後:約100ms
②海外リージョンにデータ保存を懸念しているユーザーの不安解消
契約情報などの重要情報を取り扱う性質上、セキュリティ・データ保護について強く気にされているお客様の中で海外のデータ保管だと導入することができないと言われるお客様もいましたが、今回のAWSリージョン移行によって東京リージョンに移行することで導入を検討されるお客様も出てくると思われます。
③運用時の認知負荷の軽減
freeeサインではAWSアカウントで環境分離を行っていますが、各環境でシステムを動作させているリージョンに差異があることも実運用で課題感がありました。具体的には実際にAWS運用をしたことがある方であればご理解頂けると思いますが、環境(=AWSアカウント)を切り替える際に「この環境は東京で」「この環境はバージニアで」と毎回認知負荷が発生していることになり、予期せぬヒューマンエラーの発生や、確認する手間が作業効率の悪化に繋がるなど、あまり良い状態では無いかと思います。
実施したこと
AWSリージョン移行で実施したことをざっくりとではありますが、以下に箇条書きで記載します。
- 現状の環境の理解・把握
- DesignDoc作成&レビュー
- S3データ移行のスクリプト準備
- 移行先の検証環境構築
- 検証環境移行準備
- 検証環境移行
- 移行先の本番環境構築
- 本番環境移行準備
- 本番環境移行
- 移行元環境の削除
freeeサインのインフラ構成イメージ
構成図は便宜上簡易的に記載していますが、基本的な構成としては下記の通りです。
- ECS Fargateをコンテナ基盤として、その上にアプリケーションをデプロイ
- データベースにはAurora PostgreSQLを使用
- 上記のコンテナ基盤、各インスタンスはマルチAZで冗長化
- 前段のPublic subnetにはALBをデプロイしてバックエンドのECSに負荷分散
- CI/CDパイプラインは下記のサービスで構成
- ALBにWAFをアタッチ
- etc
freeeサインのインフラ構成は、書籍やネット上の記事でよく見かけるようなベーシックな構成をとっています。基本的には全てのAWSリソース、DatadogのモニターやダッシュボードをTerraformで管理しています。
以降、振り返ってリージョン移行のポイントだったと個人的に思うトピックを記載します。
データベースの移行について
freeeサインのデータベースはAurora PostgeSQL互換のRDSを使用しており、クロスリージョンAuroraレプリカはサポートしていません。ですが、Aurora Global Databaseに対応しており、グローバルクラスターを構成して可用性を向上させる以外に、今回のようなAWSリージョンの移行時にも使用することができます。今回はこのAurora Global Databaseを採用しました。Aurora Global Databaseでリージョン移行する場合のメリットを以下に記載します。
- リージョン間でのデータの同期が低遅延でほぼリアルタイムにできるので、移行時にデータの損失やデグレを発生するなどのリスクが解消される
- 切り替え(failover)が簡単にできるので、移行も戻しが発生した際もオペレーション、または手順の準備等が楽になる
- 本番の稼働に影響をことなくGlobal Database化することができ、セカンダリクラスターを事前に並行稼働することができるので、移行当日の作業を削減することができる
- Global Databaseで構築したセカンダリリージョンのクラスターはリーダーインスタンスのみの稼働となるので、誤って移行元環境にデータ書き込みが発生してデータの不整合などが発生する心配がない
以上のメリットのおかげで、データベース移行の考慮事項が少なくすることができたので、振り返ると良い技術選定だったと思います。
CI/CDパイプラインをバージニアと東京で並行稼働させる
リージョン移行の考慮事項として、移行先の東京リージョンに環境を構築する際にCI/CDパイプラインを既存の環境と並行して稼働させるようにするのが、動作確認する際の移行時も効率的に移行する要件だったと認識しています。これを実現するために構築を進めたのですがやってみると意外と大変でした。
(ここの話は、TerraformやECS、ecspressoのエコシステムの理解が前提になりますので、読み飛ばして頂いても大丈夫です。)
ちょっと話がややこしくなりますが、整理すると下記のような感じです。
- 移行前はecspresso.ymlのtfstateファイルのパスや、task_definitionやservice_definitionなどのファイル内でリソースARNをハードコーディングしていた
- 上記、同一のファイルを参照しつつも両リージョンでCI/CDパイプラインを稼働させるのに、ハードコーディング箇所を変数化してGithub Hub Actionsのワークフロー(このファイルは各リージョン毎に作成)から値を上記のファイルに渡すように変更する
- tfstateファイルはS3バケットに格納しており、そのリージョンは東京リージョン
- 上記のGithub Hub Actionsのワークフローファイルでリージョンの値(us-east-1/ap-northeast-1)を設定してecspresso.ymlに渡している
- ecspressoはv1を使用している
- AWSリソース毎にtfファイルのディレクトリを分けて作成していたので、イコールtfstateファイルもAWSリソース毎に分かれている
- そのため、複数のtfstateファイルを参照できるecspresso v2へのバージョンアップを想定していた
- ハードコーディング(AWSリソースARNベタがき)から変数に変えたことで、ecspresso.ymlで定義しているtfstateファイルからtask_definitionやservice_definitionのファイルでAWSリソースを参照する形に変更する必要があった
- そのため、ecspresso v1では複数のtfstateファイルを参照できないので、ecspresso v2にバージョンを上げようと試みた
- 結果、下記の通りecspresso v2に上げることができなかった
- 理由はecspresso v2に上げるとaws sdk v2に上がり、リージョン情報の取り扱いが代わり、tfstateファイルを格納しているバケットとecsリソースが同じリージョン前提の仕様*1になった
- この仕様の変化は上記の要件を満たして、バージニアと東京リージョンで並行稼働させたい場合において、クリアできなかった
- なので、tfstateファイルを複数ファイル参照することができないecspresso v1を使用してリージョン移行を実施する必要があった
- しかし、AWSリソース毎にディレクトリを分けている(=tfstateファイルを分けている)ので、これを1つにまとめる必要性が出てきた
といった感じで、慣れていないtfstateファイルの取り扱いをする作業に直面しましたが、結果的には問題なくtfstateファイルの統合は出来て、CI/CDパイプラインの並行稼働状態も無事実現できました。
S3データ移行
(この作業は同じチームのfujiya3にやり切って頂きました。) S3データをリージョン間を跨いで移行する必要があります。基本的にはS3のレプリケーション機能を使用してデータ移行を行いました。しかし、アプリケーションで使用しているデータの一部(一部といっても数百万ファイルある)は、クライアントサイドで暗号化を実施しており、その鍵はリージョンを跨いで使用することができない制限があることから既存の鍵で復号化してから、新しい鍵で暗号化して移行先のS3バケットにアップロードする必要があります。言うのは簡単ですが、実際やると考慮事項も多く大変な作業だったかと思います。具体的には、移行したファイルに更新が入ったら再度移行対象にする必要があったり、並列に実行する際の本番RDSに与える負荷を考慮したりなどあったかと思います。結果的にはトラブルも無く完璧に実施していただきました。
リージョン移行を実施した感想
freeeサインにjoin後の4ヶ月目に本プロジェクトが開始したわけですが、今その時のドキュメントやGithub issueを見ると解像度が低く手探り感が感じ取れます。事前に環境をコードリーディング的に眺めてはいましたが、実際に作業に入ると環境や技術の理解不足を痛感させられました。また、QA準備の際に動作確認をするタイミングになってfreeeサインに存在を知った機能があったりと、実践の中で成長することが多くあったかなと思います。
おわりに
AWSリージョン移行後、上記の「①パフォーマンス改善」でも記載しましたがパフォーマンスが改善されたことによって、freeeサインを操作してみて、体感でも速くなったと社内の声があったり、 freeeサインのAPIの速度が数倍速くなっているがRate Limitの改定はしないんですかと、CSさん経由で嬉しい問い合わせがあったりと、このような反応があると素直に嬉しいものです。 長丁場でしたが、多くの人に協力して頂けたことで最後まで無事にやり切ることができました。年末にキリがよく移行作業を終えることができ安心して年が越せそうな気持ちではありますが、次に切り替えて行きたいと思います。
最後まで読んでくださり、ありがとうございました!
クリスマスの明日は、SRE 統制チームの Yさんとoracleさんの共同執筆の記事となります。
是非、ご期待頂けたらと思います!
*1:後日、カヤックのfujiwara sanに改修頂きました。