こんにちは、広野です。
データ分析や加工でよく使われるライブラリに、pandas があると思います。AWS Lambda 関数の中でそれを使用したいときには、外部ライブラリとして呼び出せるよう、あらかじめ使用するリージョン内に pandas の Lambda Layer を用意しておかなければなりません。
本記事では、Python 3.12 ベースの AWS Lambda 関数で動作する pandas の Lambda Layer を準備する手順を紹介します。
やりたいこと
- Python 3.12 ベースの Lambda 関数で動作する pandas の Lambda Layer を準備する。
- Lambda Layer への登録は AWS CloudFormation を使用する。
実現方法
- pandas モジュールのインストールは AWS Cloud9 (Amazon Linux 2023) 上で行い、必要ファイルを ZIP で固める。
- AWS Cloud9 に Python 3.12 をインストールする。
- pip も最新にアップグレードする。
- 完成した ZIP ファイルを AWS CloudFormation で Lamda Layer に登録する。
手順
- AWS Cloud9 を Amazon Linux 2023 で立ち上げる。
- Python 3.12 を pyenv でインストールする。
以下、必要なコマンド。#はコメントとする。
# 下準備。pythonディレクトリを作成しておく。 mkdir python # 必要なモジュールをインストール。 sudo yum -y install bzip2-devel xz-devel # Python環境管理ツール pyenv を Git からインストール。 git clone https://github.com/pyenv/pyenv.git ~/.pyenv # pyenvのパスを通すよう、.bashrcをviで修正。 vi ~/.bashrc # 以下追記内容 export PATH="$HOME/.pyenv/bin:$PATH" eval "$(pyenv init -)" # 追記内容ここまで # .bashrcの修正を反映 source ~/.bashrc # pyenv のバージョンを確認 pyenv --version # インストール可能なPython3.12のバージョンを確認 pyenv install --list | grep 3.12 # 最新のPython3.12.1をインストール pyenv install 3.12.1 # Python3.12.1を使用するよう環境を設定 pyenv global 3.12.1 # Pythonのバージョンを確認 python -V
3. pip をアップグレードする。
# アップグレード pip install --upgrade pip # アップグレード後バージョン確認 pip -V
4. pandas をインストールする。
執筆時点では、pandas 2.1.4 がインストールされました。
pip install pandas
5. Pandas 関連ファイルを python ディレクトリにコピーし、ZIP 圧縮する。
インストールされているモジュールのバージョンは執筆時点のもの。
cd /home/ec2-user/.pyenv/versions/3.12.1/lib/python3.12/site-packages cp -r dateutil /home/ec2-user/environment/python/ cp -r numpy /home/ec2-user/environment/python/ cp -r numpy-1.26.3.dist-info /home/ec2-user/environment/python/ cp -r numpy.libs /home/ec2-user/environment/python/ cp -r pandas /home/ec2-user/environment/python/ cp -r pandas-2.1.4.dist-info /home/ec2-user/environment/python/ cp -r python_dateutil-2.8.2.dist-info /home/ec2-user/environment/python/ cp -r pytz /home/ec2-user/environment/python/ cp -r pytz-2023.3.post1.dist-info /home/ec2-user/environment/python/ cp -r six-1.16.0.dist-info /home/ec2-user/environment/python/ cp -r six.py /home/ec2-user/environment/python/ cp -r tzdata /home/ec2-user/environment/python/ cp -r tzdata-2023.4.dist-info /home/ec2-user/environment/python/ cd /home/ec2-user/environment zip -r pandas214.zip python
Lambda Layer に登録する ZIP ファイル内のディレクトリ構成はランタイムによって決まっている。
そのため、一連のファイルを一旦 python フォルダ内にコピーした後、python フォルダもろとも ZIP 圧縮をかける。
6. 完成した ZIP ファイル pandas214.zip を任意の Amazon S3 バケットにコピーする。(以下は例)
aws s3 cp ./pandas214.zip s3://s3-bucket-name/sdk/Python3.12/
ここまでで、pandas モジュールのファイルは完成。以降 Lambda Layer への登録をする。
AWS CloudFormation テンプレートによる実装
以下、AWS CloudFormation のテンプレートサンプルです。
ここでは、あらかじめ任意の Amazon S3 バケット内に配置した pandas214.zip を Lambda Layer として登録し、その Lambda Layer を関連付けた Lambda 関数を作成しています。
Lambda 関数には、pandas を使用したサンプルコードを載せています。外部から受け取った JSON データを CSV ファイルに変換して Amazon S3 バケットに保存する、というシンプルなコードです。
AWSTemplateFormatVersion: 2010-09-09 Description: The CloudFormation template that creates sample resources for Lambda Layer. # ------------------------------------------------------------# # Input Parameters # ------------------------------------------------------------# Parameters: SystemName: Type: String Description: The system name. Default: example MaxLength: 10 MinLength: 1 S3BucketNameSdk: Type: String Description: S3 bucket name where SDKs are uploaded. (e.g. example-sdks-xxxxxx) Default: example-sdks-xxxxxx MaxLength: 50 MinLength: 1 S3KeyPandasSdk: Type: String Description: S3 key of pandas.zip. Fill the exact key name if you renamed. (e.g. Python3.12/pandas214.zip) Default: Python3.12/pandas214.zip MaxLength: 50 MinLength: 1 Resources: # ------------------------------------------------------------# # Lambda Layer # ------------------------------------------------------------# LambdaLayerPandas214: Type: AWS::Lambda::LayerVersion Properties: LayerName: !Sub example-pandas-${SystemName} Description: !Sub Pandas 2.1.4 for ${SystemName} CompatibleRuntimes: - python3.12 Content: S3Bucket: !Sub ${S3BucketNameSdk} S3Key: !Sub ${S3KeyPandasSdk} LicenseInfo: BSD-3-Clause # ------------------------------------------------------------# # Lambda Function # ------------------------------------------------------------# LambdaExamplePandas: Type: AWS::Lambda::Function Properties: FunctionName: !Sub example-lambda-with-pandas-${SystemName} Description: !Sub Lambda Function example with pandas. Runtime: python3.12 Timeout: 180 MemorySize: 256 Role: !GetAtt LambdaExecutionRole.Arn Handler: index.lambda_handler # pandas の Lambda Layer を関連付ける Layers: - !Ref LambdaLayerPandas214 Tags: - Key: Cost Value: !Sub example-${SystemName} Code: ZipFile: !Sub | import json import pandas as pd # pandas をインポート import datetime import boto3 def datetimeconverter(o): if isinstance(o, datetime.datetime): return str(o) def lambda_handler(event, context): try: # resultはここでは外部から受け取ったJSONデータ。pandasでロード df = pd.DataFrame(event['result']) # データを一時領域に保存するときのファイル名 tempFileName = '/tmp/result.csv' # JSONデータをCSVファイルに変換 df.to_csv(tempFileName) # CSVファイルをS3にアップロード outputBucket = 'example-${SystemName}-result' outputS3Key = 'result/result.csv' s3 = boto3.resource('s3') res = s3.meta.client.upload_file(tempFileName, outputBucket, outputS3Key) except Exception as e: print(e) return { "result": str(e) } else: return { "result": json.dumps(res, indent=4, default=datetimeconverter) } DependsOn: - LambdaExecutionRole - LambdaLayerPandas214 # ------------------------------------------------------------# # Lambda Execution Role (IAM) # ------------------------------------------------------------# LambdaExecutionRole: Type: AWS::IAM::Role Properties: RoleName: !Sub example-S3InvocationRole-${SystemName} Description: This role allows Lambda functions to be executed. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AmazonS3FullAccess
※ IAM ロールに与える権限は適宜修正ください。
まとめ
いかがでしたでしょうか?
pandas を Lambda Layer に登録する手順を中心に紹介しましたが、登録後にそれらを使用するところまでざっくりとご理解頂けたのではないかと思います。
Lambda Layer はリージョンの範囲で共有されるので、一度登録してしまえば他の Lambda 関数からもすぐに呼出ができます。外部ライブラリを使用した Lambda 関数を作成するには必須の便利機能です。
Lambda Layer は設定により別の AWS アカウントにも共有することができます。世の中には、全世界の人向けに自分が作った多数の Lambda Layer を公開してくれている人がいます。それを利用させてもらうのも手なのですが、自分のサービス維持を見知らぬ他人の(特に個人の)リポジトリに依存するのは気が引けたので、面倒ですが自分で作成しました。
本記事が皆様のお役に立てれば幸いです。