AWS ECS モノリシックアプリケーションをマイクロサービスに分割するチュートリアルをやってみた

# 初めに

以下のチュートリアルをやってみました。初めはマイクロサービスについて勉強したかったのでこのチュートリアルをやってみたのですが、ALB についての勉強にもなりました。具体的には ALB のパスベースルーティングを初めて使い、非常に勉強になりました。

https://aws.amazon.com/jp/getting-started/hands-on/break-monolith-app-microservices-ecs-docker-ec2/

なお、このチュートリアルでは EC2 タイプを使っていますが、この記事では Fargate でチュートリアルを検証しています。また、チュートリアルでは CloudFormation を使っていますが、この記事では簡略化のため VPC などはデフォルトのリソースを使い、ALB は手動で作成しています。

# マイクロサービスが重要な理由

マイクロサービスのメリットについて簡単に確認します。

- モノリシックアーキテクチャ
  - スケーリングが困難
  - アプリケーションのコードベースが拡大するにつれ、更新と維持が複雑化する
  - 新しい機能、言語、フレームワーク、テクノロジーの導入が難しい
- マイクロサービス
  - さまざまなフレームワークやプログラミング言語を使用して作成することができる
  - マイクロサービスは、単一のサービスとして、またはサービスのグループとして個別にデプロイできる

# モノリスのコンテナ化

このチュートリアルに使用するリポジトリをクローンします。

```
git clone https://github.com/awslabs/amazon-ecs-nodejs-microservices
```

ECR に api という名前のリポジトリを作成し、以下のようにモノリスアプリケーションの Dockerfile のあるディレクトリに移動し、ビルドします。

```
cd ~/amazon-ecs-nodejs-microservices/2-containerized/services/api
docker build -t api .
```

ECR にログインし、タグ付け・プッシュを行います。

```
$(aws ecr get-login --no-include-email --region ap-northeast-1)
docker tag api:latest 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/api:v1
docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/api:v1
```

# モノリスのデプロイ

以下の手順に従い ALB と ターゲットグループを作成し、モノリスをデプロイします。

https://qiita.com/quryu/items/532fe4c22bfc790a134c

/api/users 、/api/threads、/api/posts にアクセスし、適切なレスポンスが返ってくることを確認します。

# モノリスの分割

以下のように機能ごとにマイクロサービスに分割し、それぞれのイメージをビルド・プッシュします。~/amazon-ecs-nodejs-microservices/3-microservices/services にはすでに分割済みのソースコードや Dockerfile が用意されています。

```
cd ~/amazon-ecs-nodejs-microservices/3-microservices/services
docker build -t posts ./posts
docker build -t users ./users
docker build -t threads ./threads
docker tag users:latest 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/users:v1
docker tag posts:latest 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/posts:v1
docker tag threads:latest 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/threads:v1
docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/users:v2
docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/posts:v2
docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/threads:v2
```

# マイクロサービスのデプロイ

users、threads、posts 用にタスク定義を作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/dbeb7191-80b3-8526-7e2e-97e54e336271.png)

ELB はモノリスアプリケーションで使用したものを利用します。ターゲットグループごとにリスナールールを作成し、リクエスト URL のパスによってルーティングを行うことができます。

users、threads、posts 用に 3 つのターゲットグループを作成します。ターゲットタイプを「IP」にすることを除いて、デフォルトの設定で作成します。

以下のようにリスナールールを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/242e767a-1882-5a66-368d-63340b1da3ab.png)

サービスを作成します。作成後、以下のようにモノリスアプリケーションとマイクロサービスアプリケーションが両方デプロイされた状態ですが、上記のリスナールールにより、リクエストはすべてモノリスアプリケーションが処理するようになっています。これはモノリスアプリケーションからマイクロサービスアプリケーションに切り替える時のダウンタイムを 0 にするためです。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/e3023733-7e95-057a-f5b0-85c549413f3b.png)

以下のようにトラフィックの切り替えを行います。これ以降、モノリスアプリケーションにリクエストが到達することはありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/7dfe48fa-07cb-b31d-c830-391a1e79cfe0.png)

最後に api サービスのタスクの必要数を 0 にし、マイクロサービスアプリケーションに移行が完了します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/1a04836a-fc2c-5304-8a32-03e31946c93e.png)

# 参考記事

https://aws.amazon.com/jp/getting-started/hands-on/break-monolith-app-microservices-ecs-docker-ec2/

https://aws.amazon.com/jp/premiumsupport/knowledge-center/elb-achieve-path-based-routing-alb/