CodePipelineでECSにデプロイする(Ver.rolling update)

#課題

- AWS上にDocker環境管理からデプロイまで行うこと。

#解決方法

- AWS CodePipelineで自動ビルドとECSにrolling updateデプロイする。

#構成

<img width="843" alt="スクリーンショット 2019-05-17 14.49.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/b521b175-fd89-7ce2-06d2-03b08e56f8da.png">


#事前準備

- VPC作成
- Dockerfile(可能であれば、buildして問題ないもの)

#構築順番

※今回はAWSマネージメントコンソールで作成します。

1. ECR作成
2. ECS作成
3. CodePipeLine作成

##ECR作成

### Repostory name入力

![ecr_create_qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/88fa6c26-2669-1af1-c741-3340fe046b60.png)

### View push commands確認

Repostory作成できたら、詳細に移動して「View push commands」をクリックすると、
下記のimgのように、ECRにpushする方法が表示されます。

![ecr_view_command_qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/33a3b63e-bef4-94ee-eb1a-5ec9b3408c02.png)


**補足**

```text

・ECRに上げる方法は上記のcommandsとCodeBuildがあります。
  CodeBuildによるpushの方法は下記の'CodeBuild作成'のところを参考してください。
・今後ECS Service作成のために、ECRにあげておきましょう。
```

### ECRにpush後一覧表示

![ecr_after_push_qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/202edc00-8426-755c-5c76-5177f6a5c41a.png)


**補足**

```text
・imageURLに'************.dkr.ecr.us-east-1.amazonaws.com/イメージ名:latest'の確認ができ、
  このimageURLがECS Serviceのcontainer作成する時必要になります。
```

##ECS作成

**ECS作成手順**
1. TableDefinition作成
2. ELB作成
3. Cluster作成
4. Service作成

###TableDefinition作成

#### EC2 type選択

![ecs_tabledefinition_craete1_qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/005b5e1c-1b60-1f9a-59a0-3cf2ae830634.png)


#### EC2 詳細設定

![ecs_tabledefinition_craete2_qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/1f69178c-a5e7-c71b-28eb-420d0cc96065.png)


**補足**

```text
・TaskRoleはCodeDeployする際、ECS実行のために必要です。
  「ecsTaskExcutionRole」がなかったら、下記の手順で作成してください。

　・ecsTaskExcutionRole作成方法
　　・IAM > Roles > Create Role
　　・Elastic Container Service選択 > Elastic Container Service Task選択 > Next:Permissions
　　・AmazonECSTaskExcutionRolePolicy検索後チェック > Next: Tags
　　・Add tagsスルーしてNext:Reviewに移動
　　・Role nameをecsTaskExcutionRoleにしてCreate role
```

#### Container Definitions設定

