【AWS】ECS構築の基礎 −Blue/Greenデプロイ編−

#はじめに
前回の記事でCodeCommit, CodeBuild, CodePipelineを使って、AWSサービスのみでCI/CDパイプラインを構築しました。
今回は構築したパイプラインにBlue/Greenデプロイを追加して、CodeDeployから制御してみました。

https://qiita.com/suzuki0430/items/06755312a7757b940e69

ECS初心者向けの記事を何本か書いていますので、どれか参考になれば幸いです。

https://qiita.com/suzuki0430/items/2745e9ca0ead8db982f9

https://qiita.com/suzuki0430/items/440daea590b22d1621c8

https://qiita.com/suzuki0430/items/6e4e7f513f982dadbf09

https://qiita.com/suzuki0430/items/7e0ad9903d26dd5f2529

#Blue/Greenデプロイ
Blue/Greenデプロイは、アプリケーションやマイクロサービスの古いバージョン(Blue環境)からテスト済の新しいバージョン(Green環境)に、ユーザートラフィックを徐々に転送するリリースモデルで、両バージョンが稼働中の状態で実施するものです。

BlueからGreenへのトラフィックの転送が完了すると、Blueはロールバックに備えてスタンバイさせるか、あるいはプロダクションからプルして更新し、次回の更新の際にテンプレートとして使用することができます。

ECSやFargateでBlue/Greenデプロイを実行するために、CodeDeployを使用します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/98fb004b-27dd-d5b5-4e8e-c9079e686c2a.png" width="800">

##実装
前回の記事で作成したCI/CDパイプラインに以下の手順でBlue/Greenデプロイを追加します。

1. IAMロールの作成
2. ELBリスナーの作成
3. サービスの作成
4. buildspec.ymlの作成
5. appspec.yamlの作成
6. taskdef.jsonの作成
7. Buildの編集
8. Deployの編集
9. パイプラインの実行

###IAMロールの作成
`CodeDeploy - ECS`というユースケースを選択します。
![スクリーンショット 2021-07-10 10.19.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/9d8b3b4e-3e38-ac5b-e2b7-043a14a8b8ba.png)

この中には`AWSCodeDeployRoleForECS`というポリシー(中身は以下)が含まれています。
![スクリーンショット 2021-07-10 10.21.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/62c8b8fa-77cd-7929-0933-6e82461fdb54.png)

`CodeDeployServiceRole`と名付けます。
![スクリーンショット 2021-07-10 10.22.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/6b8563fd-f5ff-a669-a05b-97611a949539.png)

###ELBリスナーの作成
次にELBでリスナーを作成します。
リスナーは設定したプロトコルとポートを使用して接続リクエストをチェックするプロセスです。
リスナーに対して定義したルールによって、ELBが登録済みターゲットにリクエストをルーティングする方法が決まります。

プロダクションリスナーを新しく追加します。
![スクリーンショット 2021-07-10 10.35.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/f034d1d5-c87b-1a31-1205-63157d4a8acf.png)

また、検証テストを使用するECSデプロイには2番目のリスナー(テストリスナー)が必要です。
このリスナーは、更新されたアプリケーションにテストトラフィックを提供するために置き換えタスクセットで使用されます。
検証テストは、テストトラフィックに対して実行されます。

`HTTP:8088`でTestリスナーを作成します。
![スクリーンショット 2021-07-10 10.37.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/4dac13be-909b-7d8d-6bf8-8f55d450af7f.png)

###サービスの作成
ECSクラスター`ecs-service`に新しくサービスを作成します。
タスク定義やクラスターを選択して、サービス名を設定します。
![スクリーンショット 2021-07-10 10.43.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/29f89dd1-4faf-e782-f3d2-9becfc54ce8d.png)

デプロイメントタイプ、デプロイメント設定、CodeDeployのサービスロールをそれぞれ選択します。
![スクリーンショット 2021-07-10 10.43.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/d43b4fa5-3d7d-8859-bfe9-bb0edd35e700.png)

