仕事で直面したECS・ECRトラブルその1

仕事でいくつかECS・ECRについて触れる機会があったので以下ユースケースごとにまとめて共有。
その２以降は別途また直面したら書いていく。

## ecs execができない

**解決の近道: 権限周りを怪しむ**

[参考: ecs execute command が失敗した際に調査したこと](https://kenzo0107.github.io/2021/07/26/2021-07-27-ecs-execute-command-agent-not-running/)
[参考: [小ネタ]ECS ExecのenableExecuteCommandを有効にしようとするとエラーになってしまう](https://dev.classmethod.jp/articles/ecs-exec-enableexecutecommand-error/)
[Amazon ECS で発生したエラー「ExecuteCommand オペレーションを呼び出す際にエラーが発生しました (TargetNotConnectedException)」を解決するにはどうすればよいですか?](https://repost.aws/ja/knowledge-center/ecs-error-execute-command)

自分の場合はexecしようとしたところ

```
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.
```
というエラーメッセージが表示された。
対象のクラスターでは他にもサービスがあり、それらで起動しているタスクに対してはexecできる。
なので、当該タスクのみ何か異常があると判断して調査を開始した。

注目するべきは`The execute command failed because execute command was not enabled`の部分。
調べるとECS Service で `enableExecuteCommand = true` が返ってきていないことが疑われるとのこと。
なので

```
$ aws ecs describe-services --cluster example-cluster --services example-service | jq '.services[].enableExecuteCommand'
$ aws ecs describe-tasks --cluster example-cluster --tasks task_id | jq '.tasks[].enableExecuteCommand'
```

こちらのコマンドで確認したところ`aws ecs describe-services` の時点でFalseが返ってきた。
よってこちらをTrueにしないといけないので

```
$ aws ecs update-service \
    --cluster [クラスター名] \
    --service [サービスー名] \
    --enable-execute-command
```

こちらでサービスをUpdateして`enableExecuteCommand = true` にする。
上記のコマンド自体は問題なく実行され、Trueにもなった。
しかし

`An error occurred (TargetNotConnectedException) when calling the ExecuteCommand operation: The execute command failed due to an internal error. Try again later.`

エラーメッセージが上記のように変わっただけで解決しない。
調べるとタスクロール、またはタスク実行ロールが怪しいとのこと。
該当サービス(タスク)のタスク定義を確認すると、タスクロールに**ecsTaskExecutionRole(タスク実行ロール)**が設定されていた。
これでは当然ダメなので**ecsTaskRole**を割り当てるようにタスク定義のリビジョンを更新し、新しいデプロイを強制してタスクを切り替えた。
結果、無事execできるようになった。

## ECRのイメージのタグの付替え

何故必要だったか?: コード修正前後で比較する作業があったが誤って修正前でやる作業を行う前に環境を更新してしまったから

自分のチームでの運用は

localブランチ → master(=Dev環境)ブランチ(間にVx.x.xとバージョンブランチを作るときもある) → ステージングブランチ → 本番ブランチ

とMergeしていく。
Mergeごとにその環境のイメージがActionsによってECRへpushされ、最新のイメージには`latest`のタグ+環境判別タグ(ex. `staging`)がつくので、
その後デプロイをすれば環境が更新されるというものである。
ECRイメージのタグ付替えは以下の通りのコマンドで実行できる。

```
MANIFEST=$(aws --profile プロファイル ecr batch-get-image --repository-name リポジトリ名 --image-ids imageTag=タグ付け先のイメージのタグ --output json | jq --raw-output --join-output '.images[0].imageManifest')

aws --profile プロファイル ecr put-image --repository-name リポジトリ名 --image-tag 追加するタグ名 --image-manifest "$MANIFEST"
```

やっていることはタグを付けたいイメージをgetしてきて、追加するタグをputで更新するだけ。
しかし

```
aws --profile プロファイル ecr batch-get-image --repository-name リポジトリ名 --image-ids imageDigest=ダイジェストの値 --query 'images[].imageManifest' --output text > manifest.json

aws --profile プロファイル ecr put-image --repository-name リポジトリ名 --image-tag 追加するタグ名 --image-manifest file://manifest.json
```

こちらのやり方も手段としてはある。
ただし、こちらはタグを追加したいイメージをコピーし、新たなイメージを作成してその上でそこにタグを追加する手法。
実はChatGPTにタグの付替えをしたいと質問したところ返ってきたのがこの手法であり、既存のイメージに対して直接タグを追加する手段はないと回答された。
しかし実際は先述の通りの手法が[公式のドキュメント](https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/image-retag.html)に書いてある。
ChatGPTを過信してはいけないケースに遭遇してしまったわけだが、効果か不幸か管理リポジトリの中にはタグがついていない過去イメージもあり、結果としてChatGPT案も有効ではあった。

今回のこちらの一連の過程で発覚した点は以下の通り。

今回のこちらの一連の過程で発覚した点は以下の通り。

**問題点1: 最新のイメージにのみタグ付けがされるが、過去のイメージに適切なタグが付いていなくて付替えがスムーズに行かない**

**問題点2: そもそも環境のロールバックをイメージのタグ付替えという作業でやることについての可用性や複雑性の問題**

→

**今後考えられる解決点1: Merge時にActionsで環境変数をタスク定義にPush、タスク定義をその環境変数で更新する**

**今後考えられる解決点2: 1つ前のイメージには「previous」等のタグを付けるか、すべてのimageにUNIXではなく、通常のタイムスタンプのタグをつける**

受け持っているタスク的に余裕がなく、こういうシステム運用・保守管理に手を入れられない状態が続いているが改善はどこかで必ずやらないといけない。