【问题标题】:How to access the SQS event that triggered a Lambda deployed as a Docker image?如何访问触发部署为 Docker 映像的 Lambda 的 SQS 事件?
【发布时间】:2021-10-15 03:36:33
【问题描述】:

我目前有一个简单的 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

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

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

import os
import json

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

【问题讨论】:

  • 为了澄清,您是否希望 SQS 调用 ECR 中的服务,就像调用 Lambda 函数一样?
  • @Jason 我仍然想调用 Lambda 函数,但我不想将代码部署为 ZipFile,而是将其部署为运行特定脚本的 Docker 映像。我想知道如何将处理程序迁移到该脚本,以便处理从 SQS 收到的触发 Lambda 的消息。

标签: docker aws-lambda amazon-cloudformation amazon-sqs


【解决方案1】:

更新:加入“如何知道来源”

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

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

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

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

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

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

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

  • CMD – 指定要使用ENTRYPOINT 传入的参数。

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

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

这是一个great blog post,描述了CMDENTRYPOINT 之间的区别。

following blog 博文介绍了如何创建可部署为 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。您不需要指定处理程序和运行时属性,因为这是使用上述容器设置设置的。

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

更多信息请见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:)

事件函数返回有关调用事件的信息,在本例中为 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 指向处理程序。

这显示在以下博客文章中:

容器映像中的 runtime interface client 管理 Lambda 与函数代码之间的交互。 Runtime API 与 Extensions API 一起为运行时定义了一个简单的 HTTP interface,以接收来自 Lambda 的调用事件并以成功或失败指示进行响应。

【讨论】:

  • 嘿@Jason,对不起,我应该更清楚。我已经让这部分工作了,我唯一的疑问是问题的最后一行 - 我应该在 print_message.py 处理程序中放入什么代码,以便它可以打印出触发它的事件?我将更新问题以更具体。
  • @Kuba 我已经更新了我的答案,希望对您有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-07
  • 2020-05-17
相关资源
最近更新 更多