概要
AWSでデプロイ時、ECSタスクで以下のエラーが出ました。
こちらについて解決できたので紹介します。
CannotStartContainerError: Error response from daemon: failed to initialize logging driver: failed to create Cloudwatch log stream: ResourceNotFoundException: The specified log group does not exist.
前提
以下のようにpython側で実装。
log-sample-group
ロググループの中に手動でsample-stream
ログストリームを作成、デプロイをしました。
"handlers": {
"watchtower": {
"level": "DEBUG",
"class": "watchtower.CloudWatchLogHandler",
"boto3_session": autorefresh_session,
"log_group": "log-sample-group",
"stream_name": "sample-stream",
"formatter": "aws",
},
#...略...#
watchtower
とは、PythonのログをAmazon Web Services (AWS)のCloudWatch Logsに送信するためのライブラリ。logging
モジュールを使用して、ログをCloudWatch Logsに直接送信することができるので便利です。
しかし、デプロイすると上述のエラー。
エラーメッセージは、ECS(Docker)がCloudWatchのログストリームを作成しようとしたときに、指定したロググループが存在しない、と言っています。
ちゃんと指定したロググループとログストリームを作成しているのでちゃんとログが出力されるはずなのに...
おかしいなぁと思っていたら、原因はタスク定義の方でした。
原因と解決方法
タスク定義JSONを以下のようにしていたのですが、単純に"awslogs-group": "/aws/ecs/docker_sample"
のロググループ作成漏れでした。
{
"executionRoleArn": "arn:aws:iam::xxx/xxxx",
"taskRoleArn": "arn:aws:iam::xxx/xxxx",
"containerDefinitions": [
{
"name": "Web",
"image": "<IMAGE1_NAME>",
"logConfiguration": {
"logDriver": "awslogs",
"secretOptions": null,
"options": {
"awslogs-group": "/aws/ecs/docker_sample",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "sample-stream"
}
},
"portMappings": [
{
"containerPort": 80,
"hostPort": 0,
"protocol": "tcp"
}
],
"essential": true
}
],
"requiresCompatibilities": ["EC2"],
"networkMode": null,
"cpu": "900",
"memory": "3400",
"family": "TaskSample-xxxxxxx"
}
基本的には、タスク定義の"awslogs-group": "/aws/ecs/docker_sample"
とWatchtowerライブラリで使用するロググループは無関係。
"/aws/ecs/docker_sample"
は、ECSタスク定義の一部として設定され、ECSタスク内で実行されるコンテナアプリケーションが生成するログ(標準出力や標準エラー出力に出力されるログ)をCloudWatch Logsに送信するための設定。
対して、Watchtowerライブラリは、Pythonのloggingモジュールを通じてアプリケーションが生成するログをCloudWatch Logsに送信するためのツール。これは上述の通り別ファイルで設定します。
同じCloudWatch Logsのロググループに送信することも可能と言えば可能ですが、ECSタスクのログとアプリケーションのログが同じロググループに集約されてしまうので、わかりづらくなるかと思います。一般的にはロググループを分けるのが推奨されるでしょう。