Lambdaで250MB制限を回避するための方法

目次

背景

比較的簡易的な処理を実施するため、Lambda実装を試みたが、いわゆる、Lambdaの250MB制限に引っかかってしまった。
機械学習ライブラリ等でも良くある話と思いますが、今回はOracleDB クライアントライブラリ(古いバージョンのためかサイズが大きい)でも対応が必要となった。
※Pythonかつ古いOracleDBへの接続のため、cx_Oracle + クライアントライブラリ方式を採用せざるをえなかったのですが、現在通常はpython-oracledbが利用できるはずかと

デプロイパッケージ (.zip ファイルアーカイブ) のサイズ
50 MB (zip 圧縮済み、直接アップロード)
250 MB (解凍後)
このクォータは、レイヤーやカスタムランタイムなど、アップロードするすべてのファイルに適用されます。
3 MB (コンソールエディタ)
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/gettingstarted-limits.html#function-configuration-deployment-and-execution

エラー例

ライブラリを入れたLayer追加時に下記のようなエラーが出る。

Layers consume more than the available size of 262144000 bytes

検討内容/結果

現状Lambdaで250MB制限を逃れるには、下記のような方法があります。 (2023年6月現在)

  • ライブラリ容量の削減
    いずれの場合でも実施
  • S3利用
    新規Lambda起動時に都度ダウンロード(要アプリ実装)
  • EFS利用
    Lambdaファイルシステム設定にてマウント
  • ECR利用(コンテナ化)
    コンテナイメージをLambdaで動作させる

Lambdaのコードエディタも利用したいという要望や、リクエストが増えた際のパフォーマンスを考慮し、EFSを採用しました。
(EFS Lambda対応前にコールドスタート時S3からライブラリダウンロード実装前例はあったものの、初回レスポンスが遅い経験があったため)

EFSへのファイル配置/デプロイが継続に必要であれば、下記のような選択もあると思いますが、ほぼほぼ更新されないライブラリのため一時的に立ち上げるEC2でマウント/ファイル配置を選択しました。

AWS Transfer Familyを使用して Amazon EFS ファイルシステム内のファイルにアクセスする

https://docs.aws.amazon.com/ja_jp/efs/latest/ug/using-aws-transfer-integration.html

AWS ソリューションライブラリ - Simple File Manager for Amazon EFS

CloudFormationにて展開する形
https://aws.amazon.com/jp/solutions/implementations/simple-file-manager-for-amazon-efs/

アーキテクチャ図をみると、APIGatewayを利用していたので、Payload10MB制限大丈夫かな?と思ってましたが
実装ガイド に下記記載がありますので、問題なさそうですね、いずれ試してみたいです。

2021 年 7 月時点で、このソリューションを使用したアップロードとダウンロードは、最大 1 GB の
ファイルサイズでテストを行いました。このソリューションではより大きなファイルのアップロードを
サポートしていますが、1 GB を超えるファイルのテストは行っていません。

実装

構成図

EFS

EFSについては、作成時オプションについてはVPCの選択、パフォーマンス・冗長化オプションを設定する必要がありますが基本的にはデフォルトで問題ないと考えます。
また、Lambdaからマウントするためアクセスポイントの設定を実施しましょう。
※ライブラリ配置後は念の為ファイルシステムポリシーで「デフォルトで読み取り専用アクセスを強制する」が良いと思います。

Lambda

ファイルシステム設定

  • EFS ファイルシステム: 上記で作成したEFSファイルシステムを選択
  • アクセスポイント: 上記で作成したアクセスポイントを選択
  • ローカルマウントパス : 今回は右記としました /mnt/oracle-lib

環境変数設定

システムライブラリのパスとしてEFSに配置したライブラリの参照パスをLD_LIBRARY_PATHに追加します。

今回は下記の末尾に /mnt/oracle-lib を追加

/lib64:/usr/lib64:$LAMBDA_RUNTIME_DIR:$LAMBDA_RUNTIME_DIR/lib:$LAMBDA_TASK_ROOT:$LAMBDA_TASK_ROOT/lib:/opt/lib

予約されていない環境変数 - LD_LIBRARY_PATH - システムライブラリのパス を参照
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime

結果

サンプルテーブルから読み出したデータが返却されました。

当然の話ですが、LD_LIBRARY_PATHにEFS上のパスが追加されていないと、Oracle Client Library無しで怒られます。

まとめ

50MB程削れれば、なんとかデプロイ出来るんだけどもな!
と悔しい思いをしつつ、将来的にライブラリは増えることもあるため本構成にて安心出来るようになったのは大きいなと考えることができました。
また、EFSへのファイル配置について、サーバレス構成にしたのにEC2置くのもなぁという点もAWSの提供資材で解消出来そうです。

投稿者プロフィール

takashi
Japan AWS Ambassadors 2023, 2024
開発会社での ASP型WEBサービス企画 / 開発 / サーバ運用 を経て
2010年よりスカイアーチネットワークスに在籍しております

機械化/効率化/システム構築を軸に人に喜んで頂ける物作りが大好きです。

ABOUTこの記事をかいた人

Japan AWS Ambassadors 2023, 2024 開発会社での ASP型WEBサービス企画 / 開発 / サーバ運用 を経て 2010年よりスカイアーチネットワークスに在籍しております 機械化/効率化/システム構築を軸に人に喜んで頂ける物作りが大好きです。