Advent Calendar 2020 の 3 日目の記事です。
こんにちは、 wind-up-bird です。
トレタではSREチームに所属しており、このブログには初登場です。
今回は、トレタが飲食店向けに提供している顧客台帳・予約台帳サービスのバックエンドを EC2 から ECS へ移行したので、その時のお話を書いてみたいと思います。
内容は、前編と後編に分かれています。
- 前編: 移行前の構成や課題、移行方針を記載しています。
- 後編: 移行後の構成や旧環境との変更点を記載しています。
目次
旧環境と課題
全体構成
トレタのバックエンドは Ruby on Rails を採用しています。これは 1ソース (= 1 Github レポジトリ)で管理されており、API やウェブ予約、非同期処理など、各ロール毎にAWSのリソースが別れています。
また、アプリケーションのホスト先はEC2を採用しており、全体的な構成としては以下のようなイメージです。
詳細
もう少し具体的に見てみます。
1つのサービス(APIやウェブ予約などの各ロール)は、ALB と EC2 で構成されています。
プロセス | 説明 |
---|---|
Nginx | リバースプロキシ、キャッシュなどの用途です。 |
App | アプリケーションのプロセス。Unicorn が起動しています。 |
Flunentd | Appログの収集。example1.com, example2.com サーバへ転送しています。 |
Datadog | Datadog にEC2のメトリクスを転送しています。 |
デプロイ
アプリケーションを EC2 にデプロイするまでの流れは、
ツール | 用途 |
---|---|
Packer | AMI を作成します。 |
Ansible | Packer の Provisioner として利用しています。Ruby の Runtime、Nginx などのMW、各サービス向けの設定、Fluentd や Datadog エージェントをインストールします。 |
Terraform | ALB、Listener、Target Group、Launch Template、 Auto Scaling Group などを管理。AMIを差し替えることで、新しい EC2 を起動することができます。 |
導入当初から、(いくつか変更点はあるものの)おおよそこの流れで開発してきたのですが、運用していくなかでいくつか課題も出てきました。
- 当時のブログ:
課題
1. 開発スピード
サービスの機能追加などに伴い、 Packer + Ansible が担当する部分が多くなっていきました。 結果として、1回の Packer build で 40分かかってしまうようになり、小さな変更でも都度この待ち時間が発生する状況でした。
また、AMIの作成後も Terraform でAMI IDを差し替えて、 Staging および Production 環境で別々にデプロイしていました。
従って、 どんな小さな変更でも
- packer build
- terraform apply (in staging)
- terraform apply (in production)
のようにリリースサイクルをまわす必要がありました。(約1時間の作業...)
2. OSバージョンアップ
トレタではこれまで AMI のベースイメージは Ubuntu を利用していました。 従って、EOLに伴うバージョンアップ作業は今後も定期的に発生し続けることになります。*1
- 前回OSバージョンアップしたときの様子
3. Packer と アプリケーションの依存
前述の通り、 Ruby の Runtime や各種設定ファイルのインストールも Packer 側で実施していたため、例えば、アプリケーションチームが Ruby のバージョンを上げたいような場合は、SREチームに依頼して、そこで作業待ちという状況も発生していました。
4. 起動スピードとキャパシティプランニング
最新のアプリケーションのダウンロードおよびプロセスの起動は、 userdata で実行していたため、EC2 インスタンスの1台の起動に10分弱かかっていました。 このような特性から、突発的なアクセス増を見越して、大きめのサイズのインスタンスを余剰に起動させておく、という対策をとっていました。*2
移行先の検討と移行方針
前述のような課題があり、今年プロジェクト化してアプリケーションチームとSREチームで移行に踏み切りました。
移行先
検討当時(2020年3月頃)、移行先の候補としては、EKS と ECS があったのですが、以下の理由で ECS を選択しました。
- プラットフォームのバージョンアップがない。
- EKS だけでなくECSも将来の選択肢として入れたかった。
- AWSのサービスとの親和性
それぞれ、もう少し詳しく書いてみます。
まず、移行検討の段階でトレタはコンテナオーケストレーションツールとしてEKSをすでに導入済みだったこともあり、自然な流れとしてEKSを移行先として想定していました。 しかし、EKS を選択した場合、3ヶ月に1回または最長でも年に1回のアップグレードが必要になります。 今回移行対象のサービスはトレタの土台を支えるバックエンドシステムということもあり、都度移行時の作業時間やリスクを取るよりはバージョンアップを必要としない ECS の方がよいだろうと判断しました。
また、トレタはこれまでEC2とEKSは利用してきていたものの、ECS利用の実績がまだありませんでした。 従って、このタイミングで自分たち自身でECSや周辺ツールを設計・構築・運用することで、選択肢の幅が広がることを期待したというのもあります。
最後に、AWSとの親和性があります(が、1, 2 と比べてそこまで大きくはないです)。
特に検討段階では、まだ EKS と AWS の各種サービスの連携(特にセキュリティ周り)はまだこれから発展していきそうだなという印象があり、前述のとおり土台となるバックエンドのホスト先としてEKS導入はまだ早いかもしれないと判断して見送りました。*3
- 当時の移行検討資料
方針
移行先が決まったので、次は移行方針です。SREチーム内で協議し、以下のような方針を設けました。
- 移行に伴うシステム停止やメンテナンス時間は設けない。
- 新旧環境を並行稼動させつつ、ユーザ影響を可能な限り小さくする。
- 可能な限りAWSのマネージドのサービスを利用する。
- これまで使っていなかったAWSサービスも積極的に検証し、導入検討する。
今回のように移行対象が ALB + EC2 の場合は、DNSの重みを利用した段階的移行が可能であると考えていたため、無停止を目標に切り替える方針としています。
また、並行稼動にすることで移行時になにか問題があっても、すぐに旧環境にトラフィックを切り戻すことができるためです。
最後に、今回は検証の時間は十分確保できることもあり、(移行先のところでも触れましたが)将来選択できる技術要素を広げておこう!というのも狙いとしてありました。*4
後編へ続く
ということで、ECS移行前の状況や課題などまとめてみました。
後編ではこれを踏まえて、どのように移行していったのか、どのような仕組みにしたか、について書いていきたいと思います。
*1:実際、2018年には Ubuntu 14.04 から 18.04 へ アップグレードしており、systemd 対応や各種MWのバージョンアップ、移行作業など、一筋縄ではいかない場面もありました。
*2:当時ここは改善の余地があったのですが、移行が決まったというのもあり、一旦そのままに。。。
*3: 2020年3月時点。このブログを書いている現在(2020年12月)は Pod への Security Group のアタッチメントや kubernetes サービスアカウントに IAM パーミッションを割り当てる、ということもできるようになりました。EKSも日々進化しているため、将来的にはEKSへの移行も検討するかもしれません。
*4:検証したけど導入は見送った、というものも今後の資産になると考えています。