Amazon EC2でAWS Lambdaのレイヤーを作成しアップロードする【Python】
今回はAWS LambdaのレイヤーをAmazon EC2で作成しレイヤーとして追加する方法を整理していきます。
Pythonのレイヤー作成を想定していますので、他言語の場合は適宜読みかえるか参考としているAWS公式ドキュメントを参照してください。
EC2用のロール作成
EC2で作成したレイヤーをLambdaにアップロードするのでEC2にLambdaにファイルをアップロードする権限を持たせなければいけません。
IAMのロールから新しいロールを作成します。
ユースケースでEC2を選択し次へ
以下のマネージドロールを選択してロールを作成します。
AWSLambda_FullAccess
AmazonSSMManagedInstanceCore
AWSLambda_FullAccess
→Lambdaに対する全権限を付与します。
AmazonSSMManagedInstanceCore
→今回EC2にはセッションマネージャーで接続するので必要です。
このロールではCloudWatchへのログ出力ができないのでしたい方は別途権限を追加してください。
EC2の起動
EC2インスタンスを立ち上げます。
AWS LambdaはAmazon Linuxで実行されているのでAMIにはAmazon Linuxを選択するのが無難でしょう。
今回はAmazon Linux 2023を使用しました。
インスタンスタイプやデプロイ先には特に指定はありません。
無料枠のt2.microでもデフォルトVPCでも大丈夫です。
先ほど作成したIAMロールを付与するため高度な詳細のIAMインスタンスプロフィール(多分プロファイル)で作成したIAMロールを選択してください。
もし、立ち上げ時にIAMロールを設定し忘れた場合もインスタンスの詳細からEC2インスタンスに付与されているIAMロール名をクリックすることで権限の変更が可能です。
インスタンスが立ち上がったらセッションマネージャーで接続します。
開発環境の作成
Lambda関数を作成するときにランタイムを選択すると思います。
編集時点ではPythonだと3.9~3.13まで選べます。
ライブラリの依存関係の都合から作成するレイヤーも使用したいPythonバージョンで作成するのが無難でしょう。
まずはAmazon Linuxを最新の状態にしてPythonのバージョンを確認します。
sudo yum update -y
sudo python3 -version
編集時点では3.9.20が入っていました。
Python3.9のレイヤーを作成する場合はこのまま次のステップに進んでよいのですが、
異なるバージョンのレイヤーを作成する場合は希望のバージョンをインストールする必要があります。
複数バージョンのPythonをインストールするためにpyenvというツールを使用します。
https://qiita.com/DASHi/items/b03d3efd401260d8add4
pyenvのインストール
#gitコマンドを使うのでgitのインストールから
sudo yum install git -y
#pyenvのインストール
sudo git clone https://github.com/pyenv/pyenv.git ~/.pyenv
pyenvをインストールしたら動作させるための初期設定を行っていきます。
#pyenvがインストールされた場所を確認
ls -ld ~/.pyenv
Amazon Linux 2023にSSM接続している場合以下のように出力されると思います。
sh-5.2$ ls -ld ~/.pyenv
drwxr-xr-x. 12 root root 16384 Jan 1 05:07 /home/ssm-user/.pyenv
/home/ssm-user/.pyenv
がインストール先なのでこの部分を控えてください。
#フォルダの所有権を接続しているユーザー(今回はssm-user)に変更させる
sudo chown -R ssm-user:ssm-user /home/ssm-user/.pyenv
所有権をrootから作業ユーザーに変更したら設定ファイルを編集していきます。
#設定ファイルの編集画面を開く
sudo nano /etc/profile
コマンドを実行するとnanoエディタでテキストが開かれるので一番下に以下の設定を追記してください。
#"/home/ssm-user/.pyenv"の部分は先ほど控えたpyenvのインストール先です
export PYENV_ROOT="/home/ssm-user/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$($PYENV_ROOT/bin/pyenv init --path)"
eval "$($PYENV_ROOT/bin/pyenv init -)"
追記が完了したら変更を反映させます。
source /etc/profile
#以下コマンドでpyenvのパージョンが表示されれば設定は完了です。
pyenv --version
イメージ
pyenvの設定が完了したので、希望のPythonをインストールします。
#Amazon Linux 2023でPythonをインストールするために必要なツールのインストール
sudo yum groupinstall -y "Development Tools"
sudo yum install -y bzip2-devel ncurses-devel libffi-devel readline-devel openssl-devel sqlite-devel
#インストール可能なバージョンの確認
pyenv install --list
#希望バージョンのPythonをインストール
pyenv install <バージョン(3.10.0とか)>
#pyenvでインストールしたバージョンの確認(今使用しているバージョンに*マークが付いてます)
pyenv versions
#使用するバージョンの変更
pyenv global <バージョン>
これで好きなバージョンでPythonの環境を作れるようになりました。
lambdaレイヤーの作成
lambdaレイヤーは最終的にZip形式でアップロードするのでレイヤー用のフォルダを作成します。
#ホームディレクトリに移動
cd ~
#pythonフォルダを作成
mkdir python
注意点
AWS lambdaのレイヤーにはパスの指定があるのでフォルダ名を任意のものにすると正常に動作しなくなります。
lambdaレイヤーとして使用したいパッケージをインストールします。
今回は仮として以下のパッケージをインストールしてみます。
pip install -t python langchain==0.2.0 python-dateutil==2.8.2
インストール完了後にファルダをZip形式に圧縮します。
#zipのインストール
sudo yum install -y zip
#フォルダを圧縮
zip -r9 <任意のレイヤー名.zip> python
Lambdaレイヤーのサイズ
1つのLmabdaレイヤーとしてアップロードできるZIPファイルの大きさは最大50MBです。
ZIPコマンドのオプション-r9は最も圧縮率が高い形での圧縮を指定しています。
ただし、展開後に250MBを越えるレイヤーも使えないのでその場合はレイヤーを複数に分けてアップロードしてください。
*1つの関数に追加できるレイヤーは5つまでです。
圧縮が完了したらlambdaレイヤーとして登録します。
aws lambda publish-layer-version --layer-name test_layer --compatible-runtime python3.10 --compatible-architectures x86_64 --zip-file fileb://test_layer.zip --no-cli-pager
#layer-nameはlambda側で表示されるレイヤー名
#compatible-runtimeは使用するPythonのバージョン
#combatible-architecturesは『x86_64』か『arm64』。関数作成時に指定するので使用する方に合わせてください
#zip-fileでアップロード対象のフォルダを指定しています。
成功すると、LayerのARNバージョンなどが表示されます。
lambda側で確認してみましょう。
関数の作成からランタイム、アーキテクチャでレイヤーで指定したものを同じものを選択します。
コード入力画面に進んだら画面したにスクロールしレイヤーからレイヤーの追加をクリック
レイヤーソースでカスタムレイヤーを選択し先ほどアップロードしたレイヤーが表示されれば成功です。
以上が、Amzon EC2でAWS Lambdaのレイヤーを1から作成してアップロードする手順です。
参考
https://qiita.com/DASHi/items/b03d3efd401260d8add4
編集後記
私は普段インフラエンジニアなのでlambdaを使ったらり開発環境を作成することはほぼ無いんですが大変なんですね環境づくり。
本記事の内容については一度使った開発環境でくりかえしできるので今後はある程度楽ですが、最初のとっかかりは何言ってるか分かんない状態でしてた。
Pythonの複数バージョンの管理とかライブラリの依存関係とかいまだに概念が分からないものばかり……。
あと、作成中にtmpフォルダがパンパンになって一度スッキリさせる必要がありました。
(エラー吐かなければやらずに完走できるのかな?)
sudo rm -rf /tmp/*
Discussion