Serverless で Python のパッケージを使った Lambda 関数をデプロイ

Serverless で Python のパッケージを使った Lambda 関数をデプロイ

Python パッケージを使う、原始的な方法

過去に2回、Serverless Framework を使った Lambda 関数の管理について書きました。

1回目の投稿の際、Python のパッケージを使いたい場合は、以下の通り、Lambda 関数の Python ファイルと同じディレクトリにパッケージをインストールして、それを sls deploy でパッケージ化&デプロイする方法を紹介しました。

pip install パッケージ名 -t .

「原始的な方法」の問題点

上に挙げた方法には2つの問題があります。

  1. ディレクトリが汚れる
  2. pure Python ではないモジュール(コンパイルが必要なモジュール)を使う際に問題がある

それぞれについて簡単に説明します。

ディレクトリが汚れる

例えば、requests パッケージをインストールすると、requests が依存している他のパッケージも同じディレクトリにインストールされます。使用するパッケージが増えてくると、ディレクトリが沢山出来て汚いです。

また、Serverless で Lambda 関数を管理するという事は、当然ソースコードも管理しているかと思いますが、それらの Python パッケージはソースコード管理に加える事は望ましくないため、 .gitignore に入れるなどの方法を取る事になります。パッケージが増えてくると、都度 .gitignore に追加するのも面倒になってきます。

pure Python ではないモジュールを使う際に問題がある

例えば、Mac で Serverless を使っているとします。pip install で pure Python でない、コンパイルが必要なモジュールをインストールすると、当然ながら Mac 上でコンパイルされ、Mac 用のバイナリが出来ます。これをそのまま sls deploy でデプロイしても、Lambda は裏側では Amazon Linux 上で動いているので、バイナリの互換性が無いためエラーになります。

serverless-python-requirements を使った解決方法

上の問題を解決するのが serverless-python-requirements というプラグインです。

具体的な使い方は、実は Serverless のブログサイトに記事があるので、それを読んでもらうと良いかもしれませんが、若干冗長なのと英語なので、本記事でも簡単にまとめます。

How to Handle your Python packaging in Lambda with Serverless plugins

インストール・事前準備

以下の通り serverless-python-requirements をインストールします。

npm install --save serverless-python-requirements
# この後、package.json はコミットしておく

Serverless のプラグインは、それを必要とするプロジェクトでのみインストールすべきだと思うので、-g はつけない方が良いと思います。

また、同プラグインは内部で Docker を使うため、Docker もインストールしておきます。

設定

serverless.yml に以下の通り記述します。


plugins: - serverless-python-requirements custom: pythonRequirements: dockerizePip: true

使い方

requirements.txt に使いたいパッケージを記載します。例えば以下の通りです。通常の requirements.txt と同じなので、詳しい説明はしません。

requests==2.18.4
paramiko

後は、sls deploy をすれば、よしなにやってくれます。

たったこれだけです。

補足

requirements.py

ネットを見ると import requirements が必要であると書いているページがいくつかありましたが、(昔は必要だったようですが)今は必要ないようです。

以下のようなページです。

内部の動作

実際にどうやって動作しているのかは、上述の Classmethod さんのページで細かく解説しているので、そちらを参考にすると良いと思います。

ただ、若干現在の動作と異なるようなので、その部分だけ説明します。

現在は、sys.path をいじることはしていません。その代わり、sls deploy の時にローカルの .serverless に必要なファイルを全て集め、それらをパッケージングしています。

作成された zip ファイルの中身を見てみると、以下のようになっています。

$ unzip -l .serverless/my-lambda-function.zip | awk '{print $4}'
# 出力結果は適当に省略します
Name
----
.libs_cffi_backend/libffi-d7bb31a0.so.6.0.4 # <- バイナリ
(snip)
my-lamda-function.py # <- 自分で作成したファイル
(snip)
requests-2.18.4.dist-info/DESCRIPTION.rst # <- パッケージに含まれるドキュメント
(snip)
requests/__init__.py # <- パッケージ内の Python ファイル
(snip)
requirements.txt # <- 自分で作成したファイル

まとめ

Serverless を使うと、Lambda 関数が簡単に管理できますが、Serverless 単体だと Python の外部パッケージを使う際にいくつかの問題がありました。serverless-python-requirements プラグインを使う事でその問題は解決できるため、Python で Lambda 関数を開発する人にとっては必須のプラグインと言えるでしょう。