AWS HealthOmics がエフェメラルストレージに対応したので試してみた

AWS HealthOmics がエフェメラルストレージに対応したので試してみた

2026.06.29

はじめに

AWS HealthOmics のプライベートワークフローでエフェメラルストレージがサポートされました。各タスクの /tmp にタスク専用のローカルボリュームをマウントする機能です。容量は WDL、Nextflow、CWL の各ワークフロー定義のディレクティブで 16 GiB から最大 3,072 GiB まで指定できます。今回は Nextflow のプライベートワークフローで有効化し、/tmp を確認してみました。

https://aws.amazon.com/jp/about-aws/whats-new/2026/06/healthomics-scratch-storage/

確認結果

--scratch-storage-mode LOCAL を付けて Nextflow のプライベートワークフローを実行し、/tmp を確認しました。

LOCAL では /tmp がタスク専用のローカル NVMe ボリューム(/dev/nvme1n1、xfs)になりました。disk '100 GB' の指定は 16 GiB 刻みで切り上げられ、112 GiB が割り当てられました。デフォルトの SHARED では /tmp がラン共有の実行ストレージ(NFS)に置かれ、disk の指定は無視されました。

項目 LOCAL SHARED(デフォルト)
/tmp の実体 タスク専用のローカルボリューム ラン共有の実行ストレージ
デバイス / FS タイプ /dev/nvme1n1 / xfs NFS 共有マウント / nfs4
df 上の容量 112 GiB 8.0E(共有 FS の見かけ容量)
disk '100 GB' の反映 112 GiB(16 GiB 切り上げ) 無視される
manifest の scratchStorageReservedGiB 112 出力されない

エフェメラルストレージとは

エフェメラルストレージは、HealthOmics がワークフローの各タスクに専用ローカルボリュームを /tmp としてマウントする機能です。既存の実行ストレージ(DYNAMIC or STATIC で指定するストレージ)とは別物です。主にタスク内の中間データなど、高速な I/O が求められる一時的なデータを処理する scratch 領域として使います。

ゲノム解析ツール(samtools、GATK など)は中間ファイルを /tmp に書き出す設計のものが多く、共有ストレージへの I/O がボトルネックになりがちです。エフェメラルストレージではローカル NVMe ストレージに直接読み書きするためタスク単体の I/O 効率が上がります。

LOCAL で有効化すると、デフォルトの 16 GiB が /tmp の専用ボリュームとして自動で割り当てられます。容量指定は不要で、この範囲なら課金も発生しません。デフォルト設定の SHARED のままでは専用ボリュームは割り当てられず、/tmp は実行ストレージ上に置かれます。

  • デフォルト 16 GiB/タスク(容量指定不要、無料)、上限 3,072 GiB/タスク
  • 容量は 16 GiB 刻みで切り上げ(例: 100 GB の指定すると 112 GiB になる)
  • 16 GiB 超過分のみ課金(容量 × タスク実行秒数)
  • タスク終了時にデータは削除(実行ストレージも似たようなものです)
  • GPU タスクは常にローカル NVMe(ディスクサイズはインスタンスタイプ依存し指定不可)

公式ドキュメントには、マウント先、暗号化、タスク終了時の削除が次のように明記されています。

When you enable ephemeral storage, HealthOmics mounts a dedicated local storage volume at /tmp for each workflow task instance. ... Ephemeral storage volumes are always deleted when the task terminates. ... All ephemeral storage is encrypted at rest using a service-managed AWS KMS key.

出典: Ephemeral storage for HealthOmics workflow tasks - AWS HealthOmics User Guide

実行ストレージとの違い

実行ストレージはラン全体で共有し、ランの実行中だけ使えるファイルシステムです。--storage-type に DYNAMIC または STATIC を指定します(デフォルト値は DYNAMIC)。各タスクの /tmp に割り当てるエフェメラルストレージとはスコープが異なります。混同しやすいなと思ったので整理しました。

観点 実行ストレージ(ラン共有 FS) エフェメラルストレージ(今回の新機能)
スコープ ラン全体。全タスクが共有 タスク単位。タスク間で共有不可
マウント先 ワーキングディレクトリ 各タスクの /tmp(専用ローカルボリューム)
種類 DYNAMIC(自動で容量調整)または STATIC(固定容量) タスク専用のローカルボリューム(CPU は容量指定可、GPU はインスタンスサイズに依存)
容量指定 --storage-type--storage-capacity ワークフロー定義の disk(Nextflow)、disks(WDL)、tmpdirMin(CWL)
永続性 ラン終了時に破棄 タスク終了時に破棄
デフォルト設定 DYNAMIC CPU タスクは SHARED指定(LOCAL 指定で有効化必要)
課金 GB-hour 課金 16 GiB 超過分のみ、容量 × タスク実行秒数

一言でまとめると、実行ストレージは「タスク間でデータを受け渡す共有ストレージ」で、エフェメラルストレージは「タスク内で閉じる scratch 領域」です。

