【備忘録】AWS ECS Blue / Green Deploy で 複数コンテナを含んだ ECS サービス / タスク を更新する

## はじめに

以前、CodePipelineを利用した「ECS Blue / Green Deploy」を実現したのですが、その後 タスク定義の構成を変更（1タスク定義内に1コンテナを配置→2コンテナを配置）するにあたって必要だった設定について備忘録のために投稿させていただきます。

### 以前の投稿
[【備忘録】AWS ECS Blue / Green Deploy 実現のために学んだこと \- Qiita](https://qiita.com/NaokiIshimura/items/86ec84a13a6ceb831bba)

### 本投稿で説明しないこと

本投稿では、**実現したいこと**のために必要なCodeBuild/Deploy設定の追加・変更・差分についてのみ記載させていただきます。
「ECS Blue / Green Deploy」の基本的な構築方法については、**以前の投稿**に記載しているため、省略させていただきます。

- CodePipeline の設定方法
- CodeBuild の設定方法
- CodeDeploy の設定方法
- appspec.yaml の記述方法
- taskdef.json の記述方法
- buildspec.yml の記述方法 など

---

## 実現したいこと

1つのタスク定義内に複数コンテナ（webサーバとappサーバ）が含まれている構成のECSサービス/タスクに対して、「ECS Blue / Green Deploy」を実現したい。

### ECSの構成

ECSの構成イメージは以下になります。

- 1つのタスク定義内に複数コンテナ（webサーバとappサーバ）が含まれている

![Untitled Diagram-Page-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141934/b2a2fcfb-647d-27b9-5a11-aa76919e955b.png)


### CodePipelineの構成

CodePipelineの構成イメージは以下になります。

- Buildステージでは、webサーバとappサーバのコンテナイメージをビルドする
- Deployステージでは、ビルドしたコンテナイメージをECSへデプロイする

![Untitled Diagram-Page-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141934/e2ed70d8-2e4c-1f56-198c-364980d6c509.png)

---

## 実現するための設定方法

### もくじ

1. CodeBuildで、各ステップに適切な出力アーティファクト名を付ける
2. CodeDeployで、入力アーティファクトに、CodeBuildの出力アーティファクトを指定する
3. CodeDeployで、入力アーティファクト毎に、プレースホルダー文字を設定する
4. taskdef.jsonで、プレースホルダー文字を指定する

---

### 1. CodeBuildで、各ステップに適切な出力アーティファクト名を付ける

各コンテナをビルドするステップの**出力アーティファクト**に適切な名前をつけておきます

* 1-1. webサーバのビルドステップの**出力アーティファクト**にアーティファクト名（例：web_build_output）を設定する
* 1-2. appサーバのビルドステップの**出力アーティファクト**にアーティファクト名（例：app_build_output）を設定する


![ecs-blue-green-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141934/e1176305-eef6-10a5-3156-7c0767c528f6.png)
![ecs-blue-green-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141934/bf5fe2bb-cdfb-4513-2c61-eda681be4a81.png)

---

### 2. CodeDeployで、入力アーティファクトに、CodeBuildの出力アーティファクトを指定する

ビルドステップの出力アーティファクト名を**入力アーティファクト**として利用するように指定します。

#### 入力アーティファクト

* 2-1. webサーバの**出力アーティファクト（例：web_build_output）**を指定する
* 2-2. appサーバの**出力アーティファクト（例：app_build_output）**を指定する

---

### 3. CodeDeployで、入力アーティファクト毎に、プレースホルダー文字を設定する

#### タスク定義の動的な更新イメージ

また、**タスク定義の動的な更新イメージ**で、各ビルドステップの**出力アーティファクト**と**プレースホルダ文字**を指定します。

* 3-1. **入力アーティファクトを持つイメージの詳細**に、**webサーバの出力アーティファクト（例：web_build_output）**を指定する
* 3-2. **タスク定義のプレースホルダー文字**に、プレースホルダ（例：WEB_IMAGE_NAME）を設定する

* 3-3. **入力アーティファクトを持つイメージの詳細**に、**appサーバの出力アーティファクト（例：app_build_output）**を指定する
* 3-4. **タスク定義のプレースホルダー文字**に、プレースホルダ（例：APP_IMAGE_NAME）を設定する

![ecs-blue-green-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141934/c9c97416-87cd-a212-7654-93066b869aeb.png)

![ecs-blue-green-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141934/fb1f6977-0253-91c2-df2e-adbf5cd43ef6.png)

---

### 4. taskdef.jsonで、プレースホルダー文字を指定する

**taskdef.json**で、イメージ名を指定する項目に**CodeDeploy**で設定した、プレースホルダ（例：WEB_IMAGE_NAME、APP_IMAGE_NAME）を指定します。こうすることで、DeployステージでECSタスクを更新する際に、Buildステージでビルドされたコンテナイメージが利用されるようになります。

* 4-1. **taskdef.json**で、webサーバのイメージ名にプレースホルダー文字（例：\<WEB_IMAGE_NAME\>）を指定する
* 4-2. **taskdef.json**で、appサーバのイメージ名にプレースホルダー文字（例：\<APP_IMAGE_NAME\>）を指定する

```json:taskdef.json
... (省略)
"containerDefinitions": [
  ... (省略)
  {
    "name" : "web"
    "image": "<WEB_IMAGE_NAME>",
    ... (省略)
  },
  {
    "name" : "app"
    "image": "<APP_IMAGE_NAME>",
    ... (省略)
  }
  ... (省略)
]
... (省略)
```

---

## 注意事項

すごく基本的なことなのですが、構築中に「アーティファクト名」や「プレースホルダー文字」をコピペミスしたことで、うまくデプロイされずハマってしまったことがありました orz 

着手する前に簡単に設定する名称を整理しておいたほうが、ささいなミスを減らせるかもしれません orz
以下は本投稿で用いた名称です。

### webサーバ

役割 | 名前
--- | ---
ビルドステップ名 | WebBuild
ビルドステップの出力アーティファクト名 | web_build_output 
出力アーティファクトに対してつけたプレースホルダー文字 | WEB_IMAGE_NAME 

### appサーバ

役割 | 名前
--- | ---
ビルドステップ名 | AppBuild
ビルドステップの出力アーティファクト名 | app_build_output 
出力アーティファクトに対してつけたプレースホルダー文字 | APP_IMAGE_NAME