AWS ECS – CodePipeline + CodeDeploy での appspec / taskdef 関係のエラー

CODE DEPLOY で appspec をうまく書けずに試行錯誤していた。

# 設定

CodePiplineのDeployステージのアクション設定でプロバイダを AWS ECS(ブルー/グリーン)にしている前提

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/d2185955-5676-44ab-ad5b-7534694cd10f)

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/824b17c4-59c5-4f9a-abd1-d03255ab369d)


# デプロイ実行時のエラー

CodeBuildの「デプロイID」のページに表示されたエラー。こんなやつ。

<img width="1083" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/d9d07e74-8f10-46be-919b-2aa119853485">

## appspecファイルが見つからない

> An AppSpec file is required, but could not be found in the revision

レポジトリのトップに appspec.yml を置いてあるのにないと言われる

### 解決

buildspec.yml の artifacts に appspecファイルを指定すると解決した

```yml
artifacts:
  files:
    - appspec.yml
```

「Deploy ステージの 入力アーティファクトを Build にしている場合は
 Deployステージで 利用するファイルを artifacts で指定しておかなければいけない」と理解した (たぶん)


## 設定値のエラー？ (ではなかった)

> The deployment failed because the AppSpec file that specifies the deployment configuration is missing or has an invalid configuration.
> Could not parse or validate one of the resources in the app-spec.

最小限の項目を指定しているはずがエラーが発生した。

```yml
version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: <TASK_DEFINITION>
        LoadBalancerInfo:
          ContainerName: "container-name"
          ContainerPort: 8080
```

TASK_DEFINITION のプレースホルダの問題ではなさそう。
エラーで終了したデプロイIDのページで
***リビジョンの詳細 > アプリの仕様*** を見ると `<TASK_DEFINITION>` が新しいタスク定義のARNに展開されているのが分かった。

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/1d063706-839b-443e-ae4e-58f7863f485e)



後述するがYAMLの構文エラーや必須項目不足でもなさそう。
(その場合はそれぞれ別エラーが発生するので)

### 解決

ECS側のデプロイモードをCODE BUILD経由 ではなく ECSへの直接デプロイ(ローリングアップデート)にしてしまっていた。
作業途中で状態を切り替えていたまま忘れていたようだ。

ここでかなりハマったがようやくblue/greenデプロイが起動するようになった。

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/90a62817-dbce-4ff7-b823-cc7f6f758f9f)


## YAML構文のエラー


> The deployment failed because the AppSpec file that specifies the deployment configuration is missing or has an invalid configuration.
>  Failed to parse your appspec file. Please validate your appspec format and try again later.

YAML構文エラーのファイルを利用したところこのエラーが生じた

```yaml
XXX: YYY:
````


## テンプレートがパースできない

>  The deployment failed because the AppSpec file that specifies the deployment configuration is missing or has an invalid configuration. 
> The input AppSpec file is a not well-formed yaml. The template cannot be parsed.

項目の足りないYAMLを試してみたところこのエラーが生じた。

```yaml
version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
```

# デプロイ実行前のエラー

CodePipelineのDeployステージに表示されるエラー

そもそもデプロイが実行されないパターン
taskdef.json / appspec.yaml の記述に誤りがある場合などにエラーが発生していたようだ


こんなやつ

<img width="492" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/115efcbf-ad6e-4e5f-9f23-b20694c20051">

## 例1

> Exception while trying to read the AppSec artifact file from: Build.

存在しないファイルを appspec として指定した時にこのエラーが発生した

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/11d0efb1-a7c5-4a76-91c3-dc134c4fc829)

## 例

> Tags can not be empty.

taskdef.json のタグ指定を空で書いていたら

```
"tags": []
```

## 例

試しに taskdef.json を変えてみると

```
"tags": ["XXX"]
```

> Expected null

何…？

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/1e04a72d-5521-4209-a295-799772fa9a50)


そもそもtagsのプロパティを消してしまうことで対応した

## 例

taskdef.json のプレースホルダを解釈してくれない

> Container.image contains invalid characters.

```json
    "containerDefinitions": [
      {
        "image": "<IMAGE1_NAME>",
```

いったんプレースホルダをやめてECRイメージを直接指定することで対応した 

```json
    "containerDefinitions": [
        {
            "image": "**********.dkr.ecr.***********.amazonaws.com/**********:***",
```

だがこれも上に書いたのと同じでECSのデプロイモードを間違えていたせいだったかもしれない
(デプロイモード変更後はエラーが起こらなくなった)

## 例

以前に terraform apply で ECSサービスに紐づくタスク定義を更新しようとした時にこのエラーが起きたが CodeDeploy での実行時にも同じエラーが起きた。

>  Unable to update task definition on services with a CODE_DEPLOY deployment controller. Use AWS CodeDeploy to trigger a new deployment. 




# NOTE

- Codepipeline のトライ&エラーは1回あたり普通で10分とかかかる。途中から build ステージでは軽量な docker イメージをビルドするように差し替えて試した。 ( てきとうに alpine で )

後から気づいたがCodePipelineを通さずにCodeBuild単体でデプロイを実行できるモードもあるようなのでこれを活用にしても良いかも知れない。 appspec も直接エディタでコード内容を指定できるみたいだ。

<img width="1073" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/9741c914-e062-4aec-8247-724d9405aaad">


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura