ECSのawslogsでロググループ名がaws/始まりだとコンテナが起動しない

  • AWS
  • ECS
  • CloudWatch

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

何が起きたか

ECSのタスク定義をCDKで組んでたら、タスクが起動する前にコンテナが立ち上がらなくなった。イベント欄に出てたのはこれ。

CannotStartContainerError: Error response from daemon: failed to initialize logging driver: failed to create Cloudwatch log stream: InvalidParameterException: Log groups starting with AWS/ are reserved for AWS. status code: 400, request id: xxxxxxxx-xxxx

該当のコードはこう。

logConfiguration: {
logDriver: "awslogs",
options: {
"awslogs-group": `aws/ecs/${definition.name}`,
"awslogs-region": stack.region,
"awslogs-stream-prefix": "ecs"
},
},

原因

CloudWatch Logsのロググループ名は aws/ で始まる名前を予約済みとして弾く仕様になっている。AWSの公式ドキュメント(CreateLogGroup)にもガイドラインとして「Log group names can’t start with the string aws/」と明記されている。

エラーメッセージ自体は AWS/ と大文字で出てるけど、実際にコード側で指定してたのは小文字の aws/ecs/...。つまりこのチェックは大文字小文字を区別しないらしい。

ECSでは logs.LogGroup を明示的にCDKで作らず awslogs-group オプションだけ渡すと、ECSエージェントが実行時にロググループを自動作成しようとする。なのでこの手の命名ミスはデプロイ時のCloudFormationでは弾かれず、実際にタスクが起動するタイミングで初めて失敗する。

対処

プレフィックスを aws/ を含まない名前に変えるだけで直る。

logConfiguration: {
logDriver: "awslogs",
options: {
"awslogs-group": `my/ecs/${definition.name}`,
"awslogs-region": stack.region,
"awslogs-stream-prefix": "ecs"
},
},

my/ に限らず、app/ecs/... や先頭スラッシュだけの /ecs/... でも問題ない。

補足

CDKで new logs.LogGroup(...) を先に作ってARNを渡す構成にしてれば、ロググループ名のバリデーションはCloudFormationのデプロイ時点(cdk deploy)で弾かれてもっと早く気づけたはず。awslogs-group オプション直書きだと型チェックも構文チェックも通ってしまうので、命名規則はコード側で気をつけるしかない。