AWS EFSのバーストクレジットとスループットの算出方法について調べてみた

ある日、CloudWatch のメトリックスを確認していたところ、あることに気づきました。

# EFSのバーストクレジットが減っている！
![burstcredit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1352206/a8c5ef50-e845-6c01-fdeb-1857b472c50f.png)

ECS の永続的データの保管領域として利用している EFS において、バーストクレジット (BurstCreditBalance) が徐々に減少していることに気づきました。

## EFSにおけるバーストクレジットとは
詳細については以下のドキュメントに記載があります。

* [Amazon EFS パフォーマンス](https://docs.aws.amazon.com/ja_jp/efs/latest/ug/performance.html)
    * 原文: [Amazon EFS performance](https://docs.aws.amazon.com/efs/latest/ug/performance.html)

上記のドキュメントから大事な点をピックアップすると、以下になります。

* EFSではバーストクレジットというものがある
* ファイルサイズによって決定されるベースラインレートがある
    * ベースラインレートを超えると、このバーストクレジットを消費してスループットをバーストさせることが可能
* バーストクレジットが枯渇した場合、スループットをバーストさせることができない
    * ベースラインレートまでしかスループットを出すことができなくなる
* バーストクレジットは以下の場合で回復する
    * 使用していない場合
    * スループットがベースラインレートを下回っている場合
    * スループットがプロビジョニングスループットを下回っている場合
* ベースラインレートは1TiBあたり50MiB/s
    * 書き込みのベースラインレートは1GiBあたり50KiB/s
    * 読み込みのベースラインレートは1GiBあたり150KiB/s
        * 書き込みの3倍で計算される
* バースト可能な最大スループットは1TiBまでは一律100MiB/s
    * 最大値は1TiBを超えると、1TiBあたり100MiB/s追加される
* バーストクレジットは作成時では初期の最大値である2.1TiB支給される

つまるところ、作成時から支給されたバーストクレジットを徐々に消費してきていたということがわかりました。
またバーストクレジットが枯渇してしまった場合、スループットをバーストさせることができず、アプリケーションによっては動作に影響を与える可能性があります。

# 実際のスループットを調べてみる
実際のスループットはCloudWatchからすぐに求めることができません。CloudWatchのMath Metricを利用して、計算することで求めることが可能となります。

スループットの計算式についてはドキュメントから引用します。

> ## Metric Math スループット (MiB/秒)
> ある期間の平均スループット (MiB/秒) を算出するには、最初に合計の統計 (DataReadIOBytes、DataWriteIOBytes、MetadataIOBytes、または TotalIOBytes) を選択します。次に、値を MiB に変換して、その期間の秒数で割ります。
> 
> たとえば、このようなロジックがあるとします: (TotalIOBytes の合計 ÷ 1048576 (MiB に変換するため)) ÷ その期間の秒数
> 
> この場合、CloudWatch のメトリクス情報は次のようになります。
> 
> | ID | 使用可能なメトリクス | 統計 | 間隔 |
> |:---|:-------------------|:-----|:----|
> | m1 | DataReadIOBytes <br> DataWriteIOBytes <br> MetadataIOBytes <br> TotalIOBytes | Sum | 1m |
> 
> ユーザーの Metric Math ID と式は以下のようになります。
> 
> | ID | 使用可能なメトリクス      |
> |:---|:------------------------|
> | e1 | (m1/1048576)/PERIOD(m1) |
> 
> [Amazon EFS でのメトリックス計算の使用 - Metric Math スループット (MiB/秒)](https://docs.aws.amazon.com/ja_jp/efs/latest/ug/monitoring-metric-math.html#metric-math-throughput-mib)

## 実際に計算してみた
実際に計算してみました。

1. CloudWatchのメトリクス - すべてのメトリクスから対象のEFSのIDと、上記ドキュメントに記載があったメトリクスを選択します
1. グラフ化したメトリクスの左上にある `数式` から `空の数式` を選択し、ドキュメントに従って `ID` や `詳細` を記載します
    1. 必要に応じてラベルに値を設定します

私の場合は以下のような形になりました。(対象のEFS IDはぼかしを入れています。)
![metrics.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1352206/cfe5ad8f-fede-fced-0af9-dce8a4d32a96.png)

そしてグラフの結果は以下のとおりとなりました。(一部考察などで利用した補足用の情報も含まれています)
![throughput.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1352206/6da66d6a-4490-44a8-f4ec-63f3e98c76a1.png)

### グラフの考察
現在利用しているEFSの容量は以下のとおりでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1352206/68d0b683-9657-7501-28f4-9c31f8ed35d7.png)

合計サイズは `611.85MiB` なので、ベースラインレートは 50KiB/s となります。
値を見ていくと、 `TotalIO` のスループットはだいたい 125KiB/s 程度でした。ちなみに、`DataReadIO` より `DataWriteIO` のスループットが圧倒的に占めていました。 [^1]

[^1]: `TotalIO` ≒ `DataWriteIO` の勢いでした

### 対応
このままだと、いつかはバーストクレジットを使い切り、使い物にならなくなる未来があるため、スループットモードをプロビジョニングモードに切り替えます。
なお、有料となり、東京リージョンの場合は1MiB/s確保すると7.2USDかかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1352206/d7de01d2-395d-a50e-21ab-1369916f872d.png)

結果としてスループットは変わらず、バーストクレジットが回復していました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1352206/fa586d65-bdd7-4a33-dd9d-fbec78b7150e.png)

最初のグラフで1MiB/sだと余裕があるため、バーストクレジットが回復しています。ドキュメント通りですね。


またアプリケーションの運用によっては今の状況から変わるかもしれず、結果として、バーストクレジットを再び消費していく可能性もありますので、[メトリクスアラーム](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html)を設定して、バーストクレジットが減少していっていることを検知できるようにした方が良いかもしれません。

# まとめ
スループットモードがバーストのEFSを使ったシステムを作ったらしばらくはバーストクレジットの量を確認し、必要に応じてスループットモードをプロビジョニングすることを検討した方がよさそうです。

この記事がプロビジョニングスループットの必要量の算出に役立てば幸いです。