ECS用のデプロイツール:ecspressoの使い方について5ステップで説明してみる

## はじめに
今回紹介する**ecspresso**とは、ECS専用の管理・デプロイツールです。

ecspressoの利点は、ECSとそれ以外の管理方法を明確に分離できる点です。一般に「アプリケーションのデプロイ頻度>>他リソース(ex.EC2)のデプロイ頻度」より、管理方法が異なった方が都合が良いです。

今回はecspressoの使い方について5stepに分けて解説していきます。

:::note warn 
ECRのレポジトリやECSのクラスターやコンテナインスタンスがあらかじめ作成されている前提でお話しします。
:::

## 【step1】 ecspressoの導入方法
### ecspressoのインストール
#### ローカル環境
リリースバージョンからのインストール例はこちらです。

```bash 
$ curl -L https://github.com/kayac/ecspresso/releases/download/v2.2.4/ecspresso_2.2.4_linux_amd64.tar.gz -o ecspresso.tar.gz 
$ tar -zxvf ecspresso.tar.gz -C /usr/local/bin 
$ sudo chmod +x /usr/local/bin/ecspresso 
$ rm ecspresso.tar.gz
```

リリースバージョンは以下から確認してください。

https://github.com/kayac/ecspresso/releases


またHomebrewやasdf、aquaでも以下のようにインストールできます。
```bash 
$ brew install kayac/tap/ecspresso

$ asdf plugin add ecspresso
$ asdf install ecspresso 2.2.4
$ asdf global ecspresso 2.2.4

$ aqua g -i kayac/ecspresso
```

#### Docker環境
Dockerで環境構築している場合は、Dockerfileに以下４行を追記してリビルドすれば良いです。（リリースバージョンからのインストールとコマンドは同じです。）

```Dockerfile
# ecspresso のダウンロードとインストール
RUN curl -L https://github.com/kayac/ecspresso/releases/download/v2.2.4/ecspresso_2.2.4_linux_amd64.tar.gz -o ecspresso.tar.gz \
    && tar -zxvf ecspresso.tar.gz -C /usr/local/bin \
    && chmod +x /usr/local/bin/ecspresso \
    && rm ecspresso.tar.gz
```

### AWSのcredentialの設定
環境変数(AWS_REGION等)や設定ファイル(`.aws/config`, `.aws/credentials`)を用いてcredentialの設定を行ってください。(基本はほぼTerraformと同じです。)

## 【step2】 ecspressoの設定ファイル
ecspressoの設定ファイルは以下のように記述します。

```yml:config.yml
region: ap-northeast-1
cluster: クラスター名
service: サービス名
service_definition: ecs-service-def.json
task_definition: ecs-task-def.json
timeout: 15m0s
plugins: []
appspec: null
```

Terraformで定義した変数を使いたい場合は`plugins`に`tfstate`を指定します。

```yml:config.yml 
region: ap-northeast-1
cluster: クラスター名
service: サービス名
service_definition: ecs-service-def.json
task_definition: ecs-task-def.json
timeout: 15m0s
plugins:
  - name: tfstate
    config:
      path: "{適切なパス}"/terraform.tfstate
appspec: null
```
適切なパスを設定するために変数を使いたい場合は、環境変数を使えば良いです。
例えばdevやprdで環境を分離している場合は以下のように指定します。

```bash 
$ export ENV=dev
```

```yml:config.yml
plugins:
  - name: tfstate
    config:
      path: "{適切なパス}"/{{ must_env `ENV`}}/terraform.tfstate
```


## 【step3】 サービスの定義
サービスは`ecs-service-def.json`に定義します。

ECSonEC2のサービスにおける具体的な`ecs-service-def.json`の例はこちらです。

```json:ecs-service-def.json
{
  "serviceName": "サービス名", 
  "taskDefinition": "タスク名",
  "launchType": "EC2", 
  "schedulingStrategy": "REPLICA",
  "deploymentConfiguration": {
    "maximumPercent": 200,
    "minimumHealthyPercent": 100,
    "deploymentCircuitBreaker": {
      "enable": true,
      "rollback": true
    }
  },
  "desiredCount": 1 
}
```

Fargateの場合は`"launchType": "FARGATE"`とし、別途`networkConfiguration`(VPC、subnet、セキュリティグループ)を設定する必要があります。

## 【step4】 タスクの定義
タスクは`ecs-task-def.json`に定義します。

ECSonEC2のサービスにおける具体的な`ecs-task-def.json`の例はこちらです。

```json:ecs-task-def.json
{
  "family": "タスク名",
  "networkMode": "bridge",
  "executionRoleArn": "タスク実行ロール名",
  "taskRoleArn":  "タスクロール名",
  "containerDefinitions": [
    {
      "name": "ECRのリポジトリ名",
      "image": "ECRのリポジトリのURl:{{ must_env `IMAGE_TAG`}}",
      "cpu": 256,
      "memory": 512,
      "essential": true,
      "portMappings": [
        {
          "containerPort": 80,
          "hostPort": 80,
          "protocol": "tcp"
        }
      ],
    }
  ],
  "requiresCompatibilities": ["EC2"],
  "cpu": "256",
  "memory": "512"
}
```

イメージタグ情報は環境変数で定義すると、管理が楽になります。

```bash 
$ export IMAGE_TAG={タグ情報}
```

またタスク実行ロールやECRをTerraformで作っている場合は`tfstate`を使って以下のように書くことができます。
```
"executionRoleArn": "{{ tfstate `{リソース名}.arn`}}",
```
上記のように`tfstate`を使えばハードコーディングする情報が減り、保守しやすくなります。

リソースについては以下のTerraformのコマンドで簡単に確認できます。

```bash 
#リソース全体の確認
$ terraform state list -state=terraform.tfstate
#特定のリソースの詳細
$ terraform state show -state=terraform.tfstate　{特定のリソース名}
```

また詳細な`tfstate`の使い方は、以下の記事がわかりやすいです。

https://zenn.dev/fujiwara/articles/ecspresso-20201219

余談ですが、ややこしいタスク実行ロールとタスクロールは以下の記事でわかりやすく解説されています。

https://dev.classmethod.jp/articles/ecs_ec2_iamrole/

https://zenn.dev/fdnsy/articles/d42db2c989a637

## 【step5】 デプロイ
デプロイ事項は以下のコマンド`ecspresso deploy --dry-run`で確認できます。

```bash 
$ ecspresso deploy --dry-run --config="config.yml"
```

またAWS上のECSとローカルの設定の差分のみを確認したい場合は、`ecspresso diff`コマンドを用いて確認します。（イメージタグだけ変えたい時などの確認で便利）

```bash 
$ ecspresso diff --config="config.yml" 
```

確認が終了したら`--dry-run`オプションを消してデプロイを実行します。
```bash 
$ ecspresso deploy --config="config.yml"
```

ECSのクラスターに紐づいているコンテナインスタンスで、タスクが実行できていればOKです！！

（AWSのGUIから確認できます。心配な方はタスク定義に適切なヘルスチェックを導入することをお勧めします。）

## おわりに
ecspressoの使い方をまとめました。

ecspressoはとても使いやすく、アプリケーションの運用で便利になるケースが多々あるので、導入してみてはいかがでしょうか。

https://github.com/kayac/ecspresso