記事内容
-
@aws-cdk/aws-lambda-python-alpha
ライブラリを使ったLambda Layer作成 -
aws-cdk-lib/aws-lambda
ライブラリを使ったLambda Layer作成 - Lambdaに外部パッケージのインストール
Layer内容
Layerに含める適当な外部パッケージ、関数実装を定義
requirements.txt
numpy==1.26.0
common_layer.py
def print_message(msg):
print(f"Message: {msg}")
Layerを使用するLambda
上記Layerを使用する適当なLambda実装
import common_layer
import numpy
def handler(event, context):
print(f"numpy: {numpy.random.rand()}")
common_layer.print_message("message-1")
@aws-cdk/aws-lambda-python-alpha
ライブラリを使ったLambda Layer作成
概要
こちらの方法はDockerが起動している必要がある
Docker上で自動的にLayerを作成(python
フォルダにLayerに含めるパッケージインストール)される
そのため、Layerに含めるパッケージはローカルに残らない
また、Layerに含めるファイルをpython
フォルダに格納する必要はない
以下使用するフォルダ構成
├─ app/
│ │
│ ├ bin/
│ └─ app.ts
│
└ lib/
│
├ common-layer/
│ │
│ ├─ layers/
│ │ ├─ common_layer.py
│ │ └─ requirements.txt
│ │
│ └─ common-layer.ts
CDK実装
import * as path from 'node:path';
import * as pylambda from '@aws-cdk/aws-lambda-python-alpha';
import { Stack, StackProps } from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';
export class CommonLayerStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const stackName = this.stackName;
const commonLayerName = `${stackName}-CommonLayer`;
const commonLayer = new pylambda.PythonLayerVersion(this, commonLayerName, {
layerVersionName: commonLayerName,
entry: path.join(__dirname, 'layers'),
compatibleRuntimes: [lambda.Runtime.PYTHON_3_11],
});
}
}
aws-cdk-lib/aws-lambda
ライブラリを使ったLambda Layer作成
概要
こちらの方法は先ほどの方法とは異なり、自身でLayerに含めるパッケージをインストールする
また、Layerに含めるファイルをpython
フォルダに格納する必要がある
以下使用するフォルダ構成
├─ app/
│ │
│ ├ bin/
│ └─ app.ts
│
└ lib/
│
├ common-layer/
│ │
│ ├─ layers/
│ │ ├─ python
│ │ │ └─ common_layer.py
│ │ │
│ │ └─ requirements.txt
│ │
│ └─ common-layer.ts
パッケージインストール
LambdaがAmazon Linux上で動作する関係上、Linux上でLayerに含めるパッケージをインストールする必要がある
筆者はWindows環境のため、WSL上のUbuntuを使用(パッケージによってはAmazon Linuxが必要になる可能性あり)
Ubuntuにpyenvをインストールし、Windows環境と同じPython環境を用意
VSCodeの場合、以下のようにcmdとwslの切替が容易に行うことが可能
wslにて以下コマンドでpython
フォルダ以下にパッケージをインストール後、
cmdに切替てCDKデプロイを行った
pip install -r requirements.txt -t python/
CDK実装
import * as path from 'node:path';
import { Stack, StackProps } from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';
export class CommonLayerStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
const stackName = this.stackName;
const commonLayerName = `${stackName}-CommonLayer`;
const commonLayer = new lambda.LayerVersion(this, commonLayerName, {
code: lambda.AssetCode.fromAsset(path.join(__dirname, 'layers')),
compatibleRuntimes: [lambda.Runtime.PYTHON_3_11],
layerVersionName: commonLayerName,
});
}
}
Lambdaに外部パッケージのインストール
Lambdaも同様に @aws-cdk/aws-lambda-python-alpha
, aws-cdk-lib/aws-lambda
どちらかのライブラリを使用して定義する
@aws-cdk/aws-lambda-python-alpha
ライブラリを使ったLambda作成
LambdaのPythonファイルを格納したフォルダ内に
requirements.txt
、poetry.lock
等を含めればDocker上で自動的にパッケージをインストールしてくれる
(Layerでもpoetry.lock
を試したが上手くいかなかった)
以下使用するフォルダ構成
├─ app/
│ │
│ ├ bin/
│ └─ app.ts
│
└ lib/
│
├ functions/
│ │
│ ├─ handlers/
│ │ └─ sample-function/
│ │ ├─ index.py
│ │ └─ requirements.txt
│ │
│ └─ functions.ts
CDK実装
import * as path from 'node:path';
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { PythonFunction } from '@aws-cdk/aws-lambda-python-alpha';
export class FunctionsStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const stackName = this.stackName;
const functionName = `${stackName}-SampleFunction`;
new PythonFunction(this, functionName, {
functionName: functionName,
runtime: lambda.Runtime.PYTHON_3_11,
entry: path.join(__dirname, 'handlers/sample-function'),
handler: 'handler',
});
}
}
デプロイ結果
以下、requirements.txt
にpytz
を指定してデプロイしたLambdaのファイル構成
aws-cdk-lib/aws-lambda
ライブラリを使ったLambda作成
@aws-cdk/aws-lambda-python-alpha
のデプロイ結果から、python
フォルダ内にパッケージをインストールする必要はないが、
gitignoreでの管理上、python
フォルダ内にパッケージをインストールするよう以下のフォルダ構成とした
(pythonフォルダ以下は、index.pyを除いてgit管理対象外)
├─ app/
│ │
│ ├ bin/
│ └─ app.ts
│
└ lib/
│
├ functions/
│ │
│ ├─ handlers/
│ │ └─ sample-function/
│ │ ├─ python/
│ │ │ └─ index.py
│ │ └─ requirements.txt
│ │
│ └─ functions.ts
CDK実装
import * as path from 'node:path';
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
export class FunctionsStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const stackName = this.stackName;
const functionName = `${stackName}-SampleFunction`;
new lambda.Function(this, functionName, {
code: lambda.Code.fromAsset(path.join(__dirname, 'handlers/sample-function/python')),
handler: 'index.handler',
runtime: lambda.Runtime.PYTHON_3_11,
functionName: functionName,
});
}
}
パッケージインストール
パッケージのインストールはLayer時と同様にWLS上で実施する
Lambda Layer サイズ
LambdaにアタッチできるLayerの合計サイズには上限(262144000 bytes)があり、超えると以下のようにエラーとなる。
Resource handler returned message: "Layers consume more than the available size of 262144000 bytes (Service: Lambda, Status Code: 400, Request ID: xxxx-49792a728f0e)"
Layerに含めていた外部パッケージの一部をLambda側に移動したが、
以下のようにエラーが変わり、Layer含めたLambdaのサイズに対して上限が設定されている
Resource handler returned message: "Function code combined with layers exceeds the maximum allowed size of 262144000 bytes. The actual size is 270712450 bytes. (Service: Lambda, Status Code: 400, Request ID: )"