ECS タスクの停止理由を CloudWatch Logs に保管する方法を教えてください

2021.08.26

困っていた内容

ECS を使用したシステムを構築しています。予期せず ECS タスクが停止した際は、タスクの停止理由を確認しているのですが、しばらくすると停止したタスクはマネージメントコンソールから消えてしまうようです。
表示が消えても構わないように、停止理由を CloudWatch Logs に保管しようと思うのですが、設定する方法を教えてください。

ListTasks - Amazon Elastic Container Service

Currently, stopped tasks appear in the returned results for at least one hour.

どう対応すればいいの?

CloudFormation でecs-stopped-tasks-cwlogs.yamlテンプレートを実行してください。

ecs-stopped-tasks-cwlogs.yamlテンプレートを実行すると、ECSタスクの停止イベントが自動的に CloudWatch Logs に保管されます。保管対象はリージョン内の全ECSタスクで、複数のリージョンで使用したい場合は、リージョン毎にテンプレートを実行してください。

具体的な仕組みは、ECS が停止した時にトリガーされる EventBridge イベントを CloudWatch Logs に保存しています。

GitHub - aws-samples/amazon-ecs-stopped-tasks-cwlogs: Automate storing of Amazon ECS Stopped Tasks in Amazon CloudWatch Logsより引用

やってみた

あらかじめGitHubからecs-stopped-tasks-cwlogs.yamテンプレートをダウンロードします。

AWS CloudFormation コンソールを開き、「スタックの作成」をクリックします。

「テンプレートファイルのアップロード」を選択し、「ファイルの選択」からダウンロードしたecs-stopped-tasks-cwlogs.yamlを選択。「次へ」をクリックします。

任意の名前を入力し、必要に応じてログの保管先(CloudWatch Logs のロググループ名)と保持期間(単位:日)を指定します。

「次へ」をクリックします。

「スタックの作成」をクリックします。

自動的にリソースが作成されるため、しばらく待ちます。
「イベント」タグの矢印をクリックで、作成状況が更新されます。

ステータスが「CREATE_COMPLETE」なったことを確認します。

実際の挙動

ECSタスクを手動で停止します。

しばらく待つと、作成時に指定した CloudWatch Logs にログストリームが作成されます。

ストリーム内のイベントをクリックすると、停止時のイベント(停止理由)確認できます。

サンプル

※停止理由はstoppedReasonを確認します。

{
    "version": "0",
    "id": "dcfeb05f-8046-d26b-0250-22353be17ed5",
    "detail-type": "ECS Task State Change",
    "source": "aws.ecs",
    "account": "123456789012",
    "time": "2021-08-11T09:15:14Z",
    "region": "ap-northeast-3",
    "resources": [
        "arn:aws:ecs:ap-northeast-3:123456789012:task/hato-ecs-cluster/866773c124284ea6bc488f7a3be8c3c2"
    ],
    "detail": {
        "attachments": [
            {
                "id": "ddd8dec3-6a67-42cc-b869-6eb050a4ba8b",
                "type": "eni",
                "status": "DELETED",
                "details": [
                    {
                        "name": "subnetId",
                        "value": "subnet-01234567890123456"
                    },
                    {
                        "name": "networkInterfaceId",
                        "value": "eni-09449af85d9145c2f"
                    },
                    {
                        "name": "macAddress",
                        "value": "00:11:22:33:44:55"
                    },
                    {
                        "name": "privateDnsName",
                        "value": "ip-10-0-0-1.ap-northeast-3.compute.internal"
                    },
                    {
                        "name": "privateIPv4Address",
                        "value": "10.0.0.1"
                    }
                ]
            }
        ],
        "availabilityZone": "ap-northeast-3b",
        "clusterArn": "arn:aws:ecs:ap-northeast-3:123456789012:cluster/hato-ecs-cluster",
        "connectivity": "CONNECTED",
        "connectivityAt": "2021-08-11T09:01:48.973Z",
        "containers": [
            {
                "containerArn": "arn:aws:ecs:ap-northeast-3:123456789012:container/hato-ecs-cluster/866773c124284ea6bc488f7a3be8c3c2/96574b15-39b9-41fb-b2ea-2362089cd242",
                "exitCode": 0,
                "lastStatus": "STOPPED",
                "name": "nginx",
                "image": "nginx:stable",
                "runtimeId": "123456c124284ea6bc488f7a3be8c3c2-2531612879",
                "taskArn": "arn:aws:ecs:ap-northeast-3:123456789012:task/hato-ecs-cluster/866773c124284ea6bc488f7a3be8c3c2",
                "networkInterfaces": [
                    {
                        "attachmentId": "ddd8dec3-6a67-42cc-b869-6eb050a4ba8b",
                        "privateIpv4Address": "10.0.0.1"
                    }
                ],
                "cpu": "0"
            }
        ],
        "cpu": "256",
        "createdAt": "2021-08-11T09:01:41.903Z",
        "desiredStatus": "STOPPED",
        "enableExecuteCommand": false,
        "ephemeralStorage": {
            "sizeInGiB": 20
        },
        "executionStoppedAt": "2021-08-11T09:14:51.927Z",
        "group": "service:hato-ecs-service",
        "launchType": "FARGATE",
        "lastStatus": "STOPPED",
        "memory": "512",
        "overrides": {
            "containerOverrides": [
                {
                    "name": "nginx"
                }
            ]
        },
        "platformVersion": "1.4.0",
        "pullStartedAt": "2021-08-11T09:01:58.639Z",
        "pullStoppedAt": "2021-08-11T09:02:05.671Z",
        "startedAt": "2021-08-11T09:02:06.509Z",
        "startedBy": "ecs-svc/4197414922177771410",
        "stoppingAt": "2021-08-11T09:14:40.449Z",
        "stoppedAt": "2021-08-11T09:15:14.753Z",
        "stoppedReason": "Task stopped by user",
        "stopCode": "UserInitiated",
        "taskArn": "arn:aws:ecs:ap-northeast-3:123456789012:task/hato-ecs-cluster/866773c124284ea6bc488f7a3be8c3c2",
        "taskDefinitionArn": "arn:aws:ecs:ap-northeast-3:123456789012:task-definition/hato-ecs-task:9",
        "updatedAt": "2021-08-11T09:15:14.753Z",
        "version": 6
    }
}

参考資料