ELBの設定で、プロダクションリスナーポートやテストリスナーポートを選択します。
![スクリーンショット 2021-07-10 10.48.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/78abeaad-3ead-f076-c926-0e4e8f8dc79e.png)

以上の設定でサービスを作成します。
ELBのリスナーの中身をみてみると、ターゲットグループが正しく設定されています。
![スクリーンショット 2021-07-10 10.51.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/0d535064-5bf4-67a1-ccdb-91de274924e1.png)

また、CodeDeployを開くと作成したアプリケーションの中身も確認できます。
![スクリーンショット 2021-07-10 10.54.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/20f25ebd-2f37-07fd-c234-50a0a8f5f634.png)

###buildspec.ymlの修正
artifactsの記述を修正します。

```yml
version: 0.2

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - aws --version
      - echo $AWS_DEFAULT_REGION
      - $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
      - REPOSITORY_URI=<<account-id>>.dkr.ecr.ap-northeast-1.amazonaws.com/ecr-simplehttp
      - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - IMAGE_TAG=${COMMIT_HASH:=latest}
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - docker build -t $REPOSITORY_URI:latest .
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
  post_build:
    commands:
      - echo Build completed on `date`
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - printf '[{"name":"simplehttp-container","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
      - printf '{"ImageURI":"%s"}' $REPOSITORY_URI:$IMAGE_TAG > imageDetail.json
artifacts:
  files:
    - 'image*.json'
    - 'appspec.yaml'
    - 'taskdef.json'
  secondary-artifacts:
    DefinitionArtifact:
      files:
        - appspec.yaml
        - taskdef.json
    ImageArtifact:
      files:
        - imageDetail.json
```

###appspec.yamlの作成
ルートディレクトリに新しくAppSpecファイル`appspec.yaml`を作成します。
AppSpecファイルでは、ECSサービスの名前と、新しいタスクセットにトラフィックを送信するために使用されるコンテナ名とポートなどを指定します。

```yml:appspec.yaml
version: 0.0

Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: <TASK_DEFINITION>
        LoadBalancerInfo:
          ContainerName: "simplehttp-container"
          ContainerPort: 8000
```

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/application-specification-files.html#appspec-files-on-ecs-compute-platform

https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/reference-appspec-file-example.html#appspec-file-example-ecs

###taskdef.jsonの作成
ルートディレクトリに`taskdef.json`を作成し、タスク定義のJSONを貼り付けます。
![スクリーンショット 2021-07-10 11.02.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/ec754fc3-2dc1-6190-c7ea-3c6616ec49d5.png)

imageの箇所を以下のように修正します。

```
"image": <IMAGE1_NAME>,
```

###Buildの編集
CodeDeployからBuildの出力アーティファクトに`DefinitionArtifact`と`ImageArtifact`を追加します。
![スクリーンショット 2021-07-10 11.07.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/1776c6ea-217f-00aa-9496-002dfb514356.png)

###Deployの編集
Deployについても修正します。
入力アーティファクトに`DefinitionArtifact`と`ImageArtifact`を追加します。
その他にはCodeDeployアプリケーション名やデプロイグループの指定、DefinitionArtifactののファイル選択、ImageArtifactの選択などを行います。
![スクリーンショット 2021-07-10 11.28.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/098a7f91-9b3d-465e-cc70-82cf52d0af09.png)

###パイプラインの実行
パイプラインを実行すると、CodeDeployからトラフィック移行の進行状況を確認することができます。
![スクリーンショット 2021-07-10 11.34.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/3e15b01c-e20b-1197-042a-41dc92f083ee.png)

トラフィックの移行が終わると置き換えタスクセットの方が100 %と表示されます。
![スクリーンショット 2021-07-10 11.43.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/c0bb78f4-1827-1d65-696b-cf1232c0f8bd.png)


#参考資料

https://www.udemy.com/course/aws-ecs-fargate/

https://aws.amazon.com/jp/blogs/news/use-aws-codedeploy-to-implement-blue-green-deployments-for-aws-fargate-and-amazon-ecs/

https://www.redhat.com/ja/topics/devops/what-is-blue-green-deployment

https://qiita.com/NaokiIshimura/items/86ec84a13a6ceb831bba