話題の記事

[アップデート] Lambda から共有ファイルストレージの EFS が利用可能になりました!

ファイル連携、めっちゃ楽。アーキテクチャの幅がまた広がるアップデートです。
2020.06.17

本日のアップデートで Lambda から EFS が利用可能になりました!

何が嬉しいのか

S3 を介さないファイル連携

Lambda でファイル連携を行うには一般的に S3 を介して利用されてきましたが、そもそも連携するためには連携させたいシステムが S3 にアクセスできるような仕組みになっている必要がありますが、オンプレからそのまま AWS に移行してきたようなシステムの場合、S3 へアクセスするための改修にハードルを感じる方も少なからず居られたかと思います。

今回、EFS に対応したことで単純にファイルシステムとしてファイル連携することが可能となりますので、そういった改修をせずとも Lambda と連携させた処理が実装しやすくなるのではないでしょうか。

結果整合性の回避

S3 を介することでどうしても付きまとう制約は S3 の仕様である「結果整合性を許容する」ことでしたが、EFS はその名のとおりファイルシステムなので結果整合性ではなく必ず最新状態の内容が取得できますし、ファイルロックもされます。S3 の特性でもある結果整合性が許容できずにサーバレスアーキテクチャを見送ったようなシステムでも Lambda & EFS のサポートによって再検討することが出来るかもしれません。

柔軟なファイル連携

最近、Fargate でも EFS がサポートされるようになりましたので、コンテナ、Lambda 間でのファイル連携も非常に容易に実装できるのは嬉しいですね。

大規模なライブラリの利用

またサービス間でのファイル連携以外にも、Lambda ではデプロイパッケージサイズとして解凍後のサイズが 250 MB までという制限がありますが、高度な処理をするための大規模なライブラリーの置き場として EFS を利用することで、このような制限をうけることなくライブラリをロードすることが出来そうです。

大容量のデータロード

Lambda の /tmp ディレクトリのストレージは 512 MB までという制限がありますが、EFS を利用することでこの制限を回避し、大容量のデータロードを Lambda で行うことも可能となりました。

利用するうえでの制約

以下のような制約がありますので、ご注意ください

  • EFS と Lambda は同一リージョンであること
  • EFS へのアクセスには EFS アクセスポイントが必要
  • VPC 内のローカルネットワークを介してアクセスするため、VPC Lambda である必要があります

やってみる

事前準備

マウント先となる EFS は事前に作成しておきます。セキュリティグループには Lambda にアタッチするセキュリティグループ lambda-sg から 2049 ポートのみを許可しています。

また、Lambda 関数から EFS にアクセスするためには EFS アクセスポイントが必要となりますので作成しておきます。EFS アクセスポイントによって Lambda 関数からアクセスする際のユーザ ID や、読み込み専用に制限したり、暗号化を強制するなどの指定をすることが可能となります。

Lambda 関数の作成

今回は Python3.8 で作成しています。Lambda の実行ロールには公式ドキュメントに従い、EFS に接続するために必要となる権限がある AmazonElasticFileSystemClientReadWriteAccess ポリシー をアタッチしています。

AmazonElasticFileSystemClientReadWriteAccess

"Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "elasticfilesystem:ClientMount",
                "elasticfilesystem:ClientWrite",
                "elasticfilesystem:DescribeMountTargets"
            ],
            "Resource": "*"
        }
    ]
}

Lambda 関数は以下のとおり VPC Lambda として構成し、セキュリティグループには EFS のセキュリティグループで許可されている lambda-sg をアタッチしています。lambda-sg のインバウンドルールは特になにも書いていません。

ファイルシステム設定

Lambda の構成メニューに [File system] という項目が追加されていますので、[Add file system] をクリックします。

事前作成済みの EFS および、EFS アクセスポイントを指定します。ローカルマウントパスは /mnt/ から始まるパスを指定し、[Save] します。

これで設定は完了です。

アクセスしてみる

事前に EFS には以下のようなファイルを置いています。配置先が efs/my-function となっていますが、これは EC2 からは EFS アクセスポイントを経由させていないためです。

$ pwd
/home/ec2-user/efs/my-function
$ cat efstest.txt
Hello!Classmethod!!

Lambda 関数は以下のように単純な読み書きをするだけの関数です。Hello!Classmethod!! が表示され、ファイルの内容が Developers.IO 2020 CONNECT!! に変わっていれば成功ですね。

注意いただきたいのは path = '/mnt/efs/efstest.txt' であることです。Lambda 関数からは EFS アクセスポイントを介してアクセスしているため my-function は不要です。(実体としては EFS のルートディレクトリ直下の my-function にアクセスしています)

def lambda_handler(event, context):
    path = '/mnt/efs/efstest.txt'
    with open(path) as f:
        print(f.read())

    s = 'Developers.IO 2020 CONNECT!!'

    with open(path, mode='w') as f:
        f.write(s)

    with open(path) as f:
        print(f.read())

この関数をテスト実行しますと…

意図したように表示されていますね!EC2 から EFS のファイル内容を確認すると…

$ pwd
/home/ec2-user/efs/my-function
$ cat efstest.txt
Developers.IO 2020 CONNECT!!

ファイルの内容が上書きされていますので Lambda 関数から EFS 内のファイルを正常に読み書きできることが確認できました。

検証は以上です!

EFS のパフォーマンス

S3 と違って EFS のパフォーマンスはユーザー側で指定する必要があります。EFS のパフォーマンスはコストに直結してきますので、EFS のパフォーマンス設定についての仕組みを理解しておく必要があるかと思います。

さいごに

Lambda から共有ストレージである EFS が利用できるようになり、柔軟なファイル連携が可能となりました。また従来の S3 を仕様したファイル連携では結果整合性であることを意識する必要がありましたが、EFS を使うことで確実に最新状態のファイルが利用できるという部分もメリットになりそうです。

今回は試していませんが EFS に大規模なライブラリを配置してロードするような利用もできそうです。

また新たなアーキテクチャが産まれる大きなアップデートとなりそうですね!

以上!大阪オフィスの丸毛(@marumo1981)でした!