Как развернуть и прикрепить слой к лямбда-функции aws с помощью aws CDK и Python

Как развернуть и прикрепить слой к лямбда-функции aws с помощью aws CDK?

Мне нужен простой код cdk, который развертывает и прикрепляет слой к лямбда-функции aws.


person ylev    schedule 13.01.2020    source источник


Ответы (5)


Следующий код aws CDK Python развертывает слой и прикрепляет его к лямбда-функции aws.

by 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
person ylev    schedule 13.01.2020

Вы можете сделать это, сначала создав и развернув свой слой, а затем импортировав его из aws и передав в качестве аргумента слоя для лямбда в определении стека.

Мы обнаружили, что самым простым решением для этого является создание папки /layer в корневом проекте cdk и создание файла bash для развертывания слоя (для его запуска необходимо cd в папку /layer).

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

Затем вам нужно найти ARN слоя в вашей консоли AWS (Lambda›Layers) и определить свой слой в вашем _stack.py следующим образом:

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>
)

Затем вы можете передать его в свою лямбду:

lambda = aws_lambda.Function(
    scope=self,
    id='<lambda_id>',
    handler='function.handler',
    runtime=aws_lambda.Runtime.PYTHON_3_6,
    code=aws_lambda.Code.asset(path='./lambda'),
    environment={
           
    },
    layers=[
        layer
    ]
)
person Goodyear    schedule 14.01.2021

Это не будет работать. Вместо этого вам нужно поставить custom_func.py на layers/python/lib/python3.7/site-packages/custom_func.py, чтобы все заработало (https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html#configuration-layers-path).

person Андрей Максимов    schedule 30.08.2020

Вы можете использовать его следующим образом,

mysql_lib = lb.LayerVersion(self, 'mysql',
    code = lb.AssetCode('lambda/layers/'),
    compatible_runtimes = [lb.Runtime.PYTHON_3_6],
)

my_lambda = lb.Function(
            self, 'core-lambda-function',
            runtime=lb.Runtime.PYTHON_3_6,
            code=lb.InlineCode(handler_code),
            function_name="lambda_function_name",
            handler="index.handler",
            layers = [mysql_lib],
            timeout=core.Duration.seconds(300),
   )
person Madeesha Fernando    schedule 20.11.2020

Я настроил это для использования моих пакетов сайтов в моей виртуальной среде, поэтому он включает не только мои зависимости, но и их зависимости. Чтобы сделать это при создании среды, настройте 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],
        )
person user2197172    schedule 16.02.2021