AWS Lambdaのファイルシステムを深掘る

本記事は 夏休みクラウド自由研究 8/31付の記事です

こんにちは、SCSK木澤です。

8/1から始まった夏休みクラウド自由研究も今回で最終回となりました。
今回の企画は幅広いクラウドやソリューションを担当する31名の執筆者にご協力いただき、無事完走することが出来ました。

TechHarmonyは今春に500記事を超え、その後も順調に記事数を増やしています。
今後も色々な企画を考えていきたいと思いますので、どうぞ引き続きご愛顧の程よろしくお願いします。

さて今回は自由研究らしく、普段とは違う話題としてAWS Lambdaのファイルシステムについて調査してみました。

きっかけ

私が本件に興味を持ったのは、5年前に携わった案件に遡ります。

管理しているEC2インスタンスに配布する設定ファイル一式についてユーザー毎/インスタンス毎にカスタマイズする必要があり、調査の上、Lambdaのファイルシステム上で処理してS3に出力することが適切と判断して実装しました。

  1. S3バケットからzipファイルをダウンロードしてzip解凍
  2. 設定ファイルを書き換え
  3. 再度zip圧縮して、S3バケットに書き込み

サーバレスコンピューティングとはいえ、実態としてはサーバーがあるんだなと興味深く当時は思った次第です。
そのあたりをもう少し詳細にお話していきます。

 

動作仕様

Lambdaの動作原理

理解を深めるためにも、Lambdaの動作原理についてから触れたいと思います。
とはいえJAWS DAYS 2022でのAWS(当時)の亀田さんの講演がとても解りやすく私の印象に強く残っているので、こちらから紹介します。

AWS Lambdaは2014年のre:Inventで発表されたものとなりますが、当時はユーザー毎に内部にEC2インスタンスを持つ構成でした。
その後Lambdaの実行に特化した構成としてNitroシステムとFirecrackerが導入され、より強固なアイソレーション(環境分離)と高速・多数の起動環境を実現しています。

実は私はAWSを担当する前に自社クラウドに携わっていたため強く思うのですが、AWS Lambdaのリリース当初はEC2ベース+コンテナの技術レベルであったにも関わらず、お客様(ディベロッパー)にとってあるべき姿を定義し、あるべき価格で(赤字でも?)提供する、そしてその後改善・解決していくという姿はThink BigでありCustomer Obesessionでもあるので感銘を受けたのを覚えています。

話が長くなったので戻しますが、現在AWS LambdaはNitroシステム+Firecrackerで提供されています。
つまりLambdaも小さい仮想サーバー(microVM)という訳です。
よって、当然ながらファイルシステムもあります。

クオータ(制限)についてはこちらをご覧下さい。

Lambda クォータ - AWS Lambda
Lambda 関数および API リクエストに関する最大サイズ、制限、およびクォータです。

ユーザーがLambdaにアタッチできるローカルファイルシステムは、/tmp にマウントされ512MB~10240MBの間で設定可能です。

ウォームスタートとコールドスタート

Lambdaのローカルファイルシステムについて触れる際に、この話は避けて通れません。

Lambdaを起動した際にmicroVMを作成される訳ですが、どうしてもこの初期化作業には一定の時間が掛かります(コールドスタート)。そのため、もし再利用できるmicroVMがあれば再利用してスピードアップするよう動作します(ウォームスタート)

この再利用(ウォームスタート)が発生した際は、前の実行時のファイルがユーザーファイルシステムに残ったままになっています。
ファイル処理を行った際にファイル重複でエラーになる可能性があるのでご注意ください。
実行開始時に一旦すべて削除するか、例外処理を入れる必要があるでしょう。

 

調査

さて、ファイルシステムの詳細を調べてみたいと思います。

容量・パーミッションの確認

デフォルトの設定でLambdaを作成し、以下のコードで実行してみます。
PythonのOSライブラリでOSコマンドを実行しています。

