CloudFormtaionのECSタスク定義にて、ログ設定をawslogsにしようとしたらハマった

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