如何访问触发部署为 Docker 映像的 Lambda 的 SQS 事件?

How to access the SQS event that triggered a Lambda deployed as a Docker image?

我目前有一个简单的 Lambda,它由 SQS 队列触发并打印出触发它的事件。它使用 CFN 部署,定义为:

PrintMessage:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Runtime: python3.8
      FunctionName: !Sub printMessage-${Environment}
      MemorySize: 1024
      Role: !Sub arn:aws:iam::${AWS::AccountId}:role/service-role/printMessageRole-${Environment}
      Timeout: 900
      Code:
        ZipFile: |
          import os
          import json

          def handler(event, context):
            print("Event: {}".format(event))

PrintMessageEventSource:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      BatchSize: 1
      Enabled: true
      EventSourceArn: !Sub arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:printMessageQueue-${Environment}
      FunctionName: !Sub printMessage-${Environment}

此流程运行良好 - 写入 printMessageQueue 的任何内容都会触发 Lambda 并打印其内容。

我的问题是我需要使用另一个组件的逻辑,它更复杂并且包含多个依赖项并且已经作为 Docker 映像部署到 ECR。到目前为止我所拥有的是:

PrintMessage:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ImageUri: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/component:${ImageTag}
      FunctionName: !Sub printMessage-${Environment}
      ImageConfig:
        EntryPoint:
          - python3
          - print_message.py
      MemorySize: 1024
      PackageType: Image
      Role: !Sub arn:aws:iam::${AWS::AccountId}:role/service-role/printMessageRole-${Environment}
      Timeout: 900

它按预期工作,运行 python3 print_message.py 在 Docker 容器内。

是否有任何方法可以访问触发 Lambda 的 SQS 事件,类似于 def handler(event, context) 行,但在 print_message.py 脚本中:

import os
import json

event = ???
print("Event: {}".format(event))

更新:包括“如何知道来源”

我的理解是您想将您创建的 docker 代码迁移到 Lambda 函数。您想要重用容器代码,并将其作为 Lambda 调用。

如果我的假设是正确的话。您的容器需要 运行 Lambda Runtime API. AWS provides base docker images 并预装 运行 时间。

将容器映像部署到 Lambda 时请注意 requirements,文档指出:

  • 容器映像必须实现 Lambda 运行时 API。
  • 容器映像必须能够 运行 在只读文件系统上。您的函数代码可以访问具有 512 MB 存储空间的可写 /tmp 目录。
  • 默认的 Lambda 用户必须能够读取 运行 您的函数代码所需的所有文件。 Lambda 通过定义具有最低特权权限的默认 Linux 用户来遵循安全最佳实践。验证您的应用程序代码不依赖于其他 Linux 用户被限制访问 运行ning 的文件。
  • Lambda 仅支持基于 Linux 的容器映像。

您在 zip 文件中使用的处理程序仍然是必需的,它是使用容器映像设置设置的:

Lambda 支持 Docker 文件中的以下容器映像设置,AWS 文档 outlines the following container 设置:

  • ENTRYPOINT – 指定应用程序入口点的绝对路径。

  • CMD – 指定要传入的参数 ENTRYPOINT.

  • WORKDIR – 指定工作目录的绝对路径。

  • ENV – 为 Lambda 函数指定一个环境变量。

这里有一个great blog post描述了CMDENTRYPOINT的区别。

following blog post 解释了如何创建可以作为 Lambda 函数部署的 docker 容器。

将容器部署到 ECR 后,您可以使用 CloudFormation like you have 将容器作为 Lambda 函数部署在 ECR 中,使用:AWS::Lambda::Function.

You set the package type to Image if the deployment 包是容器镜像。对于容器映像,代码 属性 必须包含 Amazon ECR 注册表中容器映像的 URI。您不需要指定处理程序和 运行time 属性,因为这是使用上面提到的容器设置设置的。

然后您还可以使用 CloudFormation 创建调用 Lambda 函数的 SQS 队列 AWS::Lambda::EventSourceMapping

可获得更多信息 here

作为 zip 或通过控制台部署的标准 node.js Lambda 函数的事件处理程序将传递三个参数:

  • 事件
  • 上下文
  • 回调

其他语言的结构相同。

  • Python: def lambda_handler(event, context):
  • Java: public String handleRequest(Map<String,String> event, Context context)
  • .Net: public async Task Handler(ILambdaContext context)
  • GoLang: func HandleRequest(ctx context.Context, name MyEvent) (string, error) {
  • Ruby: def handler(event:, context:)

事件函数 returns 有关调用事件的信息,在本例中为 SQS。该结构取决于调用服务。对于 SQS,它是:

"Records": [
        {
            "messageId": "5f3feef3-xxxx-xxxx-xxxx-xxxxxxx",
            "receiptHandle": "some handle",
            "body": "body from SQS message",
            "attributes": {
                "ApproximateReceiveCount": "1",
                "SentTimestamp": "1628768326353",
                "SenderId": "senderid",
                "ApproximateFirstReceiveTimestamp": "1628768326358"
            },
            "messageAttributes": {},
            "md5OfBody": "checksum",
            "eventSource": "aws:sqs",
            "eventSourceARN": "arn:aws:sqs:[REGION]:[AccountID]:[FunctionName]",
            "awsRegion": "REGION"
        }
    ]

您可以从事件中检查记录中的事件源字段以确定事件源是什么。

这个过程不会随着 Docker 部署而改变,在这里你仍然会有一个接收事件和上下文的处理程序。 Docker 图像的 CMD 指向处理程序。

这显示在以下博客 posts:

runtime interface client in your container image manages the interaction between Lambda and your function code. The Runtime API, along with the Extensions API, defines a simple HTTP interface 运行 次从 Lambda 接收调用事件并响应成功或失败指示。