Fargate(BGDeploy)+Rails：ECS設定編

#概要
ECS上でコンテナ化したRailsアプリを動かす
（ダラダラ書いてるので分割予定）

デプロイ設定は以下で
https://qiita.com/kinoshita-yu/items/6d3b07b968ff5810e489

#前提

####構成
- rails
- RDS
- ECS(Fargate)


#構成図
![Fargate構成.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309388/c9a1c551-79fa-bd51-68d7-fa77614d55dd.jpeg)

#VPCの作成
割愛：追記予定

#RDSの設定
割愛：追記予定

#ELBの設定
BlueとGreen用に２つのポートからのターゲットを受け取るように設定する

###ターゲットグループの作成（２つ作成）
1. https://ap-northeast-1.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-1#TargetGroups: に移動
1. 「ターゲットグループの作成」をクリック
1. 「ターゲットグループ名」に任意の名前を設定
1. 「ターゲットの種類」にIPを設定
1. 「プロトコル」にHTTPを設定
1. 「ポート」に3000、3001を設定
1. 「VPC」に作成したものを設定
1. 「ヘルスチェックの設定」以下は任意に設定
1. 「作成」をクリック


###ロードバランサの作成
1. https://ap-northeast-1.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-1#LoadBalancers: に移動
1. 「ロードバランサの作成」をクリックし、「Application Load Balancer」の「作成」をクリック
1. 「名前」「スキーム」「IPアドレスタイプ」に適切なものを設定
1. セキュリティーグループの設定
1. 作成したターゲットグループを設定


#ECS：Fargate設定
###タスク定義用のポリシー作成
1. https://console.aws.amazon.com/iam/home?#/policies に移動
1. 「ポリシーの作成」をクリックし「JSON」タブをクリック
1. 以下「▶︎タスク定義用ポリシー」のように設定し「ポリシーの確認」をクリック

