首页 > 解决方案 > 具有相同 CodeUri 的 AWS 多个 lambda

问题描述

我的 AWS 无服务器项目中有多个 lambda,它们都有相同的CodeUri,这是我项目中的一个文件夹。例如,它们都指向src/.

在基本用法中,或者至少在我使用它的方式中,该sam build选项为每个 lambda 创建一个文件夹。所有文件夹都包含相同的代码。然后,在运行时,sam deploy每个 zip 都会上传到 S3。拉链都是一样的,上传它们需要大量的冗余时间。

是否有“告诉”山姆只上传一次的选项?

我看到我可以手动构建 zip,然后将其上传到 S3。然后我怎样才能CodeUri在 lambdas 中设置 uri?我应该使用外部参数还是有专门的方式来发出信号?

谢谢

标签: amazon-web-servicesaws-lambdaaws-sam

解决方案


经过艰苦的努力,使用大卫康德的想法,我设法找到了一些解决方案。我们想要实现的是一次上传 lambda 的 zip(及其所有依赖项)并指向所有 lambda 以使用此 zip。

这个过程分为几个步骤,我将尽可能详细地描述这些步骤。其中一些可能与您的情况不完全相关。

大概的概念

一般的想法是创建一个包含我们要上传一次的代码的层。然后,对于每个 lambda,指定它使用该层。每个 lambda 都会让它的处理程序指向源目录中的某个位置。因此,“从层”运行代码。但!我们必须为 lambda 指定代码以运行/附加一个 zip——即使它不会运行。为了跳过它,我们将附加一个“空”代码。

构建文件夹

首先,创建一个我们将要工作的构建文件夹,例如:mkdir -p .build/

此外,定义以下变量:

  • s3_bucket="aaaaaaaa"
  • s3_prefix="aaaaaaaa"
  • s3_lambda_zip_suffix="$s3_prefix/lambda.zip"
  • s3_lambda_zip="s3://$s3_bucket/$s3_lambda_zip_suffix"

创建源 zip

解压缩 lambda 时,其内容将写入工作目录。解压缩层时,将/opt按照 AWS 中的说明将其解压缩。因为我们的 lambda 需要找到我们的源代码,这是一个“依赖项”,它需要在/opt. 为了实现它,我们需要将它解压缩到/opt/python. 我们可以通过压缩python/...成一个 zip 文件来做到这一点。

首先,我们创建文件夹,将依赖项安装到 python 文件夹中:

  • mkdir -p .build/lambda_zip/python
  • pip3 install -q --target .build/lambda_zip/python -r requirements.txt

然后我们压缩它:

  • pushd .build/lambda_zip/ > /dev/null
  • zip --quiet -r ./lambda.zip ./python
  • popd > /dev/null

现在,您可能想要添加您的 src 目录:

  • zip --quiet -r .build/lambda_zip/lambda.zip src

#Uploading to S3 现在,我们必须将 zip 文件上传到 S3 以便我们的 lambdas 加载它。

  • aws s3 cp ".build/lambda_zip/lambda.zip" $s3_lambda_zip_path

将图层添加到template.yaml

现在,我们需要将图层添加到我们的template.yaml文件中,您可以在阅读 AWS 文档后复制以下代码:

Parameters:
  LambdaCodeUriBucket:
    Type: String
  LambdaCodeUriKey:
    Type: String

Resources:

  OnUpHealthLayer:
    Type: AWS::Lambda::LayerVersion
    Properties:
      CompatibleRuntimes:
      - python3.8
      Content:
        S3Bucket: !Sub '${LambdaCodeUriBucket}'
        S3Key: !Sub '${LambdaCodeUriKey}'

为 lambdas 创建空 zip

Cloudformation 必须为 lambdas 上传 zip,因此我们希望它创建一个空 zip。但它会从requirements.txt目录中的文件中扫描依赖项,与template.yaml. 我们希望它上传一些空的东西。因此它必须在另一个文件夹中。为了解决这个问题,我将它复制template.yaml到一个空目录并添加空requirements.txt文件。之后,我们可以sam buildsam deploy往常一样运行。请注意,我们必须通过它LambdaCodeUriBucket并且LambdaCodeUriKey

#create "empty" environment for the template to be built in
mkdir -p .build/empty_template
cp template.yaml .build/empty_template
pushd .build/empty_template > /dev/null
touch requirements.txt
sam build --template template.yaml
sam deploy \
    --template-file .aws-sam/build/template.yaml \
    --capabilities "CAPABILITY_IAM" \
    --region $region \
    --s3-bucket $s3_bucket \
    --s3-prefix $s3_prefix \
    --stack-name $stack_name \
    --parameter-overrides LambdaCodeUriBucket=$s3_bucket LambdaCodeUriKey=$s3_lambda_zip_suffix
popd > /dev/null

请注意,虽然我们复制了 template.yaml 并调用sam build了新的,但我们已经将 zip 文件上传到 s3。

您必须做的重要事情是.CodeUri您的 lambda 指定 。因为他们现在使用“空拉链”。

未来,我们将能够做到:

InlineCode: |
    def handler(event, context):
        pass

并且不指定文件夹.

但是,目前sam不支持内联代码,python3.8因此我们使用.. 无论如何,您必须将其移动到单独的文件夹以删除它的依赖项。


推荐阅读