LoginSignup
3
0

AWS CDK - Python Lambda Layer デプロイ

Last updated at Posted at 2023-10-21

記事内容

  • @aws-cdk/aws-lambda-python-alphaライブラリを使ったLambda Layer作成
  • aws-cdk-lib/aws-lambdaライブラリを使ったLambda Layer作成
  • Lambdaに外部パッケージのインストール

Layer内容

Layerに含める適当な外部パッケージ、関数実装を定義

requirements.txt

requirements.txt
numpy==1.26.0

common_layer.py

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実装

common-layer.ts
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の切替が容易に行うことが可能

2023-10-21-16-45-57.png

wslにて以下コマンドでpythonフォルダ以下にパッケージをインストール後、
cmdに切替てCDKデプロイを行った

pip install -r requirements.txt -t python/

CDK実装

common-layer.ts
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.txtpoetry.lock等を含めればDocker上で自動的にパッケージをインストールしてくれる
(Layerでもpoetry.lockを試したが上手くいかなかった)
以下使用するフォルダ構成

 ├─ app/
 │   │
 │   ├ bin/
     │  └─ app.ts
     │
     └ lib/
        │
        ├ functions/
        │   │
        │   ├─ handlers/
        │   │     └─ sample-function/
        │   │           ├─ index.py
        │   │           └─ requirements.txt
        │   │
        │   └─ functions.ts

CDK実装

functions.ts
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.txtpytzを指定してデプロイしたLambdaのファイル構成

image.png

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実装

functions.ts
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: )"

参考

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0