[小ネタ]ECSタスクの異常終了を検知するEventBridgeイベントパターン

2020.12.31

はじめに

ECSタスクの異常終了を検知する為のサービスの一つとしてAmazon EventBridgeがあります。EventBridgeのイベントパターンは、任意または特定クラスタでタスクの状態変更を検知することができますが、タスクのライフサイクルすべてが対象として検知される為、異常終了したECSタスクを対象(ECS Task State Change)とするイベントパターンの方法についてご案内します。

EventBridgeが受け取るイベントデータ

EventBriegeがECSタスクの異常終了を検知するには、ECSからEventBridgeへイベントデータが送信されます。

{
    "version": "0",
    "id": "2399ff15-514a-b9ae-cf3c-39004ba0d195",
    "detail-type": "ECS Task State Change",
    "source": "aws.ecs",
    "account": "111122223333",
    "time": "2020-12-08T01:24:50Z",
    "region": "ap-northeast-1",
    "resources": [
        "arn:aws:ecs:ap-northeast-1:111122223333:task/ecs-cluster/b2f31a11604c41afacab7c7ef983ac95"
    ],
    "detail": {
        "attachments": [
            {
                "id": "46504a06-5603-415d-8014-6868c1b28c19",
                "type": "eni",
                "status": "ATTACHED",
                "details": [
                    {
                        "name": "subnetId",
                        "value": "subnet-aaaabbbbccccdddd1"
                    },
                    {
                        "name": "networkInterfaceId",
                        "value": "eni-aaaabbbbccccdddd1"
                    },
                    {
                        "name": "macAddress",
                        "value": "0a:c7:c8:ca:0d:9e"
                    },
                    {
                        "name": "privateDnsName",
                        "value": "ip-10-0-2-132.ap-northeast-1.compute.internal"
                    },
                    {
                        "name": "privateIPv4Address",
                        "value": "10.0.2.132"
                    }
                ]
            }
        ],
        "availabilityZone": "ap-northeast-1c",
        "capacityProviderName": "FARGATE_SPOT",
        "clusterArn": "arn:aws:ecs:ap-northeast-1:111122223333:cluster/ecs-cluster",
        "connectivity": "CONNECTED",
        "connectivityAt": "2020-12-08T01:24:01.079Z",
        "containers": [
            {
                "containerArn": "arn:aws:ecs:ap-northeast-1:111122223333:container/25a15501-08b1-4da7-a160-44b29f9e54ec",
                "exitCode": 1,
                "lastStatus": "STOPPED",
                "name": "python-worker1",
                "image": "111122223333.dkr.ecr.ap-northeast-1.amazonaws.com/python-worker:latest",
                "imageDigest": "sha256:dc1e598a3ffad66b70681fdf3de1c2dd49b0c051d5dc6809c2db85bea2f15f2d",
                "runtimeId": "3ff55e39e0dba5644b8fe0852187b5537e50330d366cf1b910c8eb1ff2ed53b9",
                "taskArn": "arn:aws:ecs:ap-northeast-1:111122223333:task/ecs-cluster/b2f31a11604c41afacab7c7ef983ac95",
                "networkInterfaces": [
                    {
                        "attachmentId": "46504a06-5603-415d-8014-6868c1b28c19",
                        "privateIpv4Address": "10.0.2.132"
                    }
                ],
                "cpu": "128",
                "memoryReservation": "256"
            },
            {
                "containerArn": "arn:aws:ecs:ap-northeast-1:111122223333:container/b5200cc5-3aab-4677-9c7d-e1edcdb314c8",
                "exitCode": 1,
                "lastStatus": "STOPPED",
                "name": "python-worker2",
                "image": "111122223333.dkr.ecr.ap-northeast-1.amazonaws.com/python-worker:latest",
                "imageDigest": "sha256:dc1e598a3ffad66b70681fdf3de1c2dd49b0c051d5dc6809c2db85bea2f15f2d",
                "runtimeId": "af85e2d2ddc073e933c895267252f5534ca83b876c5d7080eb7bd7c5bd939a12",
                "taskArn": "arn:aws:ecs:ap-northeast-1:111122223333:task/ecs-cluster/b2f31a11604c41afacab7c7ef983ac95",
                "networkInterfaces": [
                    {
                        "attachmentId": "46504a06-5603-415d-8014-6868c1b28c19",
                        "privateIpv4Address": "10.0.2.132"
                    }
                ],
                "cpu": "128",
                "memoryReservation": "256"
            }
        ],
        "cpu": "256",
        "createdAt": "2020-12-08T01:23:48.836Z",
        "desiredStatus": "STOPPED",
        "executionStoppedAt": "2020-12-08T01:24:40Z",
        "group": "family:python-worker",
        "launchType": "FARGATE",
        "lastStatus": "DEPROVISIONING",
        "memory": "512",
        "overrides": {
            "containerOverrides": [
                {
                    "name": "python-worker1"
                },
                {
                    "name": "python-worker2"
                }
            ]
        },
        "platformVersion": "1.3.0",
        "pullStartedAt": "2020-12-08T01:24:06.951Z",
        "pullStoppedAt": "2020-12-08T01:24:35.951Z",
        "startedAt": "2020-12-08T01:24:38.951Z",
        "stoppingAt": "2020-12-08T01:24:50.607Z",
        "stoppedReason": "Scaling activity initiated by (deployment ecs-svc/2670985220624721111)",
        "taskArn": "arn:aws:ecs:ap-northeast-1:111122223333:task/ecs-cluster/b2f31a11604c41afacab7c7ef983ac95",
        "taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:111122223333:task-definition/python-worker:4",
        "updatedAt": "2020-12-08T01:24:50.607Z",
        "version": 4
    }
}

