AWSLamdbaのエフェメラルストレージ10GB拡張を試してみた

# まえがき
普段サーバサイドエンジニアをしています。
今回はじめてQitaに記事を掲載します。

# 概要
3/24のLambdaのアップデートにてエフェメラルストレージが最大10GBまで対応できるようになったため、実際に使ってみました。
https://aws.amazon.com/jp/about-aws/whats-new/2022/03/aws-lambda-configure-ephemeral-storage/

元々Lambdaには「ファイルシステム」からEFSを設定することが可能でしたが、
VPCに接続する必要があったり、スループットが必要な案件ではかなり高価なEFSを使う必要がありました。

# 設定
マネージメントコンソール上の「設定」から「一般設定」に「エフェメラルストレージ」が増えており、
こちらから更新すること可能ですが、既にServerless frameworkで対応されていましたので、こちらからデプロイしてみたいと思います。
※「エフェメラルストレージ」の機能を使用するにはServerless framework 3.10.0以上を使用する必要があります。

https://github.com/serverless/serverless/releases/tag/v3.10.0

まずはserverless projectを作成します。
```bash
# serverless version up
$ npm install -g serverless

52 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

$ serverless --version
Framework Core: 3.10.2
Plugin: 6.2.0
SDK: 4.3.2

$ serverless create --template aws-python3 --path EphemeralStorageSizeTest
✔ Project sucessfully created in "EphemeralStorageSizeTest" from "aws-python3" template (5s)

cd EphemeralStorageSizeTest
```

つぎにserverless.ymlを開き、ephemeralStorageSizeを追加します
``` serverless.yml
functions:
  hello:
    handler: handler.hello
    ephemeralStorageSize: 10240 # <- 追加

```
Lambda内の容量を確認するため、handler.pyも更新しておきます。

```handler.py
import json
import subprocess <-追加


def hello(event, context):
    # 以下を追加
    out = subprocess.run('df', stdout=subprocess.PIPE)
    print(out.stdout.decode())
```

準備ができたのでdeployをします。
```bash
$ serverless deploy
Deploying ephemeralstoragesizetest to stage dev (us-east-1)

✔ Service deployed to stack ephemeralstoragesizetest-dev (128s)

functions:
  hello: ephemeralstoragesizetest-dev-hello (440 B)
```

マネージメントコンソールから「Lambda」 -> 「一般タブ」 -> 「一般設定」からエフェメラルストレージを確認します。10GBに変わっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511411/336f3ee3-b608-5ad7-23a2-a4dbc8950ff6.png)
Lambdaを実行してみます。
「テストタブ」-> 「テスト」を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511411/0414bcf3-e79a-c7f8-5731-cfb5df0f1648.png)
/tmp領域が10GBになっていることが確認できました。

# エフェメラルストレージ
今回の拡張とは関係ないですが、エフェメラルストレージの挙動を確認します。
Lambdaが消えたタイミングで`/tmp`フォルダに保存されているファイルは削除されるはずです。
またLambdaがホットリロード間はそのまま保存されているはずです。
handler.pyを修正して確認してみます。
``` handler.py
    test_file = pathlib.Path('/tmp/test.txt')
    print(test_file.exists())
    if not test_file.exists():
        test_file.touch()
        print('test_file created')
```
1回目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511411/7b9ddaf6-8e42-74e8-26bf-30080fce02c3.png)
2回目（ホットスタンバイ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511411/d93c0c7c-ce09-bbc5-b7c4-a1ee822ecbad.png)
ファイルが存在しているので、ホットスタンバイ間は保持されます。

しばらく放置し、コールドスタートした場合は再びファイルが作成されました。
別のエフェメラルストレージが割り当てられることがわかりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511411/5c9e14c6-d32f-7b84-a322-9c3f73e8a564.png)

# 速度
料金的には汎用SSD(GP3)相当ではあったので、既存のEFSと速度比較をしてみました。

Lambda上でテストファイルを /tmpディレクトリ配下に保存し削除されるまでの時間を計測します。

```handler.py
    os.chdir('/tmp')
    start = time.time()
    out = subprocess.run('dd if=/dev/zero of=text.txt bs=1M count=10000', stdout=subprocess.PIPE, shell=True)
    print(out.stdout.decode())
    out = subprocess.run('df -h', stdout=subprocess.PIPE, shell=True)
    print(out.stdout.decode())
    test_file = pathlib.Path('/tmp/text.txt')
    print(f'The file size is: {test_file.stat().st_size /  1024 / 1024} MBytes')
    os.remove('/tmp/text.txt')
    print(f'text_file exists?: {test_file.exists()}')

    elapsed_time = time.time() - start
    print(f'elapsed_time:{elapsed_time}[sec]')

```
エフェメラルストレージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511411/00c1a4bf-1f0e-435f-3048-9c2227491024.png)

EFSを利用した場合（スループットモード：プロビジョニング 10MB）
※EFSの設定は割愛しますが、VPC、EFSファイルシステム、Lambdaの設定を追加しています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511411/e5db06cc-b0e5-9f20-8c95-3af68466edc3.png)

EFSの場合スループットを下げた要因もありますが、エフェメラルストレージ 829MB/sとEFS 10MB/sとなり、
かなりの差が生まれました。
エフェメラルストレージの10GBまでの引き上げにより、EFSのスループットを上げずに速度改善も見込めるのではないでしょうか？

## 料金
東京リージョン GB-秒あたり 0.000000037USDとなっています。

１日1並列エフェメラルストレージ10GBで動かしてもストレージ分の費用は$0.031968(0.000000037 * 60[秒] * 60[分] * 24[時間] * 10[GB])なので、導入しやすいのではと思いました。

## まとめ
一時的なファイルが512MBを超える可能性があるケースでLambdaにEFSを使用していたケースなどは、
大幅な速度改善、費用軽減が見込めるのではないでしょうか？
また万が一512MBを超える可能性があるケースなども費用が安いので、保険としてエフェメラルストレージを増やしておくのも手かなと思います。

ただLambda特有のホットスタンバイの際はファイルは残ることを念頭にファイル操作する必要があります。
（今回のエフェメラルストレージの拡張とは関係ないですが）