Amazon ECSで、タスクの停止理由などをAWS CLIから確認する

# What's？

AWS Fargateを使っていて、タスクの起動に失敗した時にどうやって確認したらいいか覚えられなかったのでメモしようかなと。

AWSマネージメントコンソールで以下の方法で見てもいいのですが、毎回見るのも面倒なので、AWS CLIで見たいのです。

[停止したタスクのエラーの確認](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/stopped-task-errors.html)


# 環境

利用するAWS CLIのバージョンは、こちら。

```shell
$ aws --version
aws-cli/2.0.52 Python/3.7.3 Linux/4.15.0-112-generic exe/x86_64.ubuntu.20
```

AWSのクレデンシャルは、環境変数で設定しているものとします。

```shell
$ export AWS_ACCESS_KEY_ID=...
$ export AWS_SECRET_ACCESS_KEY=...
$ export AWS_DEFAULT_REGION=ap-northeast-1
```


# 確認

まずは、確認対象のクラスターを確認します。

[list-clusters](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecs/list-clusters.html)

```shell
$ aws ecs list-clusters
```

AWS CLIのドキュメント例ですが、こんな結果が得られるので、ECSクラスター名を確認しましょう。

```json
{
    "clusterArns": [
        "arn:aws:ecs:us-west-2:123456789012:cluster/MyECSCluster1",
        "arn:aws:ecs:us-west-2:123456789012:cluster/AnotherECSCluster"
    ]
}
```

ここでは、`MyECSCluster1`や`AnotherECSCluster`などがクラスター名ですね。

次に、タスクを確認します。

[list-tasks](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecs/list-tasks.html)

```shell
$ aws ecs list-tasks --cluster [クラスター名]

# たとえば
$ aws ecs list-tasks --cluster MyECSCluster1
```

結果の例。

```shell
{
    "taskArns": [
        "arn:aws:ecs:us-west-2:123456789012:task/a1b2c3d4-5678-90ab-cdef-11111EXAMPLE",
        "arn:aws:ecs:us-west-2:123456789012:task/a1b2c3d4-5678-90ab-cdef-22222EXAMPLE"
    ]
}
```

この時、`--desired-status`というオプションを指定しない場合、`RUNNING`のタスクしか表示されません。

`RUNNING`、`PENDING`、`STOPPED`のいずれかを指定することができるので、適切に指定しましょう。

それぞれの意味は、[タスクのライフサイクル](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task-lifecycle.html)を参照。

トラブルシュートの場合は、`PENDING`や`STOPPED`を指定することになります。

```shell
$ aws ecs list-tasks --cluster [クラスター名] --desired-status STOPPED

# たとえば
$ aws ecs list-tasks --cluster MyECSCluster1 --desired-status STOPPED
```

サービスの`desiredCount`との関係で、タスクが多数表示されて困るよという場合は、`--max-items`を指定して表示件数を絞りましょう。

```shell
$ aws ecs list-tasks --cluster [クラスター名] --desired-status STOPPED --max-items 3
```

これでタスクのARNが得られるので、このARNを使用してタスクの状態を確認します。

[describe-tasks](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ecs/describe-tasks.html)

```shell
$ aws ecs describe-tasks --cluster [クラスター名] --tasks [タスクのARN]

# たとえば
$ aws ecs describe-tasks \
    --cluster MyCluster \
    --tasks arn:aws:ecs:us-west-2:123456789012:task/MyCluster/1234567890123456789
```

ドキュメントのアウトプット例です。

```shell
    "tasks": [
        {
            "taskArn": "arn:aws:ecs:us-west-2:123456789012:task/MyCluster/1234567890123456789",
            "clusterArn": "arn:aws:ecs:us-west-2:123456789012:cluster/MyCluster",
            "taskDefinitionArn": "arn:aws:ecs:us-west-2:123456789012:task-definition/sample-fargate:2",
            "overrides": {
                "containerOverrides": [
                    {
                        "name": "fargate-app"
                    }
                ]
            },
            "lastStatus": "RUNNING",
            "desiredStatus": "RUNNING",
            "cpu": "256",
            "memory": "512",
            "containers": [
                {
                    "containerArn": "arn:aws:ecs:us-west-2:123456789012:container/a1b2c3d4-5678-90ab-cdef-11111EXAMPLE",
                    "taskArn": "arn:aws:ecs:us-west-2:123456789012:task/MyCluster/1234567890123456789",
                    "name": "fargate-app",
                    "lastStatus": "RUNNING",
                    "networkBindings": [],
                    "networkInterfaces": [
                        {
                            "attachmentId": "a1b2c3d4-5678-90ab-cdef-22222EXAMPLE",
                            "privateIpv4Address": "10.0.0.4"
                        }
                    ],
                    "healthStatus": "UNKNOWN",
                    "cpu": "0"
                }
            ],
            "startedBy": "ecs-svc/1234567890123456789",
            "version": 3,
            "connectivity": "CONNECTED",
            "connectivityAt": 1557134016.971,
            "pullStartedAt": 1557134025.379,
            "pullStoppedAt": 1557134033.379,
            "createdAt": 1557134011.644,
            "startedAt": 1557134035.379,
            "group": "service:fargate-service",
            "launchType": "FARGATE",
            "platformVersion": "1.3.0",
            "attachments": [
                {
                    "id": "a1b2c3d4-5678-90ab-cdef-33333EXAMPLE",
                    "type": "ElasticNetworkInterface",
                    "status": "ATTACHED",
                    "details": [
                        {
                            "name": "subnetId",
                            "value": "subnet-12344321"
                        },
                        {
                            "name": "networkInterfaceId",
                            "value": "eni-12344321"
                        },
                        {
                            "name": "macAddress",
                            "value": "0a:90:09:84:f9:14"
                        },
                        {
                            "name": "privateIPv4Address",
                            "value": "10.0.0.4"
                        }
                    ]
                }
            ],
            "healthStatus": "UNKNOWN",
            "tags": []
        }
    ],
    "failures": []
}
```

停止したタスクには、`stoppedReason`などが追加され、停止した理由を確認することができます。

たとえば、DockerHubからイメージをPullできなかった場合は、こんな感じですね。

```json
            "stopCode": "TaskFailedToStart",
            "stoppedReason": "CannotPullContainerError: failed to resolve ref \"docker.io/library/nginx:1.19.2\": failed to do request: Head https://registry-1.docker.io/v2/library/nginx/manifests/1.19.2: dial tcp 3.218.162.19:443: i/o timeout",
            "stoppingAt": "2020-09-26T17:34:13.490000+09:00",
```

これで、

[停止したタスクのエラーの確認](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/stopped-task-errors.html)

を見ているのと同じことになります。