3
0

More than 1 year has passed since last update.

LambdaのPythonライブラリ追加にEFSを使ったときのメモ

Last updated at Posted at 2022-12-07

AWSのLambdaでPythonのライブラリを読み込みたいときに、一番簡単な方法として、ライブラリをzipにしてレイヤーにアップロードするという方法があります。
ただしこれには制限があって、解凍後に500MBまでのファイルしかアップロードできません。
その解決策としては、

  1. EFS(Elastic File System)を使う。
  2. LamdaをDockerにする。

という方法があります。
ここでは、より簡単な、EFSを使う方法をとった時のメモを残したいと思います(自分がやった時のメモなので、より良い方法があるかもしれません)。

まず、インバウンドルールをタイプ:NFS、ポート範囲:2049にしたセキュリティグループを作ります。
スクリーンショット 2022-12-07 6.53.05.png
使用するEFSを用意します。
EFSの管理画面にアクセスし、右上の「ファイルシステムの作成」をクリックします。
スクリーンショット 2022-12-07 6.26.12.png
適当な名前をつけて保存します。VPCはLambdaと同じにします。
スクリーンショット 2022-12-07 6.39.14.png
ファイルシステムができたら、詳細画面の「ネットワーク」タブに移動し、「管理」をクリックします。
スクリーンショット 2022-12-07 7.00.23.png
先ほど作ったセキュリティグループを割り当てて保存します。
スクリーンショット 2022-12-07 7.08.24.png
「アクセスポイント」タブでアクセスポイントを作成します。例ではアクセス権限を777にしていますが、通常は755で良いと思います。
スクリーンショット 2022-12-07 7.12.17.png
アクセスポイントのDNSをコピーしておきます。
スクリーンショット 2022-12-07 7.34.38.png
EFSの作成はこれで完了です。

次に、EFS内に、ライブラリをインストールするディレクトリを用意します。
EFSへのライブラリのインストールはローカルからもできますが、Linuxからの方が良いとどこかで読んだので、今回はAWSのcluod9を使いました。
スクリーンショット 2022-12-07 8.10.32.png
一応アップデート。

$ sudo yum -y update

この原稿の執筆時点ではcloud9にプリインストールされているPythonのバージョンは3.7でした。Lambdaでは3.9を使うので、cloud9にPython3.9をインストールします(Lambdaで使うバージョンに合わせます)。

まず、pythonのバージョン管理を行うpyenvをインストールします。

$ git clone git://github.com/yyuu/pyenv.git ~/.pyenv

pyenvにパスを通します。

$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile

確認。

$ pyenv --version

pyenvでpythonをインストールする際に必要な依存パッケージをインストールします。

$ sudo yum -y install gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel

インストールできるPythonのバージョンを確認。

$ pyenv install -l

python3.9をインストール(例では3.9.15をインストールしています)

$ pyenv install 3.9.15

バージョンを切り替えます。

$ pyenv global 3.9.15

切り替わったか確認。

$ pyenv versions

これで下準備は整ったので、次はEFSをマウントします。
EFSをマウントするディレクトリを作成します。

$ sudo mkdir -p /mnt/efs

作成したディレクトリの所有者とグループを変更。

$ sudo chown -R ec2-user:ec2-user /mnt

先ほど作成したEFSのディレクトリをマウントします。
[EFSのアクセスポイントのDNS]には、先ほどコピーしたEFSのアクセスポイントのDNSを入れてください。

sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport [EFSのアクセスポイントのDNS]:/ /mnt/efs

マウントされていることを確認。

$ df -Th

マウントしたディレクトリに移動し、ライブラリをインストールするディレクトリを作成。
ライブラリをインストールするディレクトリ名はpythonにしないといけないという説があるので(試していないので真偽は不明)、そのようにしています。

$ cd /mnt/efs
$ mkdir -p lib/python

インストールディレクトリに移動。

cd lib/python

必要なライブラリをインストールします(以下は例です)。

$ pip install numpy -t ./
$ pip install pandas -t ./
$ pip install scikit-learn -t ./

次にLambda側の設定を行います。
設定タブのアクセス権限のところにEFSへのアクセス権限がある実行ロールを設定します。
スクリーンショット 2022-12-07 9.37.08.png
次に、VPCを確認します。
セキュリティグループの設定で、EFSとの通信ができるようになっていなければなりません。
スクリーンショット 2022-12-07 9.44.25.png
最後に、ファイルシステムで、先ほど作成したEFSを設定します。
スクリーンショット 2022-12-07 9.49.20.png

ここまでできたら、LambdaにEFSを読み込む記述を追加します。

import sys
sys.path.append("/mnt/efs/lib/python")

import numpy as np
import pandas as pd
etc...

これでEFSにインストールしたライブラリがLamdaから使えるようになります。
ただし落とし穴があって、S3への読み書きをするためのs3fsというライブラリだけは、EFSからの読み込みができませんでした。
原因は不明ですが、とりあえずs3fsだけレイヤーにアップロードするという方法で回避しました。

あと、余談ですが、EFSにファイルを保存するときは、/tmpというディレクトリしか使えません。
これは名前の通り一時保存用のディレクトリで、あるLambdaで保存したものを別のLamdaで読み出して使う、といった使い方はできません。
そういうことをしたい場合は、LambdaのDocker化を行うと良いと思います(そうすれば10GBまでのファイルを保持できます)。
LambdaのDocker化については、別の機会に書きたいと思います。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0