💾

Amazon EFSはEBSの代替となるか

2025/02/19に公開

3行でまとめると

  • EFSがEBSの代わりに使えるのか検討する
  • 処理速度は大きく変わらず費用が下がる場合もある
  • 付随する面倒を許容できるのであれば代替できるのでは

概要

Amazon EBSのボリュームサイズをElasticにしたいではEBSボリュームの空きが少なくなった場合に継ぎ足して拡張する方法を検討しました。

https://zenn.dev/zuku/articles/b0cc15ef506776

Amazon EBSはボリューム作成時のサイズに対して費用が発生するため、作成したボリュームのサイズに対し実際に使用されたサイズが大幅に少ない場合に無駄な費用が発生してしまう課題を解消する案でした。

AWSにはAmazon EFSというサービスがあります。EFSは共有のファイルストレージを提供するサービスですが、EBSとは異なり実際の使用容量に対して課金されます。
課金の仕様上無駄が避けられないEBSに対し、EFSは費用面で優位なのか、EBSの代替となるのかを検討します。

検討

EFSにはいくつかの種類があり、大きくは可用性を決める

  • リージョンレベル (マルチAZ)
  • OneZone (シングルAZ)

とスループットを決める

  • エラスティック
  • プロビジョニング
  • バースト

を組み合わせて使用します。

元々の課題が「費用を抑えたい」ですので、可用性の部分では料金の安いOneZoneを選択します。

EFSのスループットモード

EFSのスループットモードには前述の通りエラスティック、プロビジョニング、バーストがあります。

エラスティックスループット

エラスティックスループットモードは自動的にスループットが調整されるモードです。読み書きに対しても課金されます。ap-northeast-1では2025年2月時点で以下の料金が設定されています。(以降の料金も同リージョン/同一時点のもの)

R/W 金額(/GB)
Read $0.04
Write $0.07

入力ファイルが30GBだった場合、ダウンロード時に書き込みで 30 x 0.07 = $2.1 発生し、さらにビデオのエンコードでは基本的に入力ファイルのほぼ全域を読み込むため、エンコード1回あたり 30 x 0.04 = $1.2 発生します。

書き込みだけ見ても、$2.1はEBSのgp3[1]であれば約650GBを1日使った料金になりますので、エラスティックスループットは費用面ではEBSに対し優位になりません。

プロビジョニングスループット

プロビジョニングスループットモードはあらかじめスループットを指定するモードです。指定したスループットに応じて課金されます。

MB/sあたり月$7.20になりますので、100MB/sを設定した場合は1日で$24、1ヶ月で$720です。
プロビジョニングスループットも費用が高くなるため、費用面ではEBSに対し全く優位になりません。

バーストスループット

バーストスループットモードは使用容量に対して付加されたバーストクレジットによってスループットが決まるモードです。使用容量に対する費用のみで、スループットに対する追加の費用は発生しません。

バーストクレジットの仕様について、動画エンコード用途での使用を想定した今回のケースでは以下が関連します。

エンコード処理は基本的に数分から数時間程度で完了し、使用容量も数十GB程度となるため、基準スループットの増量分は当てにできず、最初に割り当てられた2.1TiBのバーストクレジット頼りになり、クレジットを使い切ると遅すぎて使えなくなります。

エラスティックとプロビジョニングが費用面で選択できないため、OneZoneのバーストを選択することになりますが、2.1TiBのバーストクレジットの上限があるため使用方法には考慮が必要です。

EFSの使用方法

EFSはファイル共有用のストレージですので、ひとつ(または少数)のEFSファイルシステムを作り複数のEC2インスタンスからアクセスする1:Nの構成が一般的な使用方法となります。
しかし、今回のケースでは前述のスループット上限があるため1:1の構成にする必要があります。

EFSファイルシステムのスループット上限は100MiB/s(≒800Mbps)ですが、同一リージョンのS3からAWS CLIを使用してのファイルダウンロードでは1,000Mbpsを超えるスループットになる[2]ため、EFSのスループットを使い切ってしまいます。
スループットを使い切っている状態ではlsコマンドの結果表示に数秒待たされるような状態となり、同じファイルシステムにアクセスする他の処理は大幅に速度が低下します。1:N構成ではひとつのインスタンスがファイルをダウンロードしている間、他のインスタンスの処理速度が大幅に低下すると考えられます。

1:1構成にすれば解決しますが、その場合でもバーストクレジットの枯渇問題が残ります。バーストクレジットは2.1TiBあり、1回のエンコードで使い切るケースは限定的ですが、EFSファイルシステムを複数回のエンコードで使い回した場合、いつかはバーストクレジットが枯渇して嘘みたいなスループットに低下します。

従って、今回のような用途でのEFS使用方法は以下の流れになります。

