【備忘録】AWS ECS  Blue / Green Deploy 実現のために学んだこと

# ざっくりまとめた図

以下は各機能やファイルがどのように連携するのかを自分なりにまとめた図です。
これから ECS Blue / Green Deploy に着手する方の助けになれば幸いです🙇‍♂️

![CodePipeline-Flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141934/9ad8206b-d9db-c587-3388-bb2030c29942.png)

---

# はじめに

本投稿では私自身が AWS ECS の Blue / Green Deploy を実現できるようになるために学んだことを備忘録として投稿させていただきます。

## 前提知識

- ECSのデプロイはCodePipelineで自動化していた(Blue / Green は利用してない)

## 背景
- エンドユーザが新しいバージョンのアプリを操作可能となる前に本番環境で動作確認できるようにしたかった
- ECS Blue / Green Deploy であれば容易に実現可能だと思った

---

# 学習

## ECS  Blue / Green Deploy の 学習に参考としたサイト

以下のサイトでは「80ポートでリクエストを受け付けるNginxコンテナ を ECS Blue / Green Deploy する手順」が解説されてます。

- [CodePipelineからECSにBlue/Greenデプロイする ｜ DevelopersIO](https://dev.classmethod.jp/cloud/aws/codepipeline-ecs-codedeploy/)
- [チュートリアル: Amazon ECR ソースと、ECS と CodeDeploy 間のデプロイでパイプラインを作成する \- CodePipeline](https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/tutorials-ecs-ecr-codedeploy.html)
- [Amazon ECS CodeDeploy IAM ロール \- Amazon Elastic Container Service](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/codedeploy_IAM_role.html)
- [CodeDeploy を使用した Blue/Green デプロイ \- Amazon Elastic Container Service](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/deployment-type-bluegreen.html)

## 自分が知らなかった機能(ワード)

これまでの ECS Deploy では利用してなかった

- SourceArtifact
- BuildArtifact
- appspec.yaml
- taskdef.json
- imageDetail.json

という機能(ワード)が出てきたため、調べつつ 環境構築を行いました。

## 理解

機能(ワード) | 自分の理解
--- | ---
SourceArtifact | CodeCommit で Source に含まれるファイル(?)。
BuildArtifac | CodeBuild で `artifacts ` として出力したファイル(?)。
appspec.yaml | ECSサービスに含めるタスク定義の設定を記述したファイル<br>事前に作成しておき、ソースコードと一緒にCodeCommitへプッシュしておく
taskdef.json | デプロイするタスク定義の設定を記述したファイル<br>事前に作成しておき、ソースコードと一緒にCodeCommitへプッシュしておく
imageDetail.json | デプロイするタスク定義で利用するコンテナイメージが記載されたファイル<br>CodeBuildのビルド成果物として出力させる

> 補足：
> (?)部分は自分でも理解が怪しいと思っている箇所です。
> 誤りがありましたらご指摘いただけると助かります

---

# 実践

参考サイトを参照しつつ、以下のことを行った。

1. リポジトリに`appspec.yaml`を追加する
2. リポジトリに`taskdef.json`を追加する
3. `buildspec.yml`で`imageDetail.json`を出力するようにする

## 1. リポジトリに`appspec.yaml`を追加する

ECSを利用していれば難しくない準備です。
`appspec.yaml`を作成して、リポジトリ直下に配置しました。

```
/xxx
  |-- appspec.yaml
```

### `appspec.yaml`のサンプル

以下はAWSのチュートリアルに記載されていた`appspec.yaml`です。
`ContainerName`と`ContainerPort`を適切な値に変更します。
`<TASK_DEFINITION>`については変更せず、そのままにします。

```yaml:appspec.yaml
version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: <TASK_DEFINITION>
        LoadBalancerInfo:
          ContainerName: "sample-website"
          ContainerPort: 80
```

## 2. リポジトリに`taskdef.json`を追加する

Blue / Green Deploy を行う前は作成してなかったため、少し手間かと思いましたが、タスク定義のコンソールにjsonを表示する機能があったため、あまり手間はかかりませんでした。

### `taskdef.json`の作り方

#### 1. タスク定義のコンソールからjsonをコピペする

![CodePipeline-TaskDefinition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141934/82c2f6c2-dabd-44e6-e914-43e64671a295.png)

#### 2. json内の`image`の値を`"<IMAGE1_NAME>"`に書き換える

修正前

```json:taskdef.json
"image": "xxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/xxxxx:latest",
```

修正後

```json:taskdef.json
"image": "<IMAGE1_NAME>",
```


#### 3. `taskdef.json`という名前でリポジトリ直下に保存する

```
/xxx
  |-- appspec.yaml
  |-- taskdef.json
```


## 3. `buildspec.yml`で`imageDetail.json`を出力するようにする

`buildspec.yml`を修正して、CodeBuildでのビルド時に`imageDetail.json`を出力するようにしました。
Blue / Green Deploy を利用しないケースも想定して、通常のDeployに利用する`imagedefinitions.json`の出力も残しました。

### `imageDetail.json`のサンプル

```yml:buildspec.yml
version: 0.2

env:
  # 省略
phases:
  install:
    # 省略
  pre_build:
    commands:
      - # 省略
      - REPOSITORY_URI=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/${IMAGE_NAME}
      - IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - # 省略
  build:
    commands:
      # 省略
  post_build:
    commands:
      - # 省略
      - echo "[{\"name\":\"${IMAGE_NAME}\",\"imageUri\":\"${REPOSITORY_URI}:${IMAGE_TAG}\"}]" > imagedefinitions.json
      - printf '{"Version":"1.0","ImageURI":"%s"}' $REPOSITORY_URI:$IMAGE_TAG > imageDetail.json
artifacts:
    files:
      - imagedefinitions.json
      - imageDetail.json
```

---

# まとめ

以上の準備を行った上で、参考サイトの手順に従って Blue / Green Deploy の環境構築を行ったところ、ECS Blue / Green Deploy を実現することができました。

以下は各機能やファイルがどのように連携するのかを自分なりにまとめた図です。
これから ECS Blue / Green Deploy に着手する方の助けになれば幸いです🙇‍♂️

![CodePipeline-Flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141934/9ad8206b-d9db-c587-3388-bb2030c29942.png)