AWS ECS on Fargateチュートリアル Level 3

## はじめに
AWSのFargateを使ってみたいけど、何から始めていいかわからない...という方へ。
一緒に超シンプルな構成を試して「これがFargateか😃」を体感してみましょう！の第３弾です。
ネットワークもAWSも初学の人が書いているので、どうか温かい目で読んでくださいね。

ちなみに第１弾と第２弾はこちらです。

https://qiita.com/yuzu_ponz007/items/a07cc611871c1e1cfd10

https://qiita.com/yuzu_ponz007/items/d96bb41df30c89311f2f


<br>

**今回はプライベートサブネットにFargateを置いてALBと接続します**
![インフラ図練習-ページ4 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/cccb61ed-af3f-4c59-be83-dbab6861588f.jpeg)


## まずは用語をざっくり説明
### VPC（Virtual Private Cloud) :
論理的に隔離されたプライベートスペースです。
「進撃の巨人」で例えると、冒頭で巨人に壁を破壊されたシガンシナ区です。
このエリアの中にFargate（エレンの家）やALB（交通整理の人）を置きます。

### ECR（Elastic Container Registry）:
Dockerイメージを安全に保存・共有するためのツールです。
想像ですが、シガンシナ区の外にある秘密の食糧庫みたいなものですかね。

### ECS（Elastic Container Service）：
複数のコンテナを効率的に管理、運用できるツールです。
今回の役割としては、ECRのDockerイメージをFargateの中で起動させます。
例えると、村の外にある食糧庫から冷凍肉まんを取ってくる人です。


### Fargate：
コンテナに対しサーバレスで実行できる環境を提供してくれるサービスです。
ECRがとってきたDockerイメージをコンテナとして起動します。
例えるなら、エレンの家の電子レンジです。
食糧庫から取ってきた冷凍肉まんをホカホカに温めます。


### ALB（Application Load Balancer）:
ALBには「交通整理」と「安全確認」の２つの役割があります。

１つ目の「交通整理」について。
ALBは、２つのAZ(アベイラビリティーゾーン)をまたぐ場所にあり、
**ユーザーからのアクセスをどちらかのAZにバランス良く振り分けます。**
今回は一方のAZにのみ、Fargateを置くので振り分けはありません。
</br>
２つ目の「安全確認」について。
**アクセス先が安全かを確認するヘルスチェックを、60秒おきに行います。**

これでエレンは渋滞に巻き込まれることなく安全に家まで辿りつけるのですね。

### NAT（Network Address Translation）：
FargateのIPアドレスをグローバルIPアドレスに変換します。

エレンの家は、村人の間で「エレンんち」と呼ばれているけど
公的には「シガンシナ区２丁目９番地」と呼ばれている感じですね、多分。


ちなみに、NATはIPアドレスとグローバルIPアドレスを１対１に変換しますが、
NAPT（Network Address Port Translation）は複数のIPアドレスを１つのグローバルIPアドレスに変換します。
会社としてのグローバルIPアドレスは１つ、会社内のネットワークにあるPCのIPアドレスは複数ある、という状態です。
グローバルIPアドレスからIPアドレスに変換する際はポートを見て識別します。

:::note info
**NATとNAPT**
IPアドレス⇆グローバルIPアドレス
NATは１対１、NAPTは多対１で、IPアドレス＋ポート番号で識別する。
:::

## やってみよう
以下の手順で進めます
    - Fargateに入るためのIAMロールを作成
    - ECRにリポジトリを作成し、イメージをプッシュ
    - VPCを作成
    - ECSにタスク定義を作成
    - ECSにクラスター、サービスを作成
    - ターゲットグループを作成
    - ロードバランサ（ALB）を作成
    - Fargateにアクセスしてみよう
    - Fargateの中に入ってみよう
    
## Fargateに入るためのIAMロールを作成
CloudShellで下記コマンドを実行します。
```ruby:
aws iam create-role \
  --role-name ecsTaskRole \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "Service": "ecs-tasks.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
      }
    ]
  }'

```
引用：https://qiita.com/free-honda/items/53884ea680031be839b9

<br></br>

ecsTaskExecutionRoleとecsTaskRoleがあるか確認してください

![スクリーンショット 2025-04-06 14.53.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/5be96c10-550e-441b-ae46-8f811c329fd0.png)