試算

ここまでで既にEBSと比べて面倒なことはわかりましたが、実際にエンコードを行ってみて費用等がどうなるかの試算を行います。

環境

  • EC2インスタンスタイプ
    • c6i.4xlarge
  • OS
    • Amazon Linux 2 (Kernel 5.10)
  • NFSマウント
    • amazon-efs-utils (2.1.0-1)使用
    • mount -t efs -o tls fs-XXXXXXXXXXXX: /data
  • FFmpeg
    • 5.1.1

設定

試算の際の設定と、実際に運用する場合に必要となるであろう設定をこちらでまとめています。

設定方法の詳細

ファイルシステム作成の準備

以下の権限をエンコードを行うEC2に割り当てるロールに追加します。

  • elasticfilesystem:CreateFileSystem
  • elasticfilesystem:CreateMountTarget
  • elasticfilesystem:DescribeFileSystems
  • elasticfilesystem:DescribeMountTargets
  • elasticfilesystem:DeleteFileSystem
  • elasticfilesystem:DeleteMountTarget
  • elasticfilesystem:TagResource

セキュリティグループの作成

EFSファイルシステム(のマウントターゲット)に接続できるようにするためのセキュリティグループを作成します。

  • インバウンド
    • Protocol: TCP
    • Port: 2049 (NFS)
    • Source: NFSクライアントEC2のセキュリティグループ
  • アウトバウンド
    • Protocol: Any
    • Port: Any
    • Destination: NFSクライアントEC2のセキュリティグループ

ファイルシステム作成

ファイルシステムを作成します。AVAILABILITY_ZONEにはこのコマンドを実行するEC2があるAZを指定します。
OneZoneにするためには--availability-zone-nameパラメータの指定が必要ですが、古いAWS CLIでは対応していません。(恐らくAWS CLI v1.19.24から対応)
後述する理由により、ルールを決めてタグを設定した方が良いです。
作成に成功するとFileSystemIdを含む結果が返ります。IDは後続の処理で使用します。

CREATION_TOKEN=`uuidgen`
aws efs create-file-system \
	--region ${REGION} \
	--creation-token ${CREATION_TOKEN} \
	--performance-mode generalPurpose \
	--availability-zone-name ${AVAILABILITY_ZONE} \
	--no-encrypted \
	--no-backup \
	--throughput-mode bursting \
	--tags "Key=Tag1,Value=Value1" "Key=Tag2,Value=Value2"

作成直後はLifeCycleStatecreatingになります。describe-file-systemsを繰り返し実行して、この値がavailableになるまで待機します。

aws efs describe-file-systems \
	--region ${REGION} \
	--file-system-id ${FILE_SYSTEM_ID}

マウントターゲット作成

作成したファイルシステムに対してマウントターゲットを作成します。

aws efs create-mount-target \
	--region ${REGION} \
	--file-system-id ${FILE_SYSTEM_ID} \
	--subnet-id ${SUBNET_ID} \
	--security-groups ${SECURITY_GROUP}

マウントターゲットも作成直後はLifeCycleStatecreatingになります。describe-mount-targetsを繰り返し実行して、この値がavailableになるまで待機します。

aws efs describe-mount-targets \
	--region ${REGION} \
	--file-system-id ${FILE_SYSTEM_ID}

マウント

EC2インスタンスでファイルシステムをマウントします。

mount -t efs -o tls ${FILE_SYSTEM_ID}:/ /mount-point

マウント完了後にエンコード等の処理が行えます。

アンマウント

ファイルシステムをアンマウントします。

umount /mount-point

マウントターゲット削除

ファイルシステムを削除する前にマウントターゲットを削除します。

aws efs delete-mount-target \
	--region ${REGION} \
	--mount-target-id ${MOUNT_TARGET_ID}

削除が完了するまでに時間がかかるためdescribe-mount-targetsを繰り返し実行して、削除の完了(結果のMountTargetsが空の配列になる)を待ちます。

aws efs describe-mount-targets \
	--region ${REGION} \
	--file-system-id ${FILE_SYSTEM_ID}

ファイルシステム削除

ファイルシステムを削除します。削除が完了するまでに時間がかかりますが、後続処理はないので完了の待機は不要です。

aws efs delete-file-system \
	--region ${REGION} \
	--file-system-id ${FILE_SYSTEM_ID}

放置されたファイルシステムの監視

エンコード処理の途中でスポットインスタンスが終了するなどするとEFSファイルシステムは削除されずに残ってしまいます。ファイルシステム内にファイルが存在する場合は費用が発生し続けますので、放置されたファイルシステムを発見、削除する処理の定期実行が必要です。

  1. EFSファイルシステムのリストを取得しタグを手がかりに対象を絞り込む
  2. 作成日時を調べて作成直後のファイルシステムを除外
  3. 残った各ファイルシステムのクライアント接続数をCloudWatchから取得して0だったら放置されていると判定
  4. 放置されているファイルシステムを削除