イベントデータの中身は、ECSタスクメタデータエンドポイントです。タスクのメタデータがJSON形式でレスポンスが返されます。

Amazon ECS タスクメタデータエンドポイント

ContainersのexitCodeが0以外が異常終了となりますが、ローリングアップデートの条件によってはexitCode137で強制終了する場合もあります。タスクが停止した際にエラーメッセージは、stoppedReasonで確認できます。

停止されたタスクでのエラーの確認

ローリングアップデートによるデプロイのエラーメッセージ「Scaling activity initiated by〜」は検知しないように設定します。

異常終了にマッチするイベントパターン

EventBridgeのルール作成時にイベントパターンをフィルタリングすることができるので予期しないタスクの異常終了だけを検知するフィルタリングを作成します。

イベントパターンを使用したコンテンツベースのフィルタリング

{
    "source": [
        "aws.ecs"
    ],
    "detail-type": [
        "ECS Task State Change"
    ],
    "detail": {
        "clusterArn": [
            "arn:aws:ecs:ap-northeast-1:111122223333:cluster/ecs-cluster"
        ],
        "containers": {
            "exitCode": [
                {
                    "anything-but": 0
                }
            ]
        },
        "lastStatus": [
            "STOPPED"
        ],
        "stoppedReason": [
            {
                "anything-but": {
                    "prefix": "Scaling activity initiated by"
                }
            }
        ]
    }
}

上記は、

  • clusterArnで指定したクラスターで起動したECSタスク
  • exitCodeが0以外
  • ECSタスクの最後のステータス(lastStatus)がSTOPPED
  • Scaling activity initiated byから始まるエラーメッセージ(stoppedReason)を除外

を条件とするイベントパターンです。予期せぬ異常終了が検知してAmazon SNSをターゲットとするルールを作成すればメール通知するルールを作成できます。

clusterArnで固有のAWSリソースを指定していますが、clusterArnプロパティを省くことでリージョン内のタスクすべてを対象とする、いわゆるワイルドカード相当とすることも可能です。

さいごに

EventBridgeのイベントパターンは、カスタマイズすることで限定的な条件とすることができます。ECSタスクに限らず、AWSサービスも含むサービス・プロバイダをトリガーにすることができます。まずはイベントデータがどんな内容か、しっかり把握してからカスタマイズしていきましょう。