AWS HealthOmics が WDL ワークフローのタスクレベルタイムアウトに対応したので試してみた

AWS HealthOmics が WDL ワークフローのタスクレベルタイムアウトに対応したので試してみた

AWS HealthOmics が WDL ワークフローのタスクレベルタイムアウト機能に対応しました。`omicsTimeout` を設定して、実際の動作と指定時間を超えた場合の挙動を検証した結果をまとめています。
2026.08.22

はじめに

AWS HealthOmics が WDL ワークフローのタスクレベルタイムアウトに対応しました。タスクごとに最大実行時間を指定できるようになり、指定時間を超えるとタスクが停止できるようになりました。sleep 600 するだけの WDL タスクに omicsTimeout: "2m" を指定して実行し、実際に停止するまでの挙動を確認しました。

aws-healthomics-wdl-task-timeout.png

https://aws.amazon.com/jp/about-aws/whats-new/2026/08/aws-healthomics-wdl-task-level-timeout/

確認結果

検証は東京リージョン(ap-northeast-1)で 2026 年 8 月 4 日に実施しました。

  • omicsTimeout: "2m" を指定したタスクは指定時間の経過後に停止し、run とタスクのステータスが FAILED になりました
  • タスクの startTime から stopTime までは 182.274 秒 でした。指定した 120 秒に対して、停止処理に 約 62 秒 のオーバーヘッドがありました
  • タイムアウトを示す文言は CloudWatch Logs には出力されず、get-run-taskfailureReason とコンソールの「エラーの理由」で確認できました

なにが嬉しいのか

開発中の無限ループタスクを自動停止してコストを抑えられる

ワークフローの新規作成中(試行錯誤中)に想定より長く動くタスクや無限ループに気づかないまま計算コストが高くなってしまうことがあります。omicsTimeoutruntime セクションに 1 行加えるだけで、指定時間を超えたタスクを強制的に止められようになりました。試行錯誤している段階では分単位でタスクを止められるガードレールの設定は実用的なのではないでしょうか。

run 全体でなくタスク単位でタイムアウトを区切れる

HealthOmics にはすでに run 全体の最大実行時間を決めるクォータや、run グループ単位の時間指定があります。今回追加されたomicsTimeout は、タスク単位というより小さい単位でタイムアウトを設定できます。つまり、特定のステップだけが長時間化しやすいワークフローで、特定のタスクだけにタイムアウトを設定できます。

AWS HealthOmics は 2025 年 8 月に、Nextflow の time directive で同様の仕組みを先行してサポートしていました。今回の対応で、WDL のワークフローでも同じガードレールを使えるようになりました。

https://aws.amazon.com/about-aws/whats-new/2025/08/aws-healthomics-task-level-timeout-nextflow-workflows/

omicsTimeout の仕様

omicsTimeout は WDL タスクの runtime セクションに追加する、HealthOmics 独自の属性です。整数(秒)、または smhd を組み合わせた文字列で最大実行時間を指定します。例えば "40m""1h30m""1m3s" のように書けます。

HealthOmics provides a custom omicsTimeout attribute to set a maximum task duration in your workflow. Specify the timeout duration as an integer (seconds) or a string using one or more of the following units: s, m, h, or d. For example, "40m", "1h30m", or "1m3s".

出典: WDL workflow definition specifics

公式ドキュメントではomicsTimeout について以下の挙動が挙げられています。

  • 粒度は 1 分単位で、指定できる範囲は 60 秒から run の最大実行時間まで
  • 60 秒未満の値は 60 秒に切り上げられ、60 秒を超える値は分単位で切り捨てられる
  • タイムアウトするとタスクはキャンセルされる。この処理には 1〜2 分かかることがある
  • run とタスクのステータスは failed になり、同じ run 内の他タスク(Starting、Pending、Running)もキャンセルされる。タイムアウト前に完了していたタスクの出力は S3 の出力先にエクスポートされる
  • pending 状態で待機していた時間は、タスクの経過時間に算入されない

run 全体の最大実行時間は Workflows - Maximum run duration サービスクォータがあります。既定値は 604,800 秒(7 日)で、調整可能なので必要に応じて引き上げをリクエストできます。

