ECS on EC2からFargateに移行時に考慮した点

## はじめに

去年、チームのサービスをECS on EC2からECS on Fargateに移行しましたので、自分の復習も含めて調べていた資料とポイントを振り返ってみようと思います。

## サービスの構成

規模は比較的小さく、5~6個のコンテナサービスを常時起動と定期バッチ起動しており、他チームと共有しているEC2インスタンス上で稼働する構成(ECS on EC2)を取っています。

## ECS on Fargateについて

Fargateは、AWS上でサーバーレスにコンテナを利用できるサービスです。EC2インスタンスの運用が不要となり、アプリケーションの開発だけに集中できるのが特徴です。Fargateに移行することで得られるメリット、デメリットは以下のようなものがあります。

### ECS on Fargateのメリット

- OSから下の世界はAWSに任すことになるので、運用コストを減らせます
- ECS on EC2に比べて大きなCPUとメモリスペック選ぶことができます
    - 例えば、ECS on EC2では10vCPUまで設定可能ですが、Fargateにすると16vCPUまで上げることができます
    - https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definition_parameters.html
- タスクの組み合わせにより、EC2インスタンスのリソースが余ることがなくなります

### ECS on Fargateのデメリット

- EC2を利用する場合に比べて、同じスペックならFargateの方が利用料金が高くなります
- 起動時に選ばれるCPUが毎回同じではない可能性があり、同じvCPU、メモリでも性能差がある場合があります（いわゆるCPUガチャ）
    - https://blog.father.gedow.net/2021/05/21/aws-ecs-fargate-cpu/
    - https://blog.father.gedow.net/2023/10/02/aws-ecs-fargate-cpu-2023/
- AWSにお任せする分、メンテナンスによる再起動のタイミングなど、OSから下の世界は制御できない部分があります

### Fargateに移行した理由

サービス特性とFargateのメリット、デメリットを考慮した結果、私たちのチームではFargateへの移行を決定しました。理由としては

- Fargateの性能の差分(CPUガチャ)にそこまでに影響されないサービスである
- タスクサイズをよりハイスペック(特にメモリ)にしたい
- 運用にかけられる工数・対応メンバーが少ないため、運用コストをできるだけ抑えたい
- 他チームから私たちのチームへ、こちらから他チームへ影響を少なくしたい
    - 例えば、他チームのリソースでEC2の利用可能リソースがなくなり、サービスが立ち上がらなくなることを避けたい

でした。逆に運用面とコストを考慮した結果、ECS on EC2を選択した例もあるようです。

https://tech.uzabase.com/entry/2022/12/01/175423

## いざ、移行

### 移行前に参考にした資料
まずはAWSドキュメントや先人たちのブログを確認し、Fargate移行時に考慮が必要なところを確認しました。

- ECS での Fargate ⼊⾨
    - https://d1.awsstatic.com/webinars/jp/pdf/services/202108_AWS_Black_Belt_Containers202-ECSFargate.pdf
- ECS on EC2 から ECS on Fargate への移行で考慮した4つのポイント
    - https://link-and-motivation.hatenablog.com/entry/2022/12/26/121837
