AWS CLI で ECS run-task して、完了を待って実行結果を確認する

GitHub Actions で ECS でスクリプトを実行したかったのですが、ECS run-task は非同期実行なので完了を待つのと、実行結果の確認が自身で実装する必要がありました。
AWS CLI で実行する方法の調査結果メモです。

ECS RunTask
ECS_CLUSTER=<cluster name>
TASKDEF_NAME=<task definition name>
SUBNET_IDS='["<subnet id 1>","<subnet id 2>","<subnet id 3>"]'
SECURITY_GROUP_IDS='["<security group id>"]'
run_task_response=$(aws ecs run-task \
--cluster ${ECS_CLUSTER} \
--count 1 \
--launch-type FARGATE \
--network-configuration 'awsvpcConfiguration={
subnets='${SUBNET_IDS}',
securityGroups='${SECURITY_GROUP_IDS}',
assignPublicIp=ENABLED}' \
--platform-version 1.4.0 \
--task-definition ${TASKDEF_NAME}
)
完了は待たず、レスポンスは返ってきます

Waiter
AWS CLI は waiter という機能があります。
waiter は非同期実行する API の状態が条件に一致するまで待つという機能です。
今回の ECS に限らず、いくつかのサービス、状態に対応しています。
わかりやすい例でいえば、EC2 インスタンスを起動して、RUNNING ステータスを待つなどはイメージしやすいかと思います。
ECS は以下の waiter(状態)を持ちます。
aws ecs wait help
...
AVAILABLE COMMANDS
o services-inactive
o services-stable
o tasks-running
o tasks-stopped
今回は tasks-stopped
というタスクのステータスが STOPPED になるのを待つコマンドを利用します。
引数は ECS クラスタ名とタスク ARN を渡すだけです。ARN は複数渡すことができ、複数のタスクの完了を待つこともできます。
aws ecs wait tasks-stopped \
--cluster ${ECS_CLUSTER} \
--tasks $(echo $run_task_response | jq -r '.tasks[0].taskArn')
実行するとコマンド実行状態となります。
指定したすべてのタスクが STOPPED ステータスになるとプロンプトが返ってきます。標準出力はありません。

タスクの詳細ステータスの確認
waiter tasks-stopped
はステータスが STOPPED になるのを待つだけで成功したのか、失敗したのか判断できません。
なので別途タスクを確認する必要があります。
ECS task の確認
{
"tasks": [
{
...
"stopCode": "EssentialContainerExited",
"stoppedReason": "Essential container in task exited",
"containers": [
{
...
"exitCode": 1,
...
ECS、ECS タスクレベルのエラーは stopCode
、stoppedReason
から確認することができます。上記レスポンス例はコンテナが終了した(今回だと entrypoint で指定したスクリプトが終了した)ためとなります。
stopCode
の種類は以下ドキュメントページに記載されています。
またコンテナが終了した際に正常終了したのか exitCode などで確認できます。
exitCode は数値なのでもう少し詳細を確認しようと思うと、ログの確認が必要になります。
CloudWatch Logs の確認
ECS タスクのコンテナはログ出力先を指定できます。
今回はよく利用する CloudWatch Logs を例に確認方法を調査しました。
CloudWatch Logs は tail オプションを持ち、Linux コマンドの tail のような感じで簡単に新しいログを確認できます。
--since
オプションが便利で相対時間、絶対時間の両パターンで指定できます。
aws logs tail \
${LOG_GROUP_NAME} \
--since 10m
# ISO8601 形式
START_DATETIME=$(date +%Y-%m-%dT%H:%M:%S+0900)
#(略)
aws logs tail \
${LOG_GROUP_NAME} \
--since ${START_DATETIME}
また今回は利用しませんが --follow
オプションで tail -f
相当のことができます(便利!)