如何使用AWS CDK和Python将层部署并附加到AWS Lambda函数

时间:2020-01-13 12:07:13

标签: python amazon-web-services aws-lambda aws-cdk

如何使用aws CDK将层部署并附加到aws lambda函数?

我需要一个简单的cdk代码,该代码将aws lambda函数部署并附加一层。

5 个答案:

答案 0 :(得分:3)

以下aws CDK Python代码部署一个层并将其附加到aws lambda函数。

由yl。

项目目录结构

--+
  +-app.py
  +-cdk_layers_deploy.py
  +--/functions+
               +-testLambda.py
  +--/layers+
            +-custom_func.py

app.py文件

#!/usr/bin/env python3

import sys

from aws_cdk import (core)
from cdk_layers_deploy import CdkLayersStack

app = core.App()
CdkLayersStack(app, "cdk-layers")

app.synth()

cdk_layers_deploy文件

from aws_cdk import (
    aws_lambda as _lambda,
    core,
    aws_iam)
from aws_cdk.aws_iam import PolicyStatement
from aws_cdk.aws_lambda import LayerVersion, AssetCode


class CdkLayersStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # 1) deploy lambda functions
        testLambda : _lambda.Function = CdkLayersStack.cdkResourcesCreate(self)

        # 2) attach policy to function
        projectPolicy = CdkLayersStack.createPolicy(self, testLambda)

    # -----------------------------------------------------------------------------------
    @staticmethod
    def createPolicy(this, testLambda:_lambda.Function) -> None:
        projectPolicy:PolicyStatement = PolicyStatement(
            effect=aws_iam.Effect.ALLOW,
            # resources=["*"],
            resources=[testLambda.function_arn],
            actions=[ "dynamodb:Query",
                      "dynamodb:Scan",
                      "dynamodb:GetItem",
                      "dynamodb:PutItem",
                      "dynamodb:UpdateItem",
                      "states:StartExecution",
                      "states:SendTaskSuccess",
                      "states:SendTaskFailure",
                      "cognito-idp:ListUsers",
                      "ses:SendEmail"
                    ]
        )
        return projectPolicy;
    # -----------------------------------------------------------------------------------
    @staticmethod
    def cdkResourcesCreate(self) -> None:
        lambdaFunction:_lambda.Function = _lambda.Function(self, 'testLambda',
                                                           function_name='testLambda',
                                                           handler='testLambda.lambda_handler',
                                                           runtime=_lambda.Runtime.PYTHON_3_7,
                                                           code=_lambda.Code.asset('functions'),
                                                           )
        ac = AssetCode("layers")
        layer  = LayerVersion(self, "l1", code=ac, description="test-layer", layer_version_name='Test-layer-version-name')
        lambdaFunction.add_layers(layer)

        return lambdaFunction

    # -----------------------------------------------------------------------------------

testLambda.py

# -------------------------------------------------
# testLambda
# -------------------------------------------------

import custom_func as cf  # this line is errored in pyCharm -> will be fixed on aws when import the layer

def lambda_handler(event, context):
    print(f"EVENT:{event}")
    ret = cf.cust_fun()
    return {
        'statusCode': 200,
        'body': ret
    }

custom_func.py-图层功能

import datetime

def cust_fun():                           
    print("Hello from the deep layers!!")
    date_time = datetime.datetime.now().isoformat()
    print("dateTime:[%s]\n" % (date_time))

    return 1

答案 1 :(得分:1)

您可以先创建和部署您的层,然后从 aws 导入它并将其作为堆栈定义中 lambda 的层参数传递。

为此,我们发现最简单的解决方案是在您的根 cdk 项目中创建一个 /layer 文件夹,并创建一个 bash 文件来部署该层(您需要将 cd 放入 {{ 1}} 文件夹来运行它)。

/layer

然后您需要在您的 AWS 控制台中搜索层的 ARN(Lambda>层)并通过以下方式在您的 LAYER_NAME="<layer_name>" echo <your_package>==<package.version.0> >> requirements.txt # See PyPi for the exact version docker run -v "$PWD":/var/task "lambci/lambda:build-python3.6" /bin/sh -c "pip install -r requirements.txt -t python/lib/python3.6/site-packages/; exit" zip -r $LAYER_NAME.zip python > /dev/null aws lambda publish-layer-version \ --layer-name $LAYER_NAME \ --zip-file fileb://$LAYER_NAME.zip \ --compatible-runtimes "python3.6" \ --region <your_region> rm requirements.txt rm -rf python rm $LAYER_NAME.zip 中定义您的层:

_stack.py

然后您可以将其传递到您的 lambda 中:

layer = aws_lambda.LayerVersion.from_layer_version_arn(
    self,
    '<layer_name>',
    <layer_ARN>  # arn:aws:lambda:<your_region:<your_account_id>:layer:<layer_name>:<layer_version>
)

答案 2 :(得分:0)

那是行不通的。您需要将db.collection("collection_key").document("document_key").add("mylist", value) 放在custom_func.py上才能使其正常工作(https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html#configuration-layers-path)。

答案 3 :(得分:0)

您可以按以下方式使用它,

// JavaScript POC. Output:
// Matches:  ["GOODBYE","CRUEL","WORLD","IM","LEAVING","U","TODAY"]

let str = `GOODBYE,CRUEL,WORLD,IM,LEAVING,U,TODAY`
let matches = [];

function recurse(str, matches) {
    let regex = /^((,?([A-Z]+))+)$/gm
    let m
    while ((m = regex.exec(str)) !== null) {
        matches.unshift(m[3])
        return str.replace(m[2], '')
    }
    return "bzzt!"
}

while ((str = recurse(str, matches)) != "bzzt!") ;
console.log("Matches: ", JSON.stringify(matches))

答案 4 :(得分:0)

我将其设置为在我的虚拟环境中使用我的站点包,因此它不仅包含我的依赖项,还包含它们的依赖项。为了在创建环境时执行此操作,请像这样设置 venv:

mkdir .venv
python3 -m venv .venv/python

然后在您的堆栈中将您的虚拟环境引用为 AssetCode(".venv")。因为这包括路径中的 python 版本,作为站点包的一部分,您必须根据您的版本限制兼容性。支持所有 python 版本的最简单方法是使用定义的不同结构 https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html

示例:

from aws_cdk import core
from aws_cdk.aws_lambda import AssetCode, LayerVersion, Runtime


class lambda_layer_stack(core.Stack):
    def __init__(self, scope: core.Construct, construct_id: str, version: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        ac = AssetCode(path=".venv")
        au_layer = LayerVersion(
            self,
            id=construct_id,
            code=ac,
            layer_version_name=construct_id,
            description=version,
            compatible_runtimes=[Runtime.PYTHON_3_8],
        )