ECSのタスク定義をCloudFormationで書いていて、ハマったところがあったのでメモしておきます。
事象
タスク定義内のコンテナ定義にて、LogConfigurationの値をawslogsにしたところ、作成されたタスク定義を起動しても、コンテナ起動に失敗してしまう。
詳細
ECSのログ出力設定には幾つかの方法が用意されていますが、基本的には awslogs
の設定を利用すると便利です。これは、コンテナ上の標準出力/エラー出力の内容を、CloudwatchLogsに連携してくれる、という設定となります。
なお、awslogsの設定を利用するには、ECSコンテナエージェントのバージョンが1.9.0以降である必要があります。
で、CloudFormationのテンプレートですと、コンテナ定義部分に以下みたく記載します。
LogConfiguration: LogDriver: "awslogs" Options: awslogs-create-group: true awslogs-group: "ecslog" awslogs-region: !Ref "AWS::Region" awslogs-stream-prefix: "sample"
Optionsに設定できるパラメータは、以下の公式マニュアルにて説明されています。
awslogs ログドライバーを使用する - Amazon Elastic Container Service
デフォルトでは、CloudwatchLogsグループを新規作成してくれないのですが、 awslogs-create-group
パラメータをtrueにすることで、タスク起動時に自動で作成してくれるようになります。
しかし、作成されたタスクは起動することができず、どうにも、CloudwatchLogsグループ作成の処理で失敗しているよう見えました。が、解決方法がなかなか分からなかった。
結論
結果から言ってしまうと、ECS Task execution Role
にCloudwatchLogsへのアクセス権限が不足していました。
ECSを触っていると、以下3種類のIAMロールが出てきます。
- ECS Container Instance の EC2 Instance Role
- いわゆる、EC2のIAM Role
- Container InstanceにIAM Policyを与えてくれる
- ECS Task execution Role
- ECS コンテナエージェントに付与されるロール
- デフォルトでは、IAMポリシー
AmazonECSTaskExecutionRolePolicy
が与えられており、ECRからのイメージpull権限等を持っている
- ECS Task Role
- タスクに付与されるロール
- タスク(コンテナ)で実行されているアプリケーションに利用される
てっきり、ECS Task RoleにCloudwatchLogsへのアクセス権限を与えれば良いと思っていたのですが、ECS Task execution Roleにも必要だった、という話です。
ECS Task execution Roleに、IAMポリシーCloudWatchAgentServerPolicy
を与えることで、タスクが正常に起動してくれました。
反省
原因特定まで時間かかったのですが、そもそもECS Containerのログを見に行けば、しっかり原因が書いてありました。
ECS Container上の「/var/log/ecs/ecs-agent.log」には、以下のメッセージが出力されていました。
2019-02-08T09:08:17Z [WARN] Managed task [arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXX:task/XXXXXXXXXX]: error starting/provisioning container[nginx]; marking its desired status as STOPPED: Error response from daemon: failed to initialize logging driver: failed to create Cloudwatch log group: AccessDeniedException: User: arn:aws:sts::XXXXXXXXXXXX:assumed-role/ecsTaskExecutionRole/XXXXXXXX is not authorized to perform: logs:CreateLogGroup on resource: arn:aws:logs:ap-northeast-1:XXXXXXXXXXXX:log-group:/ecslog:log-stream: status code: 400, request id: XXXXXXXXXXXX
ここに辿り着くまでが長かった。。。
その他
本件のログの話とは関係ないですが、CloudFormationからタスク定義を作成する場合、DeletePolicy
パラメータは働かないようです。CFnのStackを削除しても、タスク定義が消えてくれませんでした。
UpdateReplacePolicy
パラメータを利用して、タスク定義をUpdateする形で対応していけ、と下記Github issueで議論されていますね。
Does CFN keep the task def revision? · Issue #1 · awslabs/ecs-refarch-continuous-deployment · GitHub