EBSの場合はEC2にアタッチされているかどうかで使用中かを判定できますが、EFSの場合はその性質から上記の不安感のある方法で判定するしかない気がします。

入力ファイル

項目
解像度 1920x1080
フレームレート 29.97
再生時間 30:00
ファイルサイズ 32,338,408,042B (30.12GiB)
Codec (V) Apple ProRes 422
Codec (A) LPCM 24bit 44.1kHz
コンテナ QuickTime

EC2と同じリージョンのS3に設置してAWS CLIでダウンロードします。

出力

ビデオコーデックにはH.264/AVCを使用し通常のMP4で出力します。組み合わせはYouTubeのHLS向けを参考にして決めています。

名前 ビットレート Profile
144p 170kbps Main
240p 300kbps Main
360p 800kbps Main
480p 1300kbps Main
720p 1800kbps High
1080p 4700kbps High
audio 128kbps AAC-LC

2-passエンコードを行い、都度1-passで出力されたログファイルを削除しています。
動画配信用のエンコードであればエンコード後に配信用形式(MPEG-DASH等)への変換やアップロードを行いますが、今回の試算では省略しています。

詳細な出力設定
BITRATE BUFSIZE HEIGHT PROFILE
170k 340k 144 main
300k 600k 240 main
800k 1600k 360 main
1300k 2600k 480 main
1800k 3600k 720 high
4700k 9400k 1080 high

Video

ffmpeg -i ${INPUT} -c:v h264 -b:v ${BITRATE} -maxrate ${BITRATE} -bufsize ${BUFSIZE} \
    -tune film -preset medium \
    -force_key_frames "expr:gte(n,n_forced*90)" \
    -x264-params "min-keyint=90" \
    -vf "format=yuv420p,scale=-2,${HEIGHT}" \
    -profile:v ${PROFILE} \
    -an \
    -pass 1 -f null /dev/null

2-pass

    -pass 2 ${OUTPUT}

Audio

ffmpeg -i ${INPUT} -vn -c:a aac -b:a 128k ${OUTPUT}

結果

EFSファイルシステムを使いエンコードを行った場合の結果は以下になります。参考としてEBS[3]を使った場合の所要時間も併記しています。

項目名 所要時間 出力ファイルサイズ (参考)EBS所要時間
ダウンロード 05:27 30.12GiB 03:31
144p 04:06 36.68MiB 07:21
240p 04:42 64.28MiB 04:46
360p 05:44 170.74MiB 05:49
480p 07:15 277.51MiB 07:28
720p 10:00 383.76MiB 11:03
1080p 17:17 1,004.70MiB 18:12
audio 00:28 28.18MiB 00:28
合計 54:59 32.04GiB 58:38

ダウンロードはEFSよりEBSが高速ですが、エンコードはEFSがEBSよりやや高速になっています。
EBSの144pエンコードが極端に遅くなっているのは1-pass目のエンコードに特に時間がかかっているためです[4]

時間経過に伴うEFS使用容量のグラフです。このグラフの青で塗られた部分の面積がEFS費用の概算となります。

EFS使用容量の推移

費用を計算するとおよそ$0.00756となりました。

考察

速度

EFSとEBSを比較すると、ファイルのダウンロード(書き込み)ではEBSの方が高速でした。これはEBS(gp3)のスループット125MiB/sがEFSのスループット100MiB/s[5]を上回るためです。

一方、エンコードではEFSの方がEBSよりもやや高速でした。エンコード中のデータ転送量推移から、次のような状態になっているのではないかと推測しています。

  • EFS
    • クライアント(EC2インスタンス)にファイルの内容はキャッシュされない
    • エンコード中は常にEFSから入力ファイルを読み込む
    • エンコーダが要求する入力ファイル読み込みのスループットは上限の300MiB/sよりも低いのでEFSはボトルネックにならない
  • EBS
    • クライアントにファイルの内容がキャッシュされる(ページキャッシュ)
    • c6i.4xlargeのメモリ32GBは入力ファイル全体がギリギリキャッシュに乗るか乗らないかのサイズ
    • キャッシュにないファイルの部分が要求された時EBSから読み込む
    • エンコーダが要求するスループットが上限の125MiB/sを上回る場合(144p)があるためEBSがボトルネックになり処理速度が低下する
    • EBSがボトルネックになっていないはずの720p, 1080pが微妙に遅い理由は不明
    • AWS CLIでのファイルダウンロード直後にキャッシュに乗ってないように見える理由は不明