- ECS EC2からFargateへ移行した理由とメリット
    - [https://pages.awscloud.com/rs/112-TZM-766/images/01_タップル様_資料.pdf](https://pages.awscloud.com/rs/112-TZM-766/images/01_%E3%82%BF%E3%83%83%E3%83%95%E3%82%9A%E3%83%AB%E6%A7%98_%E8%B3%87%E6%96%99.pdf)
- Best practices when migrating from Amazon ECS with Amazon EC2 to AWS Fargate
    - https://www.youtube.com/watch?v=7eZ8VXSEfG8
    - https://pages.awscloud.com/rs/112-TZM-766/images/2023_OTT-OD-0805-MDA_Slide-Deck.pdf

### 移行前に考慮したところ

上記の資料を参考にし、私たちのサービスでは以下を考慮する必要がありました。

#### タスクサイズの定義
FargateではvCPUの数によって割り当てられるメモリの範囲が決まっているので、利用するvCPUとメモリのスペックをドキュメントに従って定義する必要があります。

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definition_parameters.html

#### ECS Execを実行できるようにする

ECS ExecはECSのコンテナの中に接続することができる機能です。
利用のためには
- タスクロールを作成し、ECS Execに適切なアクセス許可設定をする
- ECS サービス、タスクの設定でECS Execを有効(`enable-execute-command`)にする

必要があります。

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-exec.html

私たちのサービスではCI/CDパイプラインでECSサービスのデプロイを自動化しているので、サービスデプロイの際にAWS CLIを利用してECS Execを有効にしています。

#### VPCエンドポイントの追加
プライベートサブネット(NATゲートウェイやNATインスタンス経由でインターネットにアクセスする経路が存在しない)内にサービスリソースがあるので、VPCエンドポイントを追加する必要がありました

https://dev.classmethod.jp/articles/vpc-endpoints-for-ecs-2022/

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/vpc-endpoints.html

#### ネットワークモードをbridgeからawsvpcに変更する
Fargateでのネットワークモードの選択肢がawsvpcモードのみとなるので、現在bridgeモードで利用しているコンテナはawsvpcに変更する必要がありました。
※awsvpcモードの場合、サブネットのIPアドレスを消費することになります。サブネットの使用可能なIPアドレス枠を事前確認することをおすすめします。

#### ALBターゲットグループの修正
ネットワークモードがbridgeモードではターゲットグループのターゲットタイプを「インスタンス」で利用していましたが、「IPアドレス」で新しくターゲットグループを作成する必要がありました。

#### データボリュームの修正
Dockerボリュームを利用していたところが一部あったのですが、Fargateでは利用できないためEFSボリュームに変更しました。


#### 無停止移行の検討
Fargateに切り替えるにはサービスを一度再作成する必要がありますが、可能な限り稼働中のサービスを停止せずにデプロイしたいと思いました。そこで、一時的なサービスを作成し、そのサービスを本来のサービスと同じターゲットグループに登録することで移行作業中でもサービスが継続できるようにしました。

## 移行後に考慮する必要があったと気付いたところ

考慮が漏れていて、移行後に気づいた点もいくつかありました。

### コンテナはUTC時間になる

今まではEC2の設定に従い日本時間で表示されてきたログがFargateに移行したらUTC時間に変わっていました。TZの環境変数を設定するなど別途設定が必要となります。

https://dev.classmethod.jp/articles/ecs-fargate-task-time-zone-jst/

### EventBrigeルール実行時のネットワーク設定

EventBrigeのルールで実行している定期バッチコンテナのネットワークモードをBridgeからawsvpcに変更した場合、ネットワークの設定をルールの設定から行う必要がありました。

### Fargateの自動メンテナンス

Fargateではインフラの管理をAWSに任せることになるので、メンテナンスのための再起動について私たちが制御することほぼできません。しかし、Fargateのメンテナンス(再起動必要)については7日前(デフォルト)にAWS Health経由で案内が来るので、7日間でこちら側で再起動を実施するか、7日後にAWS側のタイミングで再起動を行うかを選ぶことができます。また、通知期間は設定を通じて、14日前に変更することもできます。

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task-maintenance.html

一般的なコンテナのデプロイ時は、既存のタスクがある状態で新しいタスクをデプロイして、デプロイが完了したら新しいタスクに切り替え、既存のタスクを終了するような運用になるかと思います。したがって、メンテナンスで再起動されても 基本的にサービスの継続に問題はないはずです。

私たちのサービスではソフトウェアの仕様上、既存のタスクがいる状態で新しいタスクをデプロイできないサービスがあり、また、タスクを停止してから起動する方式にするとダウンタイムが発生することになり、これも許容できないため、このサービスだけはEC2に残すことになりました。

### サブネットのIP枯渇問題

ネットワークモードがawsvpcの場合はタスクごとにENIが割り当てられ、サブネットのIPアドレスを消費することになります。サブネットに利用可能なIPアドレスが少ない場合、IPアドレスを確保できずタスクが立ち上がらない場合があるので注意が必要です。

## おわりに

Fargateへの移行により、運用時に他サービスへの影響を考慮する負担が減少し、より大きなリソースを割り当てることでサービスのパフォーマンスを向上させることができました。

Fargateへ移行する皆様の参考になれば幸いです。