import json
import os

def lambda_handler(event, context):
    # 実行ユーザーを確認
    print("--user")
    print(os.system("whoami"))

    # ディスク容量を確認
    print("--disk capacity")
    print(os.system("df -h"))

    # マウント状態を確認
    print("--mount")
    print(os.system("cat /etc/fstab"))

    # パーミッションの確認
    print("--permisson /")
    print(os.system("ls -al /"))
    print("--permisson /tmp")
    print(os.system("ls -al /tmp"))

    # 書き込み
    print("--write /")
    print(os.system("touch /test1.txt"))
    print(os.system("ls -al /"))
    print("--write /tmp")
    print(os.system("touch /tmp/test2.txt"))
    print(os.system("ls -al /tmp"))

    return {
        'statusCode': 200,
        'body': ''
    }

実行結果を確認します

実行ユーザー
--user
sbx_user1051

当然ながら一般ユーザー権限でユーザープロセスは実行されています

ディスク容量、マウント状態
--disk capacity
Filesystem Size Used Avail Use% Mounted on
/dev/vde 144G 143G 0 100% /
/dev/vdb 1.5G 18M 1.4G 2% /etc/hosts
tmpfs 64M 0 64M 0% /dev
/dev/vdd 525M 8.0K 514M 1% /tmp
/dev/root 9.7G 386M 9.3G 4% /etc/passwd
/dev/vdc 128K 128K 0 100% /var/task

--mount
#
LABEL=/ / auto defaults,noatime 1 1

/tmpはユーザー設定により容量が変わるので、別ディスクとしてマウントされています
ルートディスクはリードオンリーではないですが、書き込み不可となっています。

パーミッション
--permisson /
total 116
drwxr-xr-x 18 root root 4096 Jul 31 08:47 .
drwxr-xr-x 18 root root 4096 Jul 31 08:47 ..
-rw-r--r-- 1 root root 48222 Jul 31 22:38 THIRD-PARTY-LICENSES.txt
lrwxrwxrwx 1 root root 7 Jan 30 2023 bin -> usr/bin
dr-xr-xr-x 2 root root 4096 Jan 30 2023 boot
drwxr-xr-x 2 root root 200 Aug 30 00:50 dev
drwxr-xr-x 34 root root 4096 May 10 11:16 etc
drwxr-xr-x 2 root root 4096 Jan 30 2023 home
-rwxr-xr-x 1 root root 397 Jul 31 15:59 lambda-entrypoint.sh
lrwxrwxrwx 1 root root 7 Jan 30 2023 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Jan 30 2023 lib64 -> usr/lib64
drwxr-xr-x 2 root root 4096 Apr 25 19:25 local
drwxr-xr-x 2 root root 4096 Jan 30 2023 media
drwxr-xr-x 2 root root 4096 Jan 30 2023 mnt
drwxr-xr-x 2 root root 4096 Jan 30 2023 opt
dr-xr-xr-x 123 root root 0 Aug 30 01:40 proc
dr-xr-x--- 2 root root 4096 Jan 30 2023 root
drwxr-xr-x 5 root root 4096 Apr 25 19:25 run
lrwxrwxrwx 1 root root 8 Jan 30 2023 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Jan 30 2023 srv
drwxr-xr-x 2 root root 4096 Apr 25 19:25 sys
drwxrwxrwx 2 root root 4096 Aug 5 15:36 tmp
drwxr-xr-x 12 root root 4096 Jul 31 08:47 usr
drwxr-xr-x 24 root root 4096 May 9 21:46 var

/tmpは権限777のため、一般ユーザーでも書き込み可能です。

ファイル書き込みの確認
--write /
touch: cannot touch '/test1.txt': Read-only file system

当然ながらルートディスクは書き込み不可です。