![スクリーンショット 2019-09-26 19 40 10](https://user-images.githubusercontent.com/17561411/65682243-8190a500-e095-11e9-9fe1-17729fd83e0e.png)

**補足**

```text
・Container nameはCodeBuildの時使うので、覚えておいてください。
・Imageは先ほどECRのImageURLを入力してください。'************.dkr.ecr.us-east-1.amazonaws.com/イメージ名:latest'
・Memory LimitsはContainerに重いAppが動くのであれば、Soft limitで設定してください。
・Port mappingsはContainer port設定だけでOKです。
  ECSのDeployは基本ALBを使います。
  Host portを設定してしまうと、Containerがすでに使っているportだとエラーが発生します。
```

- TableDefinition作成できたら、詳細画面で「Task Definition Name:Revision」の確認ができます。

###ELB作成

1. EC2コンソール > Load Balancers選択
2. Create Load Balancer選択
3. Application Load Balancer選択 > Create
4. Configure Load Balancerページ
    1. NameにLoad Balancer名入力
    2. Schemaにinternet-facing設定
    3. Ip address typeでipv4選択
    4. Load Balancer ProtocolでHTTP選択してPortを80にする
    5. 前もって作ったVPCを選択後、２つのSubnetを選択
    6. Next: Configure Security Settings
5. Configure Security Groupsページ
    1. なかったらnewを、あったらexistingを選択
    2. Next: Configure Routing
6. Configure Routingページ
    1. Target groupでNew target group選択
    2. NameにTarget名入力
    3. Target typeでIPを選択
    4. ProtocolでHTTP選択
    5. portに80
    6. Next: Register Targets
7. Reviewページ
    1. Create選択


**補足**

```text
・Health check PathがAppに合わせて設定してください。
・ALB設定したので、ECSのSecurity GroupsにALBのSecurity GroupsをAll TCPで適用してください。
・rolling updateの場合Load Balancer Protocol１つで
  Blue/Green Deployの場合Load Balancer Protocol２つになります。
```

###Cluster作成

#### template選択(EC2Linux + Networking)
![ecs_cluster1_qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/b6c9818d-f564-d3bd-c9c1-3c9d6c10e1b9.png)

#### cluster設定1
![ecs_cluster2_qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/8eb911b3-bfa5-0548-fffb-462a14b5365f.png)

**補足**

```text
・EC2 instance typeは t2.medium以上をオススメします。
　CodeDeployする時一時的にContainerが２つ立ち上がってmemoryが足りない現象が起きてしまうからです。
```

#### cluster設定2

Networkingは作っておいたVPCと２つのSubnetの設定でOKです。
EC2のSecurityGroupも選択してください。
ALB作成するところにも書きましたが、**必ずALBのSGと紐づけてください。**

#### cluster設定3

![ecs_cluster3_qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/1802dd87-f39d-dbab-bc69-44eea59b6e9f.png)

**補足**

```text
・「ecsInstanceRole」がなかったら下記の手順で作成してください。
　・ecsInstanceRole作成方法
　　・IAM > Roles > Create Role
　　・EC2選択 > Next:Permissions
　　・AmazonEC2ContainerServiceForEC2Role検索後チェック > Next: Tags
　　・Add tagsスルーしてNext:Reviewに移動
　　・Role nameをecsInstanceRoleにしてCreate role
```

### Service作成

#### Service設定

先ほど作ったClusterの詳細にService Createをクリックして移動しましょう。
![ecs_service1_qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/b7bbecaf-badb-f73e-dde6-2b2c3cd13d3b.png)

**補足**

```text
・作成したTable Definition名とRevisionを選択してください。
・作成したClusterを選択してください。
・Service nameは好きなもので入力してください。
```

#### Deployment設定

今回は**Rolling update**選択して、「Next step」をクリックしてください。

![ecs_service2_qitta.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/b54d0631-258f-35ac-1c7d-f42cbeff00d4.png)

#### Network設定

![ecs_network1_qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/1d308f35-1a9e-38ad-050d-48ba826821d7.png)

**補足**

```text
・Deployのなめに、ALBを選択してください。
・「ecsServiceRole」がなかったら下記の手順で作成してください。(おそらくすでにあると思います)
　・ecsServiceRole作成方法
　　・IAM > Roles > Create Role
　　・Elastic Container Service選択 > ユースケースの選択でElastic Container Service選択 > Next:Permissions
　　・AmazonEC2ContainerServiceRole検索後チェック > Next: Tags
　　・Add tagsスルーしてNext:Reviewに移動
　　・Role nameをecsServiceRoleにしてCreate role
・作成したLoad balancer nameを選択してください。
```
#### ALB target設定

![スクリーンショット 2019-05-17 16.36.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/d8f07610-bb94-23f7-77fa-ac9e2a2695e7.png)

**補足**

```text
・Target group nameで作成してALB targetを選択すると、そのtargetによる情報で設定されます。
　設定がおわったら、そのまま次のページに移動してください。
```
#### Auto Scaling設定

今回使わないので、
「Do not adjust the service’s desired count」を選択してそのまま作成まで進んでください。


##CodePipeline作成

**CodePipeline作成手順**
1. CodeBuild作成
2. CodePipeline作成

###CodeBuild作成

####Project configuration

Project名だけでOKです。

![スクリーンショット 2019-05-17 16.47.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/6528f8a6-e85a-5b7d-911d-91c388a69b90.png)

####Source

CodeBuildするSource先を選んでください。

![スクリーンショット 2019-05-17 16.47.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/8aed086a-048d-8f99-6e1c-9946fb1c62d7.png)

**補足**

```text
・Source providerにAWS CodeCommitなど色々ありますが、今回はGitHubを使いました。
```

####Primary source webhook events

GitHubで何かのアクションを行ったらBuildを動かすものですが、
今回はCodePipelineで設定するので、**別にやる必要はない**です。

一応下記のイメージでやっていることだけ説明すると、
testというブランチにgit pushするたびにBuildが走ることになります。

![スクリーンショット 2019-09-25 10 41 51](https://user-images.githubusercontent.com/17561411/65562386-2ff6f600-df81-11e9-939e-bf616b36c904.png)


####Environment

Docker imageを使用するには、Environment imageのManaged imageを選択して、
Operating system, Runtime, Image, Image versionを適切に選択してください。

![スクリーンショット 2019-05-17 16.54.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/14f935e9-9cab-12ad-db99-8b054584aa00.png)

**補足**

```text
・Docker image buildするために、Privilegedを必ず選択してください。
```

####Buildspec

CodeBuildするために、builspec.ymlファイルが必要なので、「Use a builspec file」を選択してください。

![スクリーンショット 2019-05-17 16.58.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/0ed951df-b034-64b7-a457-da4d879bc65f.png)


####builspec.yml作成

必要なfile
・builspec.yml(codeBuildするためのymlファイル)
・imagedefinitions.json(codeDeployの時、この情報でServiceのTableDefinitionの新しいリビジョンを作成し、新しいタスク定義を使用してサービスを更新するファイル)

```yml
version: 0.2

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - $(aws ecr get-login --no-include-email --region us-east-1)
  build:
    commands:
      - echo Building the Docker image...
      - docker image build --file Dockerfile . -t イメージ名:latest
      - docker tag イメージ名:latest ************.dkr.ecr.us-east-1.amazonaws.com/イメージ名:latest
  post_build:
    commands:
      - echo Pushing the Docker image...
      - docker push ************.dkr.ecr.us-east-1.amazonaws.com/イメージ名:latest
      - echo Writing image definitions file...
      - printf '[{"name":"{container name}","imageUri":"%s"}]' ************.dkr.ecr.us-east-1.amazonaws.com/イメージ名:latest > imagedefinitions.json
artifacts:
  files:
    - imagedefinitions.json
```

**補足**

```text
・container nameは「Container Definitions設定」のcontainer nameを入力してください。
・imagedefinitions.jsonはファイル作成だけでOKです。
```


###CodePipeline作成

####Pipeline setting

Pipeline名を作成して次に進んでください。

![スクリーンショット 2019-05-17 17.12.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/7a2942b9-e850-e794-8411-1c376a1a04fb.png)

####source stage

Source ProviderをGitHubを選択して、Repository > Branchを選択すると、
そのBranchにpushするたびに、このCodePipelineが動き始めます。

![スクリーンショット 2019-05-17 17.12.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/f4afe203-3260-8fe2-b81d-bad15553b8f0.png)

####build stage

作成したCodeBuildを選択してください。

![スクリーンショット 2019-05-17 17.13.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/d63187c9-84d3-51cf-d0f6-e520048fbe65.png)

####deploy stage

Deploy providerをAmazon ECSを選択して、
作成したCluster nameとService nameを選択してください。

![スクリーンショット 2019-05-17 17.13.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/4525b3f5-7a76-ef72-dc50-9356119a94b8.png)

**補足**

```text
・image definitions fileはCodeBuildする時作成されるので、書かなくても大丈夫です。
```

####deploy success画面

![スクリーンショット 2019-05-17 17.20.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115632/efb17eee-1d8e-4bb5-a821-5ee0ba2f4fdd.png)


#**まとめ**

個人的に初めてAWSを深く触れる機会になって、非常に面白かったです。

実はDockerすら詳しくなかったので、ハードルが高いと感じられたし、触るたびにエラーばかりでした。
しかし、Docker buildからECRにpushしたり、ECSだけ動かしてみたりしながら、少しずつ理解した結果、
ついにgit pushだけでDocker deployができる仕組みを作りました。

今回構築において最も困っていたところはエラーlogの確認が難しいことでした。
色々試してみたら、下記の方法がなんとかアプローチできたのではないかと思います。
・Cluster > Service > Tasks or Events or Deployments確認
・ALB target health確認
・直接にServerに入ってlog確認

ちなみに、今後Qiitaに追加したい内容はECS(Blue/Green Deploy)と本記事内容のCloudFormation作成です！

最後に[政谷さん](https://qiita.com/k_masatany)色々ありがとうございましたー


#**参考**

[チュートリアル: Amazon ECR ソースと、ECS と CodeDeploy 間のデプロイでパイプラインを作成する](https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/tutorials-ecs-ecr-codedeploy.html)
[CodePipelineからECSにBlue/Greenデプロイする](https://dev.classmethod.jp/cloud/aws/codepipeline-ecs-codedeploy/)
[Amazon ECS入門 〜公式のDockerイメージを使って10分で構築してみる〜](https://dev.classmethod.jp/cloud/aws/amazon-ecs-entrance-1/)