Amazon ECS & Fargate と Docker on AWS CICDの学習まとめ（超初心者向け）

# これからはAWSのFargateだ！
ということで学習しながら設定の流れをメモとして随時更新します。

学習内容 ECS & Fargate, Load Balancing, Auto Scaling, ECR, CICD for ECS
最終的には、Rubu on Rails をFargateで動かすところまで目指します。

## AWSの準備＆ユーザ設定
* AWSのアカウント作成
* IAM ユーザーの設定
ルートユーザ→Adominユーザ
  * AWS アクセスの種類を選択(全部選択)
  * アクセス許可の設定
  →既存のポリシーを直接アタッチを選択
  →AmazonECS_FullAccessを選択
  * タグの追加 (不要)
  * 認証情報(コンソールのサインインリンク保存）
  * アクセス権限の追加
  →既存のポリシーを直接アタッチを選択
  →AdministratorAccess

## Fargateの設定
* リージョンを選択（東京）
* Elastic Container Service (ECS)を選択
* 2022/04時点では、ECS エクスペリエンスは古い方で設定を開始する
* ECS オブジェクトとそれらの関連を示す図
![スクリーンショット 2022-04-01 6.02.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/3837e28a-f1c4-6542-c118-841c43cc7279.png)
* タスク定義名 nginx-tdに変更
* クラスター名 nginx-clusterに変更
* お金をチャージされるで一旦削除
  →左サイドバー：クラスターを選択
  →サービスのタブを選択
  →サービス名をチェックして「削除」を選択
  →タスクのタブを選択
  →すべてを停止

## 構成図作成ツール：Diagram（無料）

* はじめはディスクトップ版だったがWEB版の方が、AWSの最新のアイコンがあって便利
https://app.diagrams.net/?splash=0&libs=aws4

## 複数サービスの場合の構成イメージ
![ECSクラスター_複数サービス.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/0ee6f246-c397-9e09-f570-3fb6dbb1370c.png)

## テスト用と本番用のアーキテクチャのイメージ
![Docker-ECSアーキテクチャー2.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/3edb7739-4a9b-8bc7-e1cd-b5f137268af0.png)
## ECSの料金について
https://aws.amazon.com/jp/fargate/pricing/
* テストは、無料枠ではできないので2,000円〜3,000円前後かかる想定。
* コストを抑えるため学習していない時は以下の対応をする。
  * EC2インスタンスの終了させる。
  * ECSサービスを0にする。
## ECSとEKSとBeanstalkの違い
* ECS
  * Docker on AWS
  * 専用の領域がある
  * EC2と連携できる
  * 詳細：https://aws.amazon.com/jp/ecs/
* EKS
  * Docker on AWS
  * Kubernetesを使う場合
  * オープンソース
  * 詳細：https://aws.amazon.com/jp/eks/
* Beanstalk
  * Paas(Platform as a Servic) on AWS
  * 少しのカスタマイズの場合？
  * 詳細：https://aws.amazon.com/jp/elasticbeanstalk/
## Docker構成図・インストール
* Docker on AWS 構成図
![Docker.drawio2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/4573c421-827b-f0d3-571b-663602f8e722.png)

* Docker Desktop インストール
https://www.docker.com/products/docker-desktop/
## Docker コマンド基礎

正しい内容は、ドキュメンを確認してください。

http://docs.docker.jp/v19.03/engine/reference/commandline/index.html

使ったものを以下にまとめます。

| 内容 | コマンド | 備考　|
|:-|:-|:-|
| コマンドでインストールできたか確認する | $ docker run hello-world |
| イメージ一覧 | $ docker image ls  | $ docker images(旧） |
| コンテナ一覧 | $ docker container ls | $ docker ps(旧） -aで全て表示|
| コンテナを全部表示一覧 | $ docker container ls --all |
| Docker Hubのイメージを検索（例 nginx) | $ docker search nginx |
| 名前をつけてコンテナを立ち上げる<br>例）nginxのimageから名前をつけてコンテナを立ち上げる | $ docker run --name (CONTAINER NAMES) -P -d nginx | * run：新しいコンテナを実行する命令<br>*　--name：名前をつける<br>*　-P：コンテナのポートをホスト側に公開 <br>*　-d：コンテナをバックグラウンドで実行し、コンテナ ID を表示　|
| 詳細情報表示 | $ docker inspect (IMAGE ID) |
| コンテナを起動する | $ docker start (IMAGE ID) |
| コンテナを停止する | $ docker stop (IMAGE ID)  |
| 使われていないイメージなどを削除 | $ docker system prune |
| Dockerfileをビルド | $ docker build -t (New Docker Name) .|-t：タグ名を指定　|
| imageを動かす | $ docker run (New Docker Name)|
| imageを削除する | $ docker image rm (Image ID)|
| コンテナを削除する | $ docker rm (Container ID)|
## ECS クラスター図解
![ECSクラスター.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/3f750405-ef7d-906b-a7c8-59d56428c9b0.png)
## ECS クラスターとIAM設定図解
![ECSクラスター_IAM.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/0cfedfa9-fc61-53f5-e6f7-0bbdc491faab.png)
### ロール(Roles)の追加
* EC2 Role for Elastic Container Serviceのロール追加
IAM>ロール>ロールを作成>ユースケース>EC2 Role for Elastic Container Service(検索）
* Elastic Container Serviceのロール追加
ユースケース>Elastic Container Service(検索）
* Elastic Container Service Taskのロール追加
ユースケース>Elastic Container Service Task(検索）
  * 許可を追加
  TaskExecutionにチェック
* Elastic Container Service Autoscaleのロール追加
ユースケース>Elastic Container Service Autoscale(検索）

## コアのインフラストラクチャー
![Docker-ECS設定2.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/e0f78afd-59f0-120f-f13d-2971a9b1bbb9.png)

* ymlファイルに上記のストラクチャを記述
core-infrastructure-setup.yml
* AWS CLIのインストール
「aws」コマンドを使うためにはインストールが必要だった
https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html

```zsh
$ curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
$ sudo installer -pkg AWSCLIV2.pkg -target /
``` 
* AWS CLI セットアップ
https://docs.aws.amazon.com/ja_jp/autoscaling/application/userguide/setup-awscli.html

```bash
$ aws help
#　heplでコマンド一覧

$ aws configure --profile adminuser
#　プロンプトが表示されたら、Application Auto Scaling で使用する IAM ユーザーの AWS アクセスキーとシークレットアクセスキーを指定します。

#aws_access_key_id = adminuser access key ID
#aws_secret_access_key = adminuser secret access key
#region = aws-region
#default output format = json

# /Users/ichigobranding/.aws/credentials に記載されている
``` 
* プロファイルが正しく設定されている場合は、以下のような出力が表示されます。
```bash
$ aws configure --profile adminuser

AWS Access Key ID [****************52FQ]: 
AWS Secret Access Key [****************xgyZ]: 
Default region name [us-east-1]: 
Default output format [json]: 
``` 
* IAMユーザーの確認
```bash
$ aws iam list-users
``` 
* プロファイルの確認
```bash
$ aws configure list
``` 
* プロファイルを自分のアカウントに切り替える（デフォルトの設定:例 user1）
```bash
$ export AWS_DEFAULT_PROFILE=user1
``` 
### Macのzshでコマンド補完の設定をした場合
* AWS CLI コマンド補完
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-completion.html#cli-command-completion-linux
```bash
$ cd /usr/local/bin/
$ touch .zshrc
$ vim ~/.zshrc 

下記を.zshrc の１行目に記載
autoload -Uz compinit && compinit
autoload -U bashcompinit && bashcompinit
complete -C '/usr/local/bin/aws_completer' aws
EOF

$ source .zshrc

$ aws s → 補完が出たら完了
```
* コマンドでインフラストラクチャーを一括で生成
```bash
$ aws cloudformation create-stack --capabilities CAPABILITY_IAM --stack-name ecs-core-infrastructure --template-body file://./core-infrastructure-setup.yml
``` 
* CloudFormationで確認する
CloudFormation>スタック　（リージョンをあわせる） 
  * ecs-core-infrastructure
VPC and subnets as base for an ECS cluster
  * EC2ContainerService-nginx-cluster
AWS CloudFormation template to create a new ECS Fargate First Run stack
* VPNで確認する

## ECSを作成する(EC2ベース）
Amazon Elastic CEontainer Service>クラスター>作成
* クラスター名前を設定
* VPCは、作ったものを選択
* サブネット2つ選択
* Amazon EC2 インスタンスにチェックを入れる
Auto Scaling グループ (ASG)の作成
![Docker-ECS設定_EC_ASG.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/dcc0eb03-94e0-d8c4-3477-3acd2e5a7f0b.png)

  * オペレーティングシステム/アーキテクチャ
→Aamazon Linux3(arm64)を選択
  * EC2 インスタンスタイプ
  →a1.mediumを選択
  * 必要な容量
  →1
## ECSをFargateベースに変更する
![Docker-ECS設定_fargate_ASG.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/f385d3e1-dd86-a3c7-7650-3397aa52ed78.png)

## ECSをCloudFormationにする
![Docker-ECS設定_CloudFormation.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/2d89c9ec-f5b7-0f94-f16d-2da26348776a.png)

Launchtype _Fargate_:  

```bash
aws cloudformation create-stack --stack-name ecs-fargate --capabilities CAPABILITY_IAM --template-body file://./ecs-fargate-via-cloudformation.yml
```

Launchtype _EC2_:  

```bash
aws cloudformation create-stack --stack-name ecs-ec2 --capabilities CAPABILITY_IAM --template-body file://./ecs-ec2-via-cloudformation.yml
```
## ECS CLIでoutputのkeyを表示させる

```bash
export CORE_STACK_NAME="ecs-core-infrastructure"
export vpc=$(aws cloudformation describe-stacks --stack-name $CORE_STACK_NAME --query 'Stacks[0].Outputs[?OutputKey==`VpcId`].OutputValue' --output text)
export subnet_1=$(aws cloudformation describe-stacks --stack-name $CORE_STACK_NAME --query 'Stacks[0].Outputs[?OutputKey==`PublicSubnetOne`].OutputValue' --output text)
export subnet_2=$(aws cloudformation describe-stacks --stack-name $CORE_STACK_NAME --query 'Stacks[0].Outputs[?OutputKey==`PublicSubnetTwo`].OutputValue' --output text)

echo "vpc: $vpc"
echo "subnet1: $subnet_1"
echo "subnet2: $subnet_2"
```

## Amazon ECS CLI セットアップ
* ecs-cli configure
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/cmd-ecs-cli-configure.html

```bash
#①ダウンロード
$ sudo curl -o /usr/local/bin/ecs-cli https://amazon-ecs-cli.s3.amazonaws.com/ecs-cli-darwin-amd64-latest

#②パーミッション変更
$ sudo chmod +x /usr/local/bin/ecs-cli

#③バージョンの確認
$ ecs-cli --version
```

* ecs-cli configure の設定

```bash
# リージョン・クラスタ名の設定
$ ecs-cli configure --region region名 --cluster cluste名 --default-launch-type FARGATE -config-name config名
```


## ECS:launch-type FARGATEを作成する

```bash
ecs-cli up \
--subnets $subnet_1,$subnet_2 \
--vpc $vpc \
--launch-type FARGATE \
--cluster ecs-fargate
```
## ECS:launch-type EC2を作成する
* Amazon EC2 キーペアの作成、表示、削除
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-services-ec2-keypairs.html

```bash
ecs-cli up --capability-iam \
--subnets $subnet_1,$subnet_2 \
--vpc $vpc \
--launch-type EC2 \
--keypair ecs-course \
--size 1 \
--instance-type t2.small \
--cluster ecs-ec2
```

## ECS サービス ALB
![Docker-EC2_Service.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/573cb8a0-56c4-389c-3307-6cb15241b945.png)

## ecs-cliでvpc名・subnet名をエクスポートする

```
export CORE_STACK_NAME="ecs-core-infrastructure"
export vpc=$(aws cloudformation describe-stacks --stack-name $CORE_STACK_NAME --query 'Stacks[0].Outputs[?OutputKey==`VpcId`].OutputValue' --output text)
export subnet_1=$(aws cloudformation describe-stacks --stack-name $CORE_STACK_NAME --query 'Stacks[0].Outputs[?OutputKey==`PublicSubnetOne`].OutputValue' --output text)
export subnet_2=$(aws cloudformation describe-stacks --stack-name $CORE_STACK_NAME --query 'Stacks[0].Outputs[?OutputKey==`PublicSubnetTwo`].OutputValue' --output text)
```
上記は、設定のみで何も表示されないので、echoで表示させる
```
echo "vpc: $vpc"
echo "subnet1: $subnet_1"
echo "subnet2: $subnet_2"
```
## ecs-cliでCloudFormationにecs-ec2を設定する
```
ecs-cli up --capability-iam \
--subnets $subnet_1,$subnet_2 \
--vpc $vpc \
--launch-type EC2 \
--keypair ecs-course \
--size 1 \
--instance-type t2.small \
--cluster ecs-ec2
```

## EC2でセキュリティグループを作成
EC2＞セキュリティグループ＞セキュリティグループを作成

## Fargateを使ったタスクとサービスの設定
![Docker-テスク・サービスの設定.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/638b7203-e1b2-5e9d-c0e7-888a3914413c.png)
* ECSのタスクをデプロイ
Amazon Elastic Container Service＞クラスター＞ecs名＞タスク
* ECSのサービスをデプロイ
Amazon Elastic Container Service＞クラスター＞ecs名＞サービス
## EC2を使ったタスクとサービスの設定
![Docker-Copy of テスク・サービスの設定.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/fade11f8-85db-3041-2a9e-c9ae3f7ede7f.png)
* ECSのタスクをデプロイ
Amazon Elastic Container Service＞タスク定義
Amazon Elastic Container Service＞タスク定義＞作成
  * 新しいリビジョンの作成
Amazon Elastic Container Service＞タスク定義＞td-ec2-wisdom-final＞リビジョン 2＞リビジョンを作成
  * インバウンドのルールを編集
  * 新しい管理画面では、「パブリック IP」が表示されていないため、古い画面に切り替え、インバウンドルールを変更（変更しないとブラウザで見れない）
クラスター＞ecs-ec2＞タスク: ID
→ EC2 インスタンスのIDをクリック
【説明タブより】セキュリティグループ＞ID>インバウンドのルールを編集
HTTP→すべてのICP
* ECSのサービスをデプロイ＞Amazon Elastic Container Service＞クラスター＞ecs-ec2＞サービスの作成

## Amazon ECS タスク配置戦略
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task-placement-strategies.html

![Docker-ECSTaskPlacement.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/f772fdb2-c248-fab0-07d8-22bc59b700e1.png)
```
"placementStrategy": [
    {
        "field": "memory",
        "type": "binpack"
    }
]
```

```
"placementStrategy": [
    {
        "type": "distinctInstance"
    }
]
```
https://aws.amazon.com/jp/blogs/compute/amazon-ecs-task-placement/
```
"placementStrategy": [
    {
        "expression": "attribute:ecs.instance-type =~ t2.*",
        "type": "memberOf"
    }
]
```
## ECS Networking Mode
![Docker-ECS NetworkingMode.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/d04118ca-5c2c-42df-a515-fd21e20f7327.png)


## ECSのセキュアーなアーキテクチャの設定

![Docker-Extended ECS Architecture Setup.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605068/5a963a82-55d6-a5cf-d255-eec72678d400.png)
※ALB・NatGWに費用がかかる