<details><summary>タスク定義用ポリシー</summary><div>

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage",
                "ecr:CompleteLayerUpload",
                "ecr:UploadLayerPart",
                "ecr:BatchCheckLayerAvailability",
                "ecr:PutImage",
                "ecr:BatchDeleteImage",
                "ecr:InitiateLayerUpload",
                "ssm:GetParametersByPath",
                "ssm:GetParameters",
                "ssm:GetParameter",
                "ssm:PutParameter"
            ],
            "Resource": [
                "arn:aws:ecr:ap-northeast-1:XXXXXXXXXX:repository/app",
                "arn:aws:ssm:ap-northeast-1:XXXXXXXXXX:parameter/app/*"
            ]
        },
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:CreateLogGroup",
                "ecs:RegisterTaskDefinition",
                "ecr:GetAuthorizationToken"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor3",
            "Effect": "Allow",
            "Action": [
                "events:PutRule",
                "events:PutTargets",
                "events:DisableRule"
            ],
            "Resource": [
                "arn:aws:events:ap-northeast-1:XXXXXXXXXX:rule/app-*"
            ]
        },
        {
            "Sid": "VisualEditor4",
            "Effect": "Allow",
            "Action": [
                "iam:PassRole"
            ],
            "Resource": [
                "arn:aws:iam::XXXXXXXXXX:role/ecs_app"
            ]
        }
    ]
}
```

</div>
</details>

###タスク定義用のロール作成
1. https://console.aws.amazon.com/iam/home?region=ap-northeast-1#/roles に移動
1. 「ロールの作成」をクリック
1. 上記で作成したポリシーを設定



###タスク定義作成
1. https://ap-northeast-1.console.aws.amazon.com/ecs/home?region=ap-northeast-1#/taskDefinitions に移動
1. 「新しいタスク定義の作成」をクリックし「FARGATE」を選択
1. 「JSONによる設定」ボタンをクリックし以下「▶︎タスク定義」のような記述を行う
※ 環境変数はSystemsManagerで定義

<details><summary>タスク定義</summary><div>

```
{
  "ipcMode": null,
  "executionRoleArn": "arn:aws:iam::XXXXXXXXXX:role/「上で作成したロール」",
  "containerDefinitions": [
    {
      "dnsSearchDomains": null,
      "logConfiguration": {
        "logDriver": "awslogs",
        "secretOptions": null,
        "options": {
          "awslogs-group": "/XXX/XXXXXXXX",
          "awslogs-region": "ap-northeast-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "entryPoint": null,
      "portMappings": [
        {
          "hostPort": 3000,
          "protocol": "tcp",
          "containerPort": 3000
        }
      ],
      "command": [
        "/bin/sh",
        "-c",
        "rails s -p 3000 -b 0.0.0.0"
      ],
      "linuxParameters": null,
      "cpu": 0,
      "environment": [],
      "resourceRequirements": null,
      "ulimits": null,
      "dnsServers": null,
      "mountPoints": [],
      "workingDirectory": null,
      "secrets": [
        {
          "valueFrom": "/XXXXX/APP_DATABASE_HOST",
          "name": "APP_DATABASE_HOST"
        },
        {
          "valueFrom": "/XXXXX/APP_DATABASE_NAME",
          "name": "APP_DATABASE_NAME"
        },
        {
          "valueFrom": "/XXXXX/APP_DATABASE_PASSWORD",
          "name": "APP_DATABASE_PASSWORD"
        },
        {
          "valueFrom": "/XXXXX/APP_DATABASE_USER",
          "name": "APP_DATABASE_USER"
        }
      ],
      "dockerSecurityOptions": null,
      "memory": null,
      "memoryReservation": null,
      "volumesFrom": [],
      "stopTimeout": null,
      "image": "XXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/XXXXX/app@sha256:XXXXXXXXXX",
      "startTimeout": null,
      "dependsOn": null,
      "disableNetworking": null,
      "interactive": null,
      "healthCheck": null,
      "essential": true,
      "links": null,
      "hostname": null,
      "extraHosts": null,
      "pseudoTerminal": null,
      "user": null,
      "readonlyRootFilesystem": null,
      "dockerLabels": null,
      "systemControls": null,
      "privileged": null,
      "name": "XXXXXXXXXX"
    }
  ],
  "placementConstraints": [],
  "memory": "1024",
  "taskRoleArn": null,
  "compatibilities": [
    "EC2",
    "FARGATE"
  ],
  "taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:XXXXXXXXXX:task-definition/XXXXX:5",
  "family": "XXXXX",
  "requiresAttributes": [
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "ecs.capability.execution-role-awslogs"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.ecr-auth"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.21"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "ecs.capability.execution-role-ecr-pull"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "ecs.capability.secrets.ssm.environment-variables"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
    },
    {
      "targetId": null,
      "targetType": null,
      "value": null,
      "name": "ecs.capability.task-eni"
    }
  ],
  "pidMode": null,
  "requiresCompatibilities": [
    "FARGATE"
  ],
  "networkMode": "awsvpc",
  "cpu": "512",
  "revision": 5,
  "status": "ACTIVE",
  "inferenceAccelerators": null,
  "proxyConfiguration": null,
  "volumes": []
}
```

</div></details>

###クラスタ作成
1. https://ap-northeast-1.console.aws.amazon.com/ecs/home?region=ap-northeast-1#/clusters に移動
1. 「クラスターの作成」ボタンをクリック
1. 「クラスターテンプレートの選択」画面で「AWSFargateを使用」を選択し「次のステップ」をクリック
1. 「クラスターの設定」画面に移動
  1. 「クラスター名」を入力
  1. 「VPCの作成」にチェックを入れない
  1. 「CloudWatchContainerInsights」にチェックを入れる

###CodeDeploy用のロール作成
1. https://console.aws.amazon.com/iam/home?region=ap-northeast-1#/roles に移動
1. 「ロールの作成」をクリック
1. 「AWSサービス」→「CodeDeploy」→「CodeDeploy-ECS」と選択し「次のステップ：アクセス権限」をクリック
1. 「AWSCodeDeployRoleForECS」ポリシーが表示されていることを確認し「次のステップ：タグ」をクリック
1. 任意のタグを設定したら「次のステップ：確認」をクリックし、問題なければ「ロールの作成」をクリック


###サービス作成
1. https://ap-northeast-1.console.aws.amazon.com/ecs/home?region=ap-northeast-1#/clusters に移動
1. 作成したクラスタを選択し「サービス」タブの「作成」ボタンをクリック
1. 「サービスの設定」画面に移動するので、以下のように設定

|設定項目|設定内容|
|:-:|:-:|
|起動タイプ|Fargate| 
|タスク定義|作成したタスク定義：latest| 
|クラスター|作成したクラスター| 
|サービス名|任意の名前|
|サービスタイプ|REPLICA|
|タスクの数|1|
|デプロイメントタイプ|Blue/Greenデプロイメント|
|CodeDeployのサービスロール|作成したCodeDeploy用のサービスロール|


1. 「ネットワーク構成」画面の設定

|設定項目|設定内容|
|:-:|:-:|
|クラスターVPC|作成したクラスタ| 
|サブネット|作成したサブネット| 
|セキュリティグループ|作成したセキュリティグループ| 
|パブリックIPの自動割り当て|ENABLED| 
|ヘルスチェック の猶予期間|100| 
|ロードバランサの種類|ApplicationLoadBalancer| 
|ロードバランサ名|作成したロードバランサー| 

1. 「ネットワーク構成」画面の「Blue/Greenデプロイメント」周りの設定
  1. 「ロードバランス用のコンテナ」で「ロードバランサーに追加」ボタンを押す
  1. 「プロダクションリスナーポート」「テストリスナーポート」にそれぞれ作成したロードバランサーのポートを割り当て
  1. 「AdditionalConfiguration」でターゲットグループそれぞれに作成した物を割り当て
  1. 「サービスの検出の統合の有効化」チェックを外す
  1. 「次のステップ」をクリック
1. 「Auto Scaling (オプション)」画面の設定
  1. 「ServiceAutoScaling」任意の設定にチェック（投稿した時点ではBlue/Greenデプロイを行う場合はAutoScalingは不可）
1. 「確認」画面の設定
  1. 内容に問題がなければ「サービスの作成」ボタンをクリック