AWS ECS(Fargate)+ELB構成を構築する手引き

![fargatewithalb.png.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/7c7bb33f-ad05-2e66-4270-5f6cab4a9823.jpeg)

#はじめに
AWSのECS（Fargate起動タイプ）で立ち上げたコンテナと、ロードバランサ（ALBまたはNLB）経由で通信させる方法の備忘録です。
まっさらな状態から、ALBとFargate上で起動しているコンテナを結合するとき、つまづいたことが多かったので、大まかな流れをまとめておこうと思った次第です。
コンテナが管理・運用の工数削減に有効なため、広がっていますが、Fargateがなかったころは、コンテナイメージの管理とコンテナが起動しているホストマシンの管理という二重管理が起きていました。Fargateを使うことで、ホストマシン管理をAWS側にオフロードすることができます。
実際のユースケースとしては、ALBと組み合わせて利用することが多いかと思いますので、その構築例を以下に示します。

#目次

以下の流れで作業します。

1. タスク定義の作成
2. ターゲットグループの作成
3. ロードバランサの作成
4. クラスタ（Fargate）の作成
5. サービスの作成

#タスク定義の作成
タスク定義とは、システムレベルでのアプリケーションの設計図に相当するものです。
以下のようなものを定義します。

- 使用するコンテナイメージ
- 公開するコンテナのポート
- 外部から挿入する環境変数
- コンテナヘルスチェック
- 割り当てるCPU・メモリ量
- ログの出力先
- 追加でマウントするボリューム

など。設定項目がたくさんあるので、最初は戸惑いますが、最低限必要なことは、コンテナイメージ、公開するポート、割り当てるCPU・メモリ量の設定です。最初から完璧なものを作ろうとせず、あとから見直して調整していくのがよいでしょう。

Fargate起動タイプは、awsvpcネットワークモードしか選択できません。
タスク実行IAMロールでは、CloudWatchにログを出力する、ECRと通信するなどの目的で、ecsTaskExecutionRoleが必要です（逆にいえば、CloudWatchにログを出さない、かつ、DockerHubのパブリックリポジトリからDockerイメージを落としてくるような場合には、なくてもOKです）。
また、余談になりますが、AWS System Managerのパラメタストアを使って、セキュアに環境変数をコンテナに注入する場合には、SystemManagerをECSのタスクが使用できるようにインラインポリシーをecsTaskExecutionRoleに追加する必要があります（　https://aws.amazon.com/jp/premiumsupport/knowledge-center/ecs-data-security-container-task/ ）。
タスクサイズで、適当なCPU,メモリを選択します。
そして、コンテナを追加します。今回は、例として、DockerHubのパブリックなNginxイメージを使用します。
80を外部に公開するポートとして設定します。
いろいろ設定項目ありますが、必要になったら追加していけばよいでしょう。
![addcontainer.png.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/0274b384-e822-1ea6-4487-95a6812c792c.jpeg)


後ろのほうに、サービス統合、プロキシ設定、ログルータ設定がありますが、とりあえず動かすだけなら、設定は不要です。

![taskdefinition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/f6f8d753-ae6f-a2ea-0e6a-79e932b5cbca.png)

#ターゲットグループの作成

ターゲットグループでは、ターゲットタイプにIPを指定します。
![targetgroup.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/2701b90b-e415-d51b-c1df-bf46f3dcbae9.jpeg)

また、ここでヘルスチェックを定義します。
また、必要であれば、StickinessをEnableにすることで、クッキーパーシステンス（Cookie persistence）を有効にすることができます。これにより、Cookie情報が同じ場合、同じコンテナへ着弾させることができます。
ちなみに、送信元IPアドレスによって振り分けたい場合は、こちらを参照↓のこと。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/elb-route-requests-with-source-ip-alb/

あとで、サービスの作成するとき、あらかじめ作成しておいたターゲットグループを指定することで、ECS側で、立ち上げるタスクに割り当てられるIPアドレスを、自動的にターゲットグループに登録してくれます。なので、ターゲットグループを作る際のRegisterTargetのページでは、何も登録せず、Create Target Groupを押します。

#ロードバランサの作成

次に、ロードバランサを作成します。ここでは、ALBを使用します。
なお、NLBを使うこともできます。CLBを使うことも可能なようです。
ルーティング設定にて、作成しておいたターゲットグループを選択します。
![alb-targetgroup.png.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/ae7a2895-ae2e-8677-eaa4-5a53906e8749.jpeg)
先ほども述べましたが、IPアドレスの登録は、ECS側でやってくれるので、ここでは登録しません。
余談ですが、複数のロードバランサを、ひとつのサービスに紐づけることができます。
ただし、その場合は、ALBまたはNLBのみサポート、サービスの更新方式はローリングアップデートのみサポートです。
複数のターゲットグループを登録するAWS公式ドキュメント↓
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/register-multiple-targetgroups.html

#クラスタ（Fargate）の作成

ここは非常に簡単です。
クラスタの作成を選択し、Fargate起動タイプを選ぶのみです。
名前を決めるだけです。VPCの作成は必要に応じてします。ContainerInsightsは、真面目に運用する場合、有効にしたほうが良いでしょう。

#サービスの作成

最後に、サービスを作成します。
以下の項目が最低限必要です。

- どのVPC、サブネットに配置するのか
- タスクに適用するセキュリティグループ
- どのロードバランサに紐づけるのか
- ロードバランサに紐づけるコンテナはどれか

![service1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/c60c6398-fd86-1a9a-03e8-78a2164afe5d.png)

ロードバランシングのところで、これまで設定してきたロードバランサ、ターゲットグループを選びます。ロードバランス用のコンテナは、今回の場合、Nginxを選ぶことになります。
![service2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/45045d91-06d2-89d9-904a-8e01cfb52ac7.png)

#アクセス確認

ALBのAレコードをブラウザに打ち込んでやると、NginxのWelcomeページに飛ばされるはずです。
![accesscheck.png.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580420/d7f98d3e-32d4-2f1f-4164-d11d44c6eb4d.jpeg)

#CleanUp
タスクを停止し、サービス、クラスタを削除します。
タスク定義を登録解除しておきます。
次に、ロードバランサ、ターゲットグループの順で削除します。
最後にセキュリティグループ、CloudWatchのロググループを削除します。

#おわりに
よくあるユースケースとして、ALB＋Fargateの構成をまっさらな状態から作成してみました。あらかじめターゲットグループを用意しておいて、次にロードバランサを用意して、といった流れに最初戸惑いやすいかと思います。