ecspressoで作ったサービスでexecute-commandを使えるようにする

普段からECSを使っている方なら知っていると思いますが、2021/03/16(JST)にECSの管理下にあるコンテナに入ることができるようになりました :tada: 
特にFargateでは、以前はなかなか回りくどい方法をとらないといけなかったのが、公式に機能が提供されたインパクトが大きく、界隈が盛り上がっていたように思います。

https://aws.amazon.com/jp/about-aws/whats-new/2021/03/amazon-ecs-now-allows-you-to-execute-commands-in-a-container-running-on-amazon-ec2-or-aws-fargate/

コンテナに入るコマンド `aws ecs execute-command ...` を使えるようにする方法は、公式ドキュメント他多くの情報があります。

https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html

https://dev.classmethod.jp/articles/ecs-exec/

ところで、私は普段ECSでデプロイを行う際に __ecspresso__ を使っています。

https://github.com/kayac/ecspresso

ecspressoの導入や使い方についてはREADMEに詳しく書いてあるので省略しますが、execute-commandを使えるようにするのに少し躓いたので、有効化する方法を紹介します。

なお、以下は2021/04/09現在の最新版である __v1.4.0__ での事例であり、バージョンアップによって解消しているかもしれないのでご了承ください。

# (2021/04/13追記) v1.5.0でexecute-commandに対応しました :sparkles: 

https://sfujiwara.hatenablog.com/entry/ecspresso-v1.5

ということで、__v1.5.0__以降のバージョンを使いましょうｗ

# GUIでサービスを作る場合、execute-commandを有効化できない

2021/04/09現在、GUIでは設定できないようです。aws-cliで設定すればいいのですが、ecspressoの設定ファイルにサービスを定義する設定ファイルが含まれているので、そのファイルにexecute-commandを有効にする設定を追加すれば良さそうな気がしますよね。

# 設定を追加してデプロイするも、有効にならず

execute-commandが有効なサービスでは、サービス定義に `"enableExecuteCommand": true` という情報が含まれているので、サービス定義ファイルにそのまま追加してデプロイしてみます。

```diff_json:ecs-service-def.json
{
  "deploymentConfiguration": {
    "deploymentCircuitBreaker": {
      "enable": false,
      "rollback": false
    },
    "maximumPercent": 200,
    "minimumHealthyPercent": 100
  },
  "desiredCount": 1,
  "enableECSManagedTags": true,
+ "enableExecuteCommand": true,
  "launchType": "FARGATE",
  (以下省略)
}
```

デプロイが完了したら、execute-commandを実行してみましょう。

```sh
$ aws ecs execute-command --cluster CLUSTER_NAME --task TASK_ID --interactive --command sh
```

```:実行結果
The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.


An error occurred (InvalidParameterException) when calling the ExecuteCommand operation: The execute command failed because execute command was not enabled when the task was run or the execute command agent isn’t running. Wait and try again or run a new task with execute command enabled and try again.
```

おや？有効になっていないぞ… :thinking: 
aws-cliでサービスの詳細を出力しても、 `"enableExecuteCommand": true` になっていません。

```sh
$ aws ecs describe-services --cluster CLUSTER_NAME --services SERVICE_NAME
```

```jsonnet:実行結果（抜粋）
            ...
            "enableECSManagedTags": true,
            "propagateTags": "NONE",
            "enableExecuteCommand": false # trueになっていてほしい
        }
    ],
    "failures": []
}
```

おそらくですが、ecspressoで使われている `aws-sdk-go` がexecute-commandに対応していないからだと思います。SDKやGoの事情はあまり詳しくありませんが、単にSDKのバージョンの問題なのかもしれません。

# aws-cliで有効化する

対応していないものはしょうがないので、aws-cliでexecute-commandを有効化します。

```sh
$ aws ecs update-service --cluster CLUSTER_NAME --service SERVICE_NAME --enable-execute-command
```

```jsonnet:実行結果（抜粋）
        ...
        "enableECSManagedTags": true,
        "propagateTags": "NONE",
        "enableExecuteCommand": true
    }
}
```

設定は有効になりましたが、execute-commandが使えるようになるのは次に起動するタスクからです。すぐに使いたい場合は、`--force-new-deployment` というオプションを付けてupdate-serviceを実行するとタスクを作り直してくれるので、新しく作成されたタスクでexecute-commandを実行できます :clap: 

```sh
$ aws ecs execute-command --cluster CLUSTER_NAME --task NEW_TASK_ID --interactive --command sh
```

```:実行結果
The Session Manager plugin was installed successfully. Use the AWS CLI to start a session.


Starting session with SessionId: ecs-execute-command-0123456789abcdef
/ #
```

# 最後に

ecspressoもすぐに対応されるんじゃないかと思うので、気長に待ちましょう :tea: 

余談ですが、TerraformのAWSプロバイダはすでに対応されています。早いですね〜。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_service#enable_execute_command