実行ストレージの DYNAMIC(elastic throughput)については以下の記事で紹介しています。

https://dev.classmethod.jp/articles/aws-healthomics-elastic-throughput-dynamic-run-storage/

今回の構成

事前準備と本記事で実行する手順の区分は次のとおりです。

区分 リソース 用途・備考
事前準備 S3 バケット ラン出力先。バケット名は start-run--output-uri で使用
事前準備 ECR プライベートリポジトリ コンテナイメージ格納。HealthOmics はパブリックイメージを直接参照できないため ECR にミラーする
事前準備 HealthOmics サービスロール(IAM) HealthOmics が S3、CloudWatch Logs、ECR にアクセスするためのロール
本記事の手順 Nextflow ワークフロー定義(main.nf disk '100 GB' でエフェメラルストレージを指定した Hello World ワークフロー
本記事の手順 HealthOmics プライベートワークフロー 上記 Nextflow 定義を登録したワークフロー
本記事の手順 HealthOmics ラン --scratch-storage-mode LOCAL を付けて実行するラン

コンテナイメージを ECR に用意する

HealthOmics のプライベートワークフローは ECR プライベートリポジトリのイメージのみ利用できます。今回は ubuntu:24.04 を ECR にミラーします。ミラーは docker pulldocker push でもできますが、今回はレジストリ間でイメージを直接コピーできる crane を試してみました。Docker デーモンを起動せずにコピーできます。

https://michaelsauter.github.io/crane/index.html

ECR にログインし、Docker Hub の ubuntu:24.04 を ECR へコピーします。

aws ecr get-login-password --region us-east-1 \
  | crane auth login --username AWS --password-stdin \
    <ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com
crane copy ubuntu:24.04 \
  <ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/healthomics-ephemeral-hello:24.04

ubuntu:24.04 はマルチアーキイメージで linux/amd64 を含むため、HealthOmics 側で amd64 が選択されます。

Nextflow ワークフロー定義を作成する

disk '100 GB' を指定して /tmp の容量を確認するワークフロー定義(main.nf)を作成します。disk ディレクティブは HealthOmics 固有の拡張ではなく Nextflow 標準のディレクティブです。HealthOmics は scratchStorageMode=LOCAL のとき、disk の値を 16 GiB 刻みで切り上げてエフェメラルボリュームをプロビジョニングします。

レポートファイルは publishDir '/mnt/workflow/pubdir' でエクスポートします。/mnt/workflow/pubdir に書いたファイルが --output-uri の S3 パスにコピーされる仕組みです。

nextflow.enable.dsl=2

process check_scratch {
    container '<ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/healthomics-ephemeral-hello:24.04'
    publishDir '/mnt/workflow/pubdir', mode: 'copy'
    disk '100 GB'

    output:
    path 'scratch_report.txt'

    script:
    """
    echo "== df -h /tmp (before write) ==" > scratch_report.txt
    df -h /tmp >> scratch_report.txt
    echo "== mount /tmp ==" >> scratch_report.txt
    mount | grep ' /tmp ' >> scratch_report.txt 2>&1 || true
    echo "== write 1 GiB to /tmp ==" >> scratch_report.txt
    dd if=/dev/zero of=/tmp/test.bin bs=1M count=1024 status=none
    echo "== df -h /tmp (after write) ==" >> scratch_report.txt
    df -h /tmp >> scratch_report.txt
    """
}

workflow {
    check_scratch()
}

定義ファイルを zip に固めます。

zip workflow.zip main.nf

ワークフローを HealthOmics に登録する

create-workflowworkflow.zip を登録します。

aws omics create-workflow \
  --name healthomics-ephemeral-hello \
  --engine NEXTFLOW \
  --definition-zip fileb://workflow.zip \
  --region us-east-1

id が返ります。作成直後のステータスは CREATING です。

実行結果
{
    "arn": "arn:aws:omics:us-east-1:<ACCOUNT_ID>:workflow/4627227",
    "id": "4627227",
    "status": "CREATING"
}

ステータスが ACTIVE になればランを実行できます。

Private_workflows_details___AWS_HealthOmics___us-east-1_🔊.png

エフェメラルストレージを有効化してランを実行する

--scratch-storage-mode LOCAL が今回の肝です。CPU タスクのデフォルトは SHARED で、disk ディレクティブが無視されます。このオプションを付けないとエフェメラルストレージは有効になりません。

公式ドキュメントには、scratchStorageMode のデフォルト値と SHARED 時の挙動が次のように記述されています。

Ephemeral storage is off by default. When scratchStorageMode is omitted from a StartRun request, scratchStorageMode is set to SHARED (default). ... When scratchStorageMode is SHARED, all disk and equivalent directives in the workflow definition are ignored and /tmp is backed by the shared filesystem.

出典: Ephemeral storage for HealthOmics workflow tasks - AWS HealthOmics User Guide

なお --scratch-storage-mode が効くのは CPU タスクのみです。GPU タスクは常に LOCAL(ローカル NVMe)で、disk 指定はできません。

--scratch-storage-mode LOCAL を付けてランを実行します。コマンド内の --storage-type DYNAMIC は実行ストレージの種別(既定値の明示)で、エフェメラルストレージの設定とは別物です。

aws omics start-run \
  --workflow-id 4627227 \
  --role-arn <serviceRoleArn> \
  --output-uri s3://<bucket>/output/ \
  --storage-type DYNAMIC \
  --scratch-storage-mode LOCAL \
  --name ephemeral-local-run \
  --region us-east-1

id が返り、ステータスは PENDING から始まります。

実行結果
{
    "arn": "arn:aws:omics:us-east-1:<ACCOUNT_ID>:run/3109928",
    "id": "3109928",
    "status": "PENDING",
    "runOutputUri": "s3://.../output/3109928"
}

コンソールのラン詳細画面でも、ステータスが実行中であることを確認できます。

スクリーンショット

動作確認

get-run でステータスと scratchStorageMode を確認します。

aws omics get-run \
  --id 3109928 \
  --region us-east-1

scratchStorageModeLOCAL で返れば有効化されています。このフィールドは --scratch-storage-mode を明示したランにのみ含まれます。ランは約 5 分 24 秒で COMPLETED になりました。

実行結果
{
    "status": "COMPLETED",
    "scratchStorageMode": "LOCAL",
    "storageType": "DYNAMIC",
    "startTime": "2026-06-29T00:30:38Z",
    "stopTime": "2026-06-29T00:36:02Z"
}

コンソールのラン詳細からも完了を確認しました。

スクリーンショット

完了後、S3 出力から scratch_report.txt を取得します。

aws s3 cp s3://<bucket>/output/3109928/pubdir/scratch_report.txt . --region us-east-1

/tmp がローカル NVMe デバイス /dev/nvme1n1(xfs)に 112 GiB でマウントされています。disk '100 GB' の指定が 16 GiB 刻みで切り上げられ 112 GiB(100 ÷ 16 = 6.25 を 7 に切り上げて 7 × 16)になりました。1 GiB 書き込むと使用量が 839M から 1.9G に増え、ローカルボリュームへ実際に書き込まれていることがわかります。

実行結果
== df -h /tmp (before write) ==
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme1n1    112G  839M  112G   1% /tmp
== mount /tmp ==
/dev/nvme1n1 on /tmp type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,sunit=8,swidth=8,noquota)
== write 1 GiB to /tmp ==
== df -h /tmp (after write) ==
Filesystem      Size  Used Avail Use% Mounted on
+/dev/nvme1n1    112G  1.9G  111G   2% /tmp