https://docs.aws.amazon.com/omics/latest/dev/service-quotas.html

検証環境

項目
リージョン ap-northeast-1(東京)
ワークフローエンジン WDL(WDL 1.0)
コンテナイメージ ubuntu 24.04(同一リージョンの ECR プライベートリポジトリ、x86_64)
ストレージタイプ DYNAMIC
タスクリソース cpu 2、memory 4 GB
omicsTimeout タイムアウト版は "2m"、ベースラインは未指定

S3 出力先、ECR リポジトリ、HealthOmics サービスロールの事前準備は、以下の Nextflow の記事と共通です。ワークフローの言語が変わっても前提リソースの構成自体は変わりません。

https://dev.classmethod.jp/articles/aws-healthomics-nextflow-26-04-hello-world/

WDL ワークフロー定義

今回使用した WDL ワークフロー定義です。SleepTasksleep 600 を実行するだけの単一タスクのワークフローで、開始時刻と終了時刻を result.txt に書き出します。runtimeセクションではdockercpumemoryに加えてomicsTimeout: "2m"を指定しています。WDL 1.0 ではdocker属性を使います。WDL 1.1 で導入されたcontainer` 属性とは書き方が異なります。

timeout.wdl
version 1.0

workflow TimeoutDemo {
    input {
        String container_image
    }
    call SleepTask {
        input:
            container_image = container_image
    }
    output {
        File result = SleepTask.result
    }
}

task SleepTask {
    input {
        String container_image
    }
    command <<<
        START=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
        sleep 600
        echo "$START" > result.txt
        date -u +"%Y-%m-%dT%H:%M:%SZ" >> result.txt
    >>>
    output {
        File result = "result.txt"
    }
    runtime {
        docker: container_image
        cpu: 2
        memory: "4 GB"
        omicsTimeout: "2m"
    }
}

omicsTimeout指定なし版も実行してベースラインを確認したいので、omicsTiout: "2m"を削ったワークフローもbaseline.wdlとして別途用意しました。

container_image をハードコードせずワークフロー入力として宣言しているので、run 実行時に渡す input.json は次のとおり ECR に保存してあるイメージ名を指定します。

{
  "TimeoutDemo.container_image": "<account-id>.dkr.ecr.ap-northeast-1.amazonaws.com/<repository-name>:24.04"
}

ワークフローを登録する

baseline.wdltimeout.wdl をそれぞれ zip 化し、aws omics create-workflow --engine WDL で登録します。

zip -j baseline.zip baseline.wdl
aws omics create-workflow --name healthomics-wdl-timeout-baseline --engine WDL \
  --definition-zip fileb://baseline.zip --region ap-northeast-1

レスポンスの id が、この後の start-run で参照するワークフロー ID です。

実行結果
{
    "arn": "arn:aws:omics:ap-northeast-1:<account-id>:workflow/1744239",
    "id": "1744239",
    "status": "CREATING",
    "tags": {},
    "uuid": "b8cfe5d3-13b2-ac1a-fec4-655be4b16b89"
}

同様にタイムアウト版も登録します。

zip -j timeout.zip timeout.wdl
aws omics create-workflow --name healthomics-wdl-timeout --engine WDL \
  --definition-zip fileb://timeout.zip --region ap-northeast-1
実行結果
{
    "arn": "arn:aws:omics:ap-northeast-1:<account-id>:workflow/7838634",
    "id": "7838634",
    "status": "CREATING",
    "tags": {},
    "uuid": "9ccfe5d3-2535-eb92-f43a-a1eb441cb778"
}

create-workflow の直後は statusCREATING です。今回は 8 秒後に両方とも ACTIVE になりました。get-workflowACTIVE を確認してから run を開始します。

aws omics get-workflow --id 1744239 --region ap-northeast-1 --query 'status'
実行結果
"ACTIVE"

検証用ワークフローを実行してみる

それぞれのワークフローに対して start-run を実行します。container_image をワークフロー入力にしているため、--parametersinput.json を渡します。--storage-typeDYNAMIC を明示します。ベースラインとタイムアウト版は独立したワークフローなので、待ち時間を短縮するため並行して起動しました。

aws omics start-run \
  --workflow-id 7838634 \
  --role-arn arn:aws:iam::<account-id>:role/<service-role-name> \
  --output-uri s3://<output-bucket>/wdl-timeout/ \
  --parameters file://input.json \
  --storage-type DYNAMIC \
  --name wdl-timeout-run --region ap-northeast-1

レスポンスの id が run の追跡に使う ID です。

実行結果
{
    "arn": "arn:aws:omics:ap-northeast-1:<account-id>:run/2833398",
    "id": "2833398",
    "status": "PENDING",
    "runOutputUri": "s3://<output-bucket>/wdl-timeout/2833398",
    "networkingMode": "RESTRICTED"
}

タイムアウトなし版なら sleep 600 は当然完走する

先にベースラインの結果です。ワークフロー ID 1744239 を同じ形式で起動し、run ID は 9485917 でした。omicsTimeout 設定を削除して同一定義の run はタスクの stopTime から startTime を引くと 616.164 秒で、sleep 600 に対して約 16 秒のオーバーヘッドでした。

aws omics list-run-tasks --id 9485917 --region ap-northeast-1
実行結果
{
    "taskId": "4546924",
    "status": "COMPLETED",
    "startTime": "2026-08-04T07:25:29.317000+00:00",
    "stopTime": "2026-08-04T07:35:45.481000+00:00",
    "instanceType": "omics.c.large"
}

タスク内部で記録した result.txt も、開始から正確に 600 秒後の時刻を残していました。

aws s3 cp s3://<output-bucket>/wdl-timeout/9485917/out/result/result.txt -
実行結果
2026-08-04T07:25:29Z
2026-08-04T07:35:29Z

タイムアウト版は RUNNING から STOPPING を経て FAILED になる

タイムアウト版のステータスを 10 秒間隔でポーリングして見守りました。ステータスの遷移は PENDING から STARTINGRUNNINGSTOPPING を経て FAILED でした。

for i in $(seq 1 60); do
  date -u +"%Y-%m-%dT%H:%M:%SZ"
  aws omics get-run --id 2833398 --region ap-northeast-1 --query 'status' --output text
  sleep 10
done
実行結果(抜粋、遷移箇所のみ)
2026-08-04T07:23:52Z STARTING
2026-08-04T07:24:03Z RUNNING
2026-08-04T07:30:51Z STOPPING
2026-08-04T07:33:08Z FAILED

run 単位の statusMessage には、どのタスクが何秒でタイムアウトしたかのメッセージがありました。

aws omics get-run --id 2833398 --region ap-northeast-1 \
  --query '{status:status,statusMessage:statusMessage,startTime:startTime,stopTime:stopTime}'
実行結果
{
    "status": "FAILED",
+   "statusMessage": "Task 4352220 timed out after 120 seconds.",
    "startTime": "2026-08-04T07:23:51+00:00",
    "stopTime": "2026-08-04T07:33:07.369210+00:00"
}

コンソールの実行の概要でも同じ内容を確認できます。ステータスが「エラー」、エラーの理由が TASK_TIMED_OUT、ステータスの説明に run 単位と同じ文言が表示されます。

Run_2833398___AWS_HealthOmics___ap-northeast-1-2.png

停止までに指定値より約 60 秒長くかかった

停止までの時間は run 単位でなくタスク単位で確認してみます。run の startTimestopTime の差には出力のエクスポートなど終了時の共通処理が混ざるためです。list-run-tasks でタスクの startTimestopTime を確認します。

aws omics list-run-tasks --id 2833398 --region ap-northeast-1
実行結果
{
    "items": [
        {
            "taskId": "4352220",
            "status": "FAILED",
            "name": "SleepTask",
            "creationTime": "2026-08-04T07:23:56.314407+00:00",
            "startTime": "2026-08-04T07:26:09.571000+00:00",
            "stopTime": "2026-08-04T07:29:11.845000+00:00",
            "instanceType": "omics.c.large"
        }
    ]
}

07:29:11.84507:26:09.571182.274 秒(約 3 分 2 秒)でした。指定した 120 秒に対して停止処理に約 62 秒のオーバーヘッドがあります。公式ドキュメントにも「1〜2 分かかることがある」と書いてあるので想定の範囲内です。

タイムアウトかどうかは CloudWatch Logs では判別できない

list-run-tasks のレスポンスに失敗理由は含まれません。個別タスクの statusMessagefailureReasonget-run-task で取得します。

aws omics get-run-task --id 2833398 --task-id 4352220 --region ap-northeast-1
実行結果
{
    "taskId": "4352220",
    "status": "FAILED",
    "startTime": "2026-08-04T07:26:09.571000+00:00",
    "stopTime": "2026-08-04T07:29:11.845000+00:00",
+   "statusMessage": "Task exceeded the time directive for the process after 120 seconds.",
+   "failureReason": "TASK_TIMED_OUT",
    "instanceType": "omics.c.large"
}

failureReasonTASK_TIMED_OUT になり、タイムアウトが原因だと判別できます。この値はマネージメントコンソールの実行の概要にある「エラーの理由」と同じです。なお run 単位とタスク単位で statusMessage の文言は異なりました。タスク単位の「time directive」は、先行して対応した Nextflow の time ディレクティブに由来する表現だと思われ、WDL の omicsTimeout でも共通して使われているように見えました。

一方で CloudWatch Logs には、タイムアウトを示す文言が出ませんでした。タスクログには起動時のトレースだけが残っており、sleep の途中で停止したことはわかりません。

aws logs get-log-events --log-group-name /aws/omics/WorkflowLog \
  --log-stream-name "run/2833398/task/4352220" --start-from-head --region ap-northeast-1
実行結果
Task started
+ echo Task started
+ cd /mnt/workflow/2833398/call-SleepTask/work
+ bash ../command
++ tee -a ../stdout.txt
++ tee -a ../stderr.txt

エンジンログにも Terminated という汎用的なエラーしか出ていませんでした。

aws logs get-log-events --log-group-name /aws/omics/WorkflowLog \
  --log-stream-name "run/2833398/engine" --start-from-head --region ap-northeast-1
実行結果(抜粋)
2026-08-04 07:29:41.186 (TaskPool_0) WARNING ... Failed to run workflow task SleepTask with arn: arn:aws:omics:ap-northeast-1:<account-id>:task/4352220
2026-08-04 07:29:41.188 (TaskPool_0) ERROR ... task SleepTask (timeout.wdl Ln 16 Col 1) failed :: dir: "/mnt/workflow/2833398/call-SleepTask", error: "Terminated"
2026-08-04 07:29:41.246 (MainThread) NOTICE ... aborting workflow

タイムアウトかどうかをログだけで切り分けが難しいことがわかりました。 get-run-taskfailureReason を見ましょう。

タイムアウトしたタスクの出力は S3 に残らない

タイムアウトした run の出力先には logs/engine.log だけが残り、result.txt はエクスポートされていませんでした。今回のタスクは sleep 600 の後に result.txt を書く作りなので、停止時点でファイル自体が存在していないので、こちらも想定どおりです。

aws s3 ls s3://<output-bucket>/wdl-timeout/2833398/ --recursive --region ap-northeast-1
実行結果
2026-08-04 16:23:24          0 wdl-timeout/2833398/
2026-08-04 16:29:44       1372 wdl-timeout/2833398/logs/engine.log

まとめ

AWS HealthOmics の WDL ワークフローで omicsTimeout を設定すると、指定時間を超えたタスクが停止し、run が FAILED になることを確認しました。runtime セクションに 1 行追加するだけで、新規作成中の試行錯誤時などのガードレールとして有用です。

120 秒の指定に対して実際に停止するまでは 182.274 秒で、停止処理に約 62 秒のオーバーヘッドがありました。

タイムアウトが原因かどうかは CloudWatch Logs では判別できず、get-run-taskfailureReason を見る必要がありました。目視ならマネージメントコンソールから原因を確認するのが楽でした。

おわりに

Nextflow で先行してサポートされていたタスクレベルタイムアウトが WDL にも来たので試してみました。最近、東京リージョンでの HealthOmics が使えるようになったのでよかったら使ってみてください。

https://dev.classmethod.jp/articles/aws-healthomics-tokyo-region/

参考

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事