ecsTaskExecutionRoleがない場合は以下の「ロールを作成」を参考に作成してみてください

https://qiita.com/yuzu_ponz007/items/d96bb41df30c89311f2f#1%E3%83%AD%E3%83%BC%E3%83%AB%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B

## ECRにリポジトリを作成し、イメージをプッシュ
### 1.ECRにリポジトリを作成
Django用とNginx用に２つのリポジトリを作成します。
リポジトリ名はそれぞれ「reverse-proxy-django-app」と「reverse-proxy-django-nginx」にしてください。後で作成するタスク定義に合わせるためです。

![スクリーンショット 2025-04-05 8.20.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/6de254f2-3ec5-4a61-9740-2a72f7568bb8.png)

### 2.CloudWatchにロググループを作成する

どの画面でも構いませんので、画面左下にあるCloudShellを開いてください。

![スクリーンショット 2025-04-05 8.41.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/2fa751d8-8240-4b61-855e-7ad28c6eb450.png)

CloudShellで下記コマンドを実行します
```ruby:CloudWatch にロググループが存在するか確認
aws logs describe-log-groups --query "logGroups[*].logGroupName"
```
```ruby:ロググループが存在しない場合は下記コマンドで作成
aws logs create-log-group --log-group-name "/aws/ecs/reverse-proxy-cluster"
```

### 3.GitHubから簡易アプリをクローンする
以下のGitHubリポジトリを使用させていただきます

https://github.com/free-honda/reverse-proxy-django-prd

CloudShellで下記コマンドを実行します

```ruby:GitHubからリポジトリをクローンする
git clone https://github.com/free-honda/reverse-proxy-django-prd.git
```

### 4.リポジトリにDockerイメージをプッシュする
ECS → リポジトリ → 「reverse-proxy-django-app」をクリック → CloudShellを開き、CloudShell内でdjango_appディレクトリに移動してください

![スクリーンショット 2025-04-05 8.44.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/0974c347-30d6-434a-a8d7-42bf943af93d.png)

コンソール画面の「プッシュコマンドを表示」をクリックし、４つのコマンドを実行します

![スクリーンショット 2025-04-05 8.44.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/914db230-9c00-4b0f-bb58-a3c5c434db25.png)

![スクリーンショット 2025-04-05 15.30.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/e6c14026-8c6a-4859-bc20-fa4a9e07c164.png)

更新ボタンを押してみてください
「reverse-proxy-django-app」リポジトリにイメージをプッシュできました


![スクリーンショット 2025-04-05 8.55.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/c9db5c30-3a03-41bb-a8a0-1913ae3a5e91.png)


<br>
次は「reverse-proxy-django-nginx」リポジトリにイメージをプッシュします

リポジトリ → 「reverse-proxy-django-nginx」をクリック → CloudShellを開き、CloudShell内でreverse-proxy-django-prdディレクトリに移動

![スクリーンショット 2025-04-05 8.52.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/f89c8568-9ecf-47a0-b38a-744344f5ce9a.png)

:::note warn
再度「プッシュコマンドを表示」のコマンドを実行しますが、
2つ目のコマンドの代わりに下記を実行してください
```ruby:Nginx のビルド
docker build -t reverse-proxy-django-nginx -f nginx.Dockerfile .
```
:::

「reverse-proxy-django-nginx」リポジトリにイメージをプッシュできました

![スクリーンショット 2025-04-05 8.54.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/1877ead8-eb22-4795-87ca-cd241b4f403d.png)


## VPCを作成する
VPC → VPCを作成

![スクリーンショット 2025-04-06 10.31.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/8155eb19-a2c3-4232-8f3d-3a1a112c53c9.png)

![スクリーンショット 2025-04-06 11.14.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/9c207b42-50b8-496d-bd3e-d7aabd6f1d0c.png)

![スクリーンショット 2025-04-06 11.14.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/fcf55f91-9ec1-4f04-9a5d-bcdbf65d6e0d.png)

![スクリーンショット 2025-04-06 11.14.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/05203278-c766-41e3-8a8c-86cc7fdc96f0.png)

VPCが作成完了するまで、画面遷移やリロードしないでくださいね
![スクリーンショット 2025-04-06 11.17.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/4e8dc507-8fec-49ca-980a-8c0eae5228a6.png)


