AWS Lambda Layersでライブラリを共通化


Lambda Layersで解決できること

Lambdaの実行環境には追加ライブラリが存在しないため、ライブラリを使用する際はデプロイパッケージにライブラリを含める必要がありました。

しかしAWS Lambda Layersを使用することで、ライブラリなどの共通コンテンツをレイヤーとして作成することで、パッケージにライブラリを含める必要がなくなりました。


Lambda Layers

Lambda Layersとは、複数のLambda関数で外部ライブラリやビジネスロジックを共有できる仕組みです。

イメージはこんな感じです。

9.png

使用するライブラリや共通のビジネスロジックをZIPアーカイブし、Layerに追加することができます。

デプロイパッケージの容量を少なくすることができるためLambdaのソースコードの管理が楽になります。

また依存関係をインストールしてパッケージ化する際に発生するエラーを回避することや、ライブラリのビルドの手順を省くこともできます。


制限

1つのLambda関数では5つのLayerのみ使用することができます。

また、Lambda関数とLayerの解凍後の合計サイズが250MB以下となる必要があります。


Lambda Layersの配置先

作成したLayerは、Lambdaの実行環境の/optディレクトリに展開されます。

/optディレクトリ以下に、ランタイムの言語ごとのディレクトリが構成されているので、ランタイムに合わせてLayerを構築する必要があります。

Pythonを例にとると、Lambdaの実行環境は/opt/python/とディレクトリが構成されているため、作成するLayerは展開される構成が/opt/python/"作成したLayer"となる必要があります。


Layerを作成しLambdaから実行する

今回はPythonのライブラリParamikoと、Paramikoを用いてサーバーにSSH接続するロジックをLayerに追加します。


Layerの作成

Layerに追加するZIPファイルを作成します。

ParamikoをLambdaで実行できるように、Amazon Linux上で作業を行います。

【参考】AWS LambdaでPythonのparamikoを使う方法

まずはデプロイパッケージを作成します。

$ mkdir python/ 

Paramikoをローカルのディレクトリ内にインストールします。

$ cd python

$ sudo yum -y install gcc gcc-c++ kernel-devel python-devel libxslt-devel libffi-devel openssl-devel
$ pip install -t ./ paramiko

SSH接続するPythonモジュールを作成します。

$ mkdir sshutils

$ cd sshutils
$ touch sshutils.py


sshutils.py

# coding: utf-8

import paramiko

def connect(hostname, username, password = None, keyfile = None):
"""
SSHクライアントの作成・SSH接続
"""

sshcon = paramiko.SSHClient()
sshcon.set_missing_host_key_policy(paramiko.AutoAddPolicy())
sshcon.connect(hostname, username=username, password=password, key_filename=keyfile)
print('接続')
return sshcon

def exec_command(sshcon, command):
"""
コマンドの実行
"""

stdin, stdout, stderr = sshcon.exec_command(command)
print('実行コマンド:' + command)
print('実行結果:')
for line in stdout:
print(line)

def close(sshcon):
"""
切断
"""

print('SSH切断')
sshcon.close()


ZIP化します。

$ cd python

$ cd ..
$ zip -r sshutils.zip python/

パッケージ構成は以下のようになります。

  python/

├ sshutils/
│ ├ sshutils.py
├ paramiko/


以上で追加するLayerを作成できました。


Layerの追加

LambdaのコンソールのタブのLayerを選択し、Layerの作成をクリックします。

1.PNG

名前をssh-utilとして、作成したLayerのZIPファイルをアップロードします。

2.PNG

Layerを作成するとバージョンが割り当てられます。

3.PNG

以上でLayerを作成することができました。


Lambda関数でLayerを使用する

実際にLambda関数からLayerを呼び出します。

手順は省きますが、今回はAWS VPC内のサーバーに接続するため、VCP、サブネット、セキュリティーグループの設定を行います。


Lambda関数にLayerを追加する

Lambda関数を作成するとDesignerからLayerを選択することができます。

「参照されるレイヤー」からレイヤーの追加を選択します。

6.png

レイヤーの追加画面で、「ランタイムと互換性のあるレイヤーのリストから選択」を選択し、先ほど作成したLayerとバージョンを選択し確認を押します。

7.png

選択したLayerが追加されていることを確認したください。

8.png


Lambda関数からLayerを呼び出す

作成したLayerはPythonのimportで呼び出すことができます。

先ほど追加したLayerは、/opt/python/直下に配置されているので、python/以下から辿ってimportすることができます。


lambda_function.py

# coding: utf-8

from sshutils import sshutils

def lambda_handler(event, context):
sshcon = sshutils.connect('XXX.XXX.XXX.XXX', 'XXXXXX', keyfile='XXXXXXX')
command = 'pwd'
sshutils.exec_command(sshcon,command)
sshutils.close(sshcon)



Lambda関数を実行

Lambdaのテストから実行します。

Lambdaのログ以下のように実行結果が表示されます。

接続

実行コマンド:pwd
実行結果:
/home/'ユーザー名'

SSH切断


まとめ

AWS Lambda Layersを利用して、ライブラリとモジュールをLayerに追加しLambda関数で実行してみました。

これまでは外部ライブラリを関数ごとにパッケージ化しなければならずプロジェクトが肥大化していましたが、Layerを使用することで自作モジュールのみとなるため開発・保守しやすくなります。

共通ロジックなどのモジュールも共有できるので、より効率的に開発することができます。

今回例に出したParamikoを使用するように、Lambdaの実行環境であるAmazno Linux上で開発環境を作成しなくてはならない場合があります。一度ライブラリをAmazon Linuxで構築し、Layerとして追加しAWSアカウント内で使い回すことができるので、環境構築も一度で済みます。

ただし、デプロイパッケージのサイズの制限やLayer数の制限もありますので、共通化する部分を検討して使用する必要があると思います。