目次
背景
比較的簡易的な処理を実施するため、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の提供資材で解消出来そうです。