ECS ブルーグリーンデプロイのCDK

ECS FargateへのブルーグリーンデプロイをCDKでやってみた際の備忘録です。

内容はこちらのワークショップを履行しました。
ただ、CDKのコードを一部変えたのでその箇所だけメモとして残します。

https://catalog.workshops.aws/cicdonaws/ja-JP

## 変更点
ワークショップの[Lab6](https://catalog.workshops.aws/cicdonaws/ja-JP/lab06)ではCDKは以下のような階層になっているかと思います。
```
├ bin
│　└ app-cdk.ts
├ lib
|  └ app-cdk-stack.ts #ECS他
|  └ ecr-cdk-stack.ts #ECR
|  └ pipline-cdk-stack.ts #Codeシリーズ  
...
```

私が試した際、CDKのバージョンは`2.98.0`でしたが、`app-cdk-stack`のデプロイ時に下記同様のエラーになったので、以下を追記したりして回避しました。

https://github.com/aws/aws-cdk/issues/26307


```diff_typescript:app-cdk-stack.ts
...

+ const cfnService = this.fargateService.service.node.defaultChild as CfnService;
+ cfnService.addPropertyDeletionOverride('DeploymentConfiguration.Alarms');

...

+ this.greenTargetGroup.configureHealthCheck({
+        healthyThresholdCount: 2,
+        unhealthyThresholdCount: 3,
+        timeout: Duration.seconds(10),
+        interval:Duration.seconds(11)
+      });
...
```

次にパイプラインです。

ビルド時にlatestではなく、タグ付けをしたかったので`buildspec.yml`を一部変更しました。

https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-env-ref-env-vars.html

```diff_yaml:buildspec_docker.yml
version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 18
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $IMAGE_REPO_URI
+     - IMAGE_TAG=$(echo $CODEBUILD_BUILD_NUMBER)

build:
  commands:
      - cd ./my-app
      - echo Build started on `date`
      - echo Building the Docker image...
      - docker build -t myapp:$IMAGE_TAG .
      - docker tag myapp:$IMAGE_TAG $IMAGE_REPO_URI:$IMAGE_TAG

  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker push $IMAGE_REPO_URI:$IMAGE_TAG
      - echo Writing image definitions file...
      - printf '[{"name":"my-app","imageUri":"%s"}]' $IMAGE_REPO_URI:$IMAGE_TAG > $CODEBUILD_SRC_DIR/imagedefinitions.json
+     - echo Writing image detail file...
+     - printf '{"ImageURI":"%s"}' $IMAGE_REPO_URI:$IMAGE_TAG > $CODEBUILD_SRC_DIR/imageDetail.json

artifacts:
    files:
      - imagedefinitions.json
+     - imageDetail.json
+     - appspec.yaml
+     - taskdef.json
```
`imagedefinitions`では"imageUri"ですが、`imageDetail`では"ImageURI"なんですよね...
スペルミスで微妙に時間が溶けました。(いや、ちゃんと読め)

https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/file-reference.html

`pipeline-cdk-stack.ts`も一部追記です。

```diff_typescript:pipeline-cdk-stack.ts
...

    pipeline.addStage({
      stageName: 'Deploy-Test',
      actions: [
        new codepipeline_actions.EcsDeployAction({
          actionName: 'deployECS',
          service: props.testAppFargateService.service,
+          input: dockerBuildOutput,
        }),
      ]
    });

...
    pipeline.addStage({
      stageName: 'ECS-Deploy-Prod',
      actions: [
        new codepipeline_actions.ManualApprovalAction({
          actionName: 'Approve-Prod-Deploy',
          runOrder: 1
        }),
        new codepipeline_actions.CodeDeployEcsDeployAction({
          actionName: 'BlueGreen-DeployECS',
          deploymentGroup: prodEcsDeploymentGroup,
+          appSpecTemplateInput: dockerBuildOutput,
+          taskDefinitionTemplateInput: dockerBuildOutput,
+          containerImageInputs: [{
+            input: dockerBuildOutput,
+            taskDefinitionPlaceholder: 'IMAGE_NAME',
+          }],
          runOrder: 2
        })
      ]
    });

...

```
合わせて、`taskdef.json`の"image"の部分をプレースホルダに変えます。
```diff_json:taskdef.json
+ "image": "<IMAGE_NAME>"
```
結果✨
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821082/d2cb5a21-7231-9b19-a63e-9b909f19dde0.png)

---

クラメソ様のこの記事と、BlackBeltの資料が分かりやす過ぎて涙涙です😭

https://dev.classmethod.jp/articles/ecs-deploytype-files/

https://pages.awscloud.com/rs/112-TZM-766/images/20210126_BlackBelt_CodeDeploy.pdf