## ECSにタスク定義を作成

ECS → タスク定義
![スクリーンショット 2025-04-06 11.28.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/47bb64ae-8cc7-4254-90e3-c9f8dc2a87d7.png)

下記のJSONを使います。[xxx]をご自身のAWSアカウントIDに置き換えてください。
```ruby
{
  "family": "reverse-proxy-task",
  "taskRoleArn": "arn:aws:iam::xxx:role/ecsTaskRole",
  "executionRoleArn": "arn:aws:iam::xxx:role/ecsTaskExecutionRole",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "1024",
  "memory": "2048",
  "containerDefinitions": [
      {
          "name": "django",
          "image": "xxx.dkr.ecr.ap-northeast-1.amazonaws.com/reverse-proxy-django-app",
          "cpu": 512,
          "memory": 1024,
          "portMappings": [
              {
                  "containerPort": 8000,
                  "protocol": "tcp"
              }
          ],
          "essential": true,
          "environment": [
              {
                  "name": "DJANGO_SETTINGS_MODULE",
                  "value": "mysite.settings"
              },
              {
                  "name": "DJANGO_SECRET_KEY",
                  "value": "your-secret-key"
              },
              {
                  "name": "STATIC_ROOT",
                  "value": "/app/staticfiles"
              }
          ],
          "logConfiguration": {
              "logDriver": "awslogs",
              "options": {
                  "awslogs-group": "/aws/ecs/reverse-proxy-cluster",
                  "awslogs-region": "ap-northeast-1",
                  "awslogs-stream-prefix": "ecs"
              }
          }
      },
      {
          "name": "nginx",
          "image": "xxx.dkr.ecr.ap-northeast-1.amazonaws.com/reverse-proxy-django-nginx",
          "cpu": 512,
          "memory": 1024,
          "portMappings": [
              {
                  "containerPort": 80,
                  "protocol": "tcp"
              }
          ],
          "essential": true,
          "logConfiguration": {
              "logDriver": "awslogs",
              "options": {
                  "awslogs-group": "/aws/ecs/reverse-proxy-cluster",
                  "awslogs-region": "ap-northeast-1",
                  "awslogs-stream-prefix": "ecs"
              }
          }
      }
  ]
}

```

![スクリーンショット 2025-04-06 11.30.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/48d5fd4f-4ea2-4150-b49a-7823a0041317.png)



## ECSにクラスター、サービスを作成

ECS → クラスター → クラスターを作成をクリック　クラスター名を付けて作成します
![スクリーンショット 2025-04-06 11.26.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/fe51f89b-5d3f-4c30-a310-938df9843763.png)

クラスターができました
![スクリーンショット 2025-04-06 11.26.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/5152fdb9-9d5f-4788-b739-7669d4540807.png)

サービスを作成します
![スクリーンショット 2025-04-06 11.27.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/3ce4b8d0-9744-4940-9c61-d279451236c4.png)

![スクリーンショット 2025-04-06 11.34.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/cebd8a3c-8d78-43fc-b8e9-528dbeb05cdd.png)

![スクリーンショット 2025-04-06 11.34.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/3a2a4cbe-cf3e-40ec-abf0-1a07d41e2d46.png)



![スクリーンショット 2025-04-06 11.34.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/da7edb5a-1c7d-4eb0-94c1-70e0cd96d4b4.png)

サービスができました
![スクリーンショット 2025-04-06 11.36.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/e97de057-5c50-4486-a95c-96bac06999cd.png)

タスクが実行しているか確認してください
![スクリーンショット 2025-04-06 11.36.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/95b497cb-ba53-4f40-9df5-25ab1d3f670e.png)

「タスク」タブにあるFargateのIPアドレスをコピーします
![スクリーンショット 2025-04-06 16.50.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/19f95829-a663-4cb0-b48a-1efdb398f893.png)



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

![スクリーンショット 2025-04-06 12.57.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/9c54c2c1-0996-4eb1-9584-dcaf218afc9f.png)

![スクリーンショット 2025-04-06 12.58.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/f2f6e23c-97d2-4ae3-8839-2f086aca2beb.png)


![スクリーンショット 2025-04-06 12.58.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/661bbb08-afa1-466e-ad08-f9c41e4afc2b.png)