EFS
EFSのデータ転送量推移

EBS
EBSのデータ転送量推移 (最後の部分は欠測)

速度については条件次第でEFSとEBSのどちらが有利になるかが変わってきますが、入力ファイルのサイズが大きく高速にダウンロードできる場所にある場合はEBSが有利で、そうでなければ速度面でEFSはEBSに対してやや有利です。

バーストクレジット

CloudWatch BurstCreditBalanceの差分によると、試算で行った処理の前後でバーストクレジットは150.10GiB消費されていました。

エンコードでは以下のRead/Writeによりバーストクレジットが消費されると考えられます。

  • ダウンロード
    • Write: 入力ファイル
  • エンコード 1-pass
    • Read: 入力ファイル(対象ストリーム)
    • Write: パスログファイル
  • エンコード 2-pass
    • Read: 入力ファイル(対象ストリーム), パスログファイル
    • Write: 出力ファイル

試算時に生成されたファイルサイズ[6]を当てはめて計算すると152.18GiBになり、BurstCreditBalanceが示した値とほぼ一致しました。

試算では再生時間30分の動画をエンコードしましたが、入力ファイル、出力ファイルと恐らくパスログファイルのサイズは再生時間に比例して増えます。再生時間とバーストクレジット消費量のおおよその関係をグラフにしました。

再生時間によるバーストクレジット消費量

入力ファイルのビットレートとして試算時と同じProRes 422の147Mbpsの他に、納品用として使われることの多いXDCAM MPEG HD422の50Mbpsと、ProRes 422 4K 24fpsでの503Mbpsも加えています。

2.1TiBに到達するのは50Mbpsの場合は19時間20分くらい、147Mbpsの場合は6時間50分くらいですので一部の長編以外ではクレジットは枯渇しませんが、503Mbpsの場合では2時間くらいですので一般的な映画でも枯渇する可能性があります。

費用

今回の試算では、EFSでの概算費用は$0.00756でした。
一方、EBSを40GBで59分使用した場合の費用は$0.00524[7]でした。実際の使用容量に対してほぼ無駄がない40GBではEBSの方が安くなりますが、60GBだった場合は$0.00787でEFSとほぼ同額になります。

入力ファイルのサイズが出力ファイルに対して十分に大きい場合、EFSの費用は入力ファイルサイズに処理時間を掛けたものに近く[8]なりますので、非常に非常に雑に計算すると結局EFSとEBS(gp3)の単価の差(2倍)がそのまま費用になります。
つまり EFSの費用 ≒ 実際の使用容量の2倍確保したEBSの費用 です。

実際の使用容量が各エンコードの間でほぼ一定であったりEBSのサイズを自動拡張する運用をしていないのであれば、平均して2倍以上余裕のあるEBSサイズを確保することは十分にあり得ますので、EFSはEBSに対して費用面で有利になるケースは少なくないと考えられます。

まとめ

動画エンコードを行うEC2インスタンスのストレージをEBSからEFSに変更した場合、費用は下がるのか、どのような課題があるのかを調べました。

前提条件によりますが、EBSのサイズを容量不足を恐れずに決めているのでなければEFSの方が費用が安くなりそうです。
書き込みスループットは若干遅いですが、読み込みは(スループット非課金の)EBSより高速で、全体の処理時間はほとんど変わりませんでした。

EBSボリュームに比べてEFSのファイルシステムは作成や削除の手順が多く(途中で失敗する可能性が高く)なります。EBSと異なりEC2の終了とともに自動削除されないため、スポットインスタンスの中断時[9]などに放置されて費用が発生し続けることを避けるための仕組みが必要になります。
バーストクレジットの初回割当分を使い切ると実質使えなくなるため、一連のエンコード処理ごとにファイルシステムを使い捨てる使い方になります。また、入力ファイルサイズが大きい、再生時間が長い、出力するファイル数(帯域)が多いなどの要因でクレジットが枯渇する可能性があります。

EFSはEBSの代替となるかに対する回答は「条件次第ではなる、しかし色々と面倒」です。

脚注
  1. $0.096/GB 月 ↩︎

  2. EBSボリュームに対して書き込みを行った場合 旧世代の小さいインスタンスでは800Mbpsを超えない場合もある ↩︎

  3. gp3 ↩︎

  4. EFS 01:59 / EBS 04:49 ↩︎

  5. 厳密には101MiB/s ↩︎

  6. 入力ファイルのストリームごとのサイズは Video 98.53% / Audio 1.47% で計算 ↩︎

  7. gp3 (0.096 / 30 / 24 / 60) * 59 * 40 ↩︎

  8. 今回の試算では実際の費用に対して10%増 ↩︎

  9. 中断通知を確認することである程度緩和は可能 ↩︎

Discussion