--write /tmp
total 8
drwxrwxrwx 2 root root 4096 Aug 30 01:40 .
drwxr-xr-x 18 root root 4096 Jul 31 08:47 ..
-rw-r--r-- 1 sbx_user1051 990 0 Aug 30 01:40 test2.txt

/tmpには書き込み可能です。

ファイル入出力速度の調査

さて、ローカルファイルシステム(/tmp)には何も保存されていない訳ですし、データは永続化できません。
よって、S3バケットなどからダウンロードしてきてから処理を行う必要があります
ファイルの入出力時間が気になるので、確認してみます。

S3バケットを作成して、CloudShellから1GBのファイルを作成して保存します。

$ dd if=/dev/zero of=1gb.dat bs=1024k count=1024
$ aws s3 cp 1gb.dat s3://S3バケット名/

以下のようなコードでLambda関数を作成します。

import json
import boto3
import os
bucketname = "S3バケット名"

def lambda_handler(event, context):
    s3r = boto3.resource('s3')

    # /tmp削除
    print("--delete")
    print(os.system("rm -rf /tmp/*"))

    # コピー
    data_bucket = s3r.Bucket(bucketname)
    print("--copy from S3 Bucket Start")
    data_bucket.download_file('1gb.dat','/tmp/1gb.dat')
    print("--copy from S3 Bucket End")

    return {
        'statusCode': 200,
        'body': ''
    }

S3にアクセスできるLambda用IAMロールを作成し、本関数に適用します。
ディスク容量は増やしておきます。

EC2インスタンスと同様、Lambdaにおいてもメモリ容量とCPUスペックは比例するように設計されています。
そこで、メモリ容量≒CPU割り当てとS3からの読み取り速度を調べたところ、以下の通りになりました。(3回平均、CloudWatch Logsに出力されたログのタイムスタンプから算定)

Lambdaメモリ割当量 ダウンロード時間 速度
128MB 74.2秒 110Mbps
256MB 40.4秒 203Mbps
512MB 19.4秒 422Mbps
1024MB 10.7秒 768Mbps
2048MB 10.4秒 785Mbps

メモリ割り当てに比例してネットワークI/O帯域も拡張されること、但し(S3バケットからのダウンロードにおいては)800Mbps弱で頭打ちになることを確認しました。
つまり、/tmpの最大容量10GBのダウンロードもしくはアップロードを行うには、最低100秒程度の時間が掛かることになります。

この辺りがローカルディスクを用いた処理の限界であるであろうことが解りました。

要件満たさない場合はEFS利用

10GBを超える大容量ファイルを扱いたい場合、あるいは永続ファイルをマウントしたい場合はAmazon EFSの利用が可能です。
なお、Amazon EFSはVPC上のサービスですので、LambdaもVPCアタッチが必要となります。

 

まとめ

実に地味な内容でしたが、Lambdaのファイルシステムについて解説・確認しました。
ネットワーク帯域にも変動があることなど、新たな発見があり楽しかったですね。

Lambdaのローカルファイルシステム(/tmp)は非永続ということもあり、ディスク容量は課金には影響しません。
色々使いこなすと楽しいので、皆様もご活用下さい!

著者について
木澤 朋隆

SCSKにてクラウドのアーキテクトやマーケティング/プロモーション、社内の開発者支援等を担当しています。

資格
 AWS認定15冠
 情報処理安全確保支援士・テクニカルスペシャリスト(NW)等
表彰
 AWS Ambassador (2021~)
 Japan AWS Top Engineer (2022~)
 Japan AWS All Certifications Engineer (2022~)
 AWS Community Builder (2023~)

木澤 朋隆をフォローする

クラウドに強いによるエンジニアブログです。

SCSKクラウドサービス(AWS)は、企業価値の向上につながるAWS 導入を全面支援するオールインワンサービスです。AWS最上位パートナーとして、多種多様な業界のシステム構築実績を持つSCSKが、お客様のDX推進を強力にサポートします。

AWS
シェアする
タイトルとURLをコピーしました