タスクごとのメトリクスを記録する manifest ログにも、scratch ストレージの値が出力されます。scratchStorageReservedGiB が 112 で、df で見た 112 GiB と一致します。

実行結果
{
    "cpusReserved": 2,
    "memoryReservedGiB": 4,
    "runningSeconds": 15.94,
    "scratchStorageReservedGiB": 112
}

公式ドキュメントでは使用量を表す scratchStorageUtilizedGiB も記録されるとされていますが、今回の manifest には現れませんでした。タスク実行が 15.94 秒と短くサンプリングできなかった可能性があります。プロビジョニング容量の scratchStorageReservedGiB(112)は出力されていました。

SHARED モードの場合

--scratch-storage-mode を省略するとデフォルトの SHARED になります。同じワークフローを SHARED で実行すると、/tmp の見え方が変わります。

このとき /tmp は専用ボリュームではなく実行ストレージ上に置かれます。今回は実行ストレージに DYNAMIC を使ったため /tmp は NFS(nfs4)になり、スクラッチ I/O はワーキングディレクトリと競合します。disk '100 GB' の指定も無視されています。

実行結果
== df -h /tmp (before write) ==
Filesystem                                                Size  Used Avail Use% Mounted on
127.0.0.1:/e2/...service/tmp                              8.0E     0  8.0E   0% /tmp
== mount /tmp ==
127.0.0.1:/e2/...service/tmp on /tmp type nfs4 (rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,...)

エフェメラルストレージを使うには --scratch-storage-mode LOCAL の指定が必須で、省略すると disk ディレクティブは効きません。

まとめ

AWS HealthOmics のプライベートワークフローで各タスクの /tmp に専用ローカルボリュームをマウントできるようになりました。Nextflow の disk ディレクティブで容量を指定し、--scratch-storage-mode LOCAL を付けてランを実行します。デフォルト 16 GiB は無料で使えます。CPU タスクで LOCAL を省略すると disk が無視され、/tmp は共有 FS になります。

おわりに

ゲノム解析ツールの多くは中間ファイルを /tmp へ書き出したくなるので、エフェメラルストレージの登場でタスク単位の I/O 効率を上げやすくなりました。これは良いアップデート。

参考

この記事をシェアする

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

関連記事