先ほどコピーしたFargateのIPアドレスを貼り付けます
![スクリーンショット 2025-04-06 13.00.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/46278358-0eed-47da-896f-b1da85a0f34f.png)

![スクリーンショット 2025-04-06 13.00.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/50b367c9-e3b9-473d-a5c1-702e4d029ac9.png)


## ロードバランサ（ALB）を作成

![スクリーンショット 2025-04-06 13.01.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/19b10599-c2c9-4834-90fb-7c2444e34157.png)

![スクリーンショット 2025-04-06 13.01.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/0afeeaa3-3a2e-4e9c-aae0-5bfe5e9ddaef.png)

![スクリーンショット 2025-04-06 13.03.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/0957ecf5-734b-4831-b90c-0c5c8337840e.png)


 「新しいセキュリティグループを作成」をクリック
![スクリーンショット 2025-04-06 13.06.46のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/8b59baba-229e-4a89-a9c1-db931ad3db94.png)

![スクリーンショット 2025-04-06 17.06.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/fca7ebb4-7cdb-42df-85c0-37eeb6ba22fb.png)

ロードバランサの作成に戻ります
![スクリーンショット 2025-04-06 13.06.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/ca31e1a0-4fde-4349-a0d6-a3b84a2c4287.png)


![スクリーンショット 2025-04-06 13.08.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/71e74e65-dcf4-4ef4-9669-737dcee9f6b7.png)


## ALBからECSのセキュリティグループへのアクセスを許可する

![スクリーンショット 2025-04-06 17.08.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/cd0f501b-82c7-4bde-a37f-5a1b93dde715.png)

![スクリーンショット 2025-04-06 17.09.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/9ac46a63-bf07-459c-8ddd-53973edcfb26.png)


## Fargateにアクセスしてみよう
EC2 → ロードバランサ　→ DNS名をクリック
![スクリーンショット 2025-04-06 17.19.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/8490ca8c-92c6-4a7b-a66d-716f0e5d4a0c.png)

ブラウザからhttpでアクセス
![スクリーンショット 2025-04-06 13.09.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/45e360c2-c4d4-471a-a021-3ba8fc213849.png)
![スクリーンショット 2025-04-06 12.29.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/c2c897df-55c4-40e2-b69a-f46ce0483ada.png)


## Fargateの中に入ってみよう

ECS → タスク → 設定にあるECS Execを確認します
![スクリーンショット 2025-04-06 17.24.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/4c468033-6bf5-4b5c-83a0-d2df5dfb8e9d.png)


CloudShellを開いて以下のコマンドを使用します
クラスタ名とサービス名は変更してください

```ruby:
aws ecs update-service \
  --cluster <ECSクラスタ名> \
  --service <ECSサービス名> \
  --enable-execute-command
```

一度タスクを停止し、更新ボタンを押して再度実行中のタスクが表示されるのを確認してください。新たにデプロイされたタスクに対してECS Execが有効になります。

![スクリーンショット 2025-04-06 17.32.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/6f119aab-cf12-41e7-aea3-87ce2bc7374e.png)



タスク内へシェル接続します
![スクリーンショット 2025-04-06 17.39.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3999989/57dd6506-3806-4313-9492-ecef6238267d.png)

CloudShellで以下のコマンドを使用します
クラスタ名とサービス名、コンテナ名は変更してください

```ruby:
aws ecs execute-command \
  --cluster <ECSクラスタ名> \
  --task <新しいタスクID> \
  --container <コンテナ名> \
  --command "/bin/sh" \
  --interactive
```

これでFargateに自由に入れるようになりました🎉


## 後片付け
:::note warn
**お金かかるので不要なら削除しましょう**
- VPC
- クラスター、サービス、タスク
- ターゲットグループ
- ALB
:::




## まとめ
今回はプライベートサブネットにFargateを置いてALBと接続してみました。
あとはRDSと接続ができればいいですね。
最後までお付き合いくださりありがとうございます。


## 参考文献
https://toamemo.com/wallna/#toc6

https://dx.nid.co.jp/column/what-kind-of-service-is-Amazon-ECS#6683b1661c6fc5032d32714d-1719974027156

https://qiita.com/free-honda/items/fc8de2af0abfc3be9eb9

https://qiita.com/free-honda/items/53884ea680031be839b9