教程:构建自定义运行时系统 - Amazon Lambda
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

教程:构建自定义运行时系统

在本教程中,您将创建一个具有自定义运行时的 Lambda 函数。首先,您在函数的部署程序包中包含运行时。然后,您将其迁移到一个您独立于函数管理的层。最后,您通过更新运行时层的基于资源的权限策略来将运行时层与全球共享。

先决条件

本教程假设您对 Lambda 基本操作和 Lambda 控制台有一定了解。如果您还没有了解,请按照 使用控制台创建 Lambda 函数 中的说明创建您的第一个 Lambda 函数。

要完成以下步骤,您需要 Amazon Command Line Interface(Amazon CLI)版本 2。在单独的数据块中列出了命令和预期输出:

aws --version

您应看到以下输出:

aws-cli/2.13.27 Python/3.11.6 Linux/4.14.328-248.540.amzn2.x86_64 exe/x86_64.amzn.2

对于长命令,使用转义字符 (\) 将命令拆分为多行。

在 Linux 和 macOS 中,可使用您首选的 shell 和程序包管理器。

注意

在 Windows 中,操作系统的内置终端不支持您经常与 Lambda 一起使用的某些 Bash CLI 命令(例如 zip)。安装 Windows Subsystem for Linux,获取 Ubuntu 和 Bash 与 Windows 集成的版本。本指南中的示例 CLI 命令使用 Linux 格式。如果您使用的是 Windows CLI,则必须重新格式化包含内联 JSON 文档的命令。

您需要一个 IAM 角色来创建 Lambda 函数。该角色需要权限才能将日志发送到 CloudWatch 日志并访问您的函数使用的Amazon服务。如果您没有函数开发的角色,请立即创建一个。

创建执行角色
  1. 在 IAM 控制台中,打开 Roles(角色)页面

  2. 选择创建角色

  3. 创建具有以下属性的角色。

    • Trusted entity(可信任的实体)– Lambda

    • 权限AWSLambdaBasicExecutionRole.

    • Role name(角色名称)– lambda-role

    AWSLambdaBasicExecutionRole策略具有该函数将日志写入 CloudWatch 日志所需的权限。

创建函数

使用自定义运行时创建 Lambda 函数。此示例包含两个文件:一个运行时系统 bootstrap 文件和一个函数处理程序。两个文件都在 Bash 中实施。

  1. 为项目创建一个目录,然后切换到该目录。

    mkdir runtime-tutorial cd runtime-tutorial
  2. 创建名为 bootstrap 的新文件。这是自定义运行时系统。

    例 引导
    #!/bin/sh set -euo pipefail # Initialization - load function handler source $LAMBDA_TASK_ROOT/"$(echo $_HANDLER | cut -d. -f1).sh" # Processing while true do HEADERS="$(mktemp)" # Get an event. The HTTP request will block until one is received EVENT_DATA=$(curl -sS -LD "$HEADERS" "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next") # Extract request ID by scraping response headers received above REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2) # Run the handler function from the script RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA") # Send the response curl "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response" -d "$RESPONSE" done

    运行时将从部署程序包加载函数脚本。它使用两个变量来查找脚本。LAMBDA_TASK_ROOT 向它告知在何处提取程序包,_HANDLER 包含脚本的名称。

    在运行时系统加载函数脚本之后,它会使用运行时系统 API 从 Lambda 检索调用事件,并将事件传递到处理程序,然后将响应发送回 Lambda。为了获取请求 ID,运行时会将来自 API 响应的标头保存到临时文件,并从该文件读取 Lambda-Runtime-Aws-Request-Id 标头。

    注意

    运行时还具有其他职责(包括错误处理),并向处理程序提供上下文信息。有关详细信息,请参阅要求

  3. 为函数创建脚本。以下示例脚本将定义一个处理程序函数,该函数将选取事件数据,将该数据记录到 stderr,然后返回它。

    例 function.sh
    function handler () { EVENT_DATA=$1 echo "$EVENT_DATA" 1>&2; RESPONSE="Echoing request: '$EVENT_DATA'" echo $RESPONSE }

    runtime-tutorial 目录现在应如下所示:

    runtime-tutorial ├ bootstrap └ function.sh
  4. 使文件可执行并将其添加到 .zip 文件存档。这就是部署包。

    chmod 755 function.sh bootstrap zip function.zip function.sh bootstrap
  5. 创建名为 bash-runtime 的函数。对于 --role,请输入您的 Lambda 执行角色的 ARN。

    aws lambda create-function --function-name bash-runtime \ --zip-file fileb://function.zip --handler function.handler --runtime provided.al2023 \ --role arn:aws:iam::123456789012:role/lambda-role
  6. 调用函数。

    aws lambda invoke --function-name bash-runtime --payload '{"text":"Hello"}' response.txt --cli-binary-format raw-in-base64-out

    如果使用 cli-binary-format 版本 2,则 Amazon CLI 选项是必需的。要将其设为默认设置,请运行 aws configure set cli-binary-format raw-in-base64-out。有关更多信息,请参阅版本 2 的 Amazon Command Line Interface 用户指南中的 Amazon CLI 支持的全局命令行选项

    应出现如下响应:

    { "StatusCode": 200, "ExecutedVersion": "$LATEST" }
  7. 验证响应。

    cat response.txt

    应出现如下响应:

    Echoing request: '{"text":"Hello"}'

创建层

要将运行时代码与函数代码分开,请创建一个仅包含运行时的层。层可让您单独开发函数的各个依赖项,而且,通过对多个函数使用相同的层,还可以减少存储使用。有关更多信息,请参阅使用层管理 Lambda 依赖项

  1. 创建包含 bootstrap 文件的 .zip 文件。

    zip runtime.zip bootstrap
  2. 使用 publish-layer-version 命令创建层。

    aws lambda publish-layer-version --layer-name bash-runtime --zip-file fileb://runtime.zip

    这将创建第一个版本的层。

更新函数

要在函数中使用运行时系统层,请将函数配置为使用该层,并从函数中删除运行时代码。

  1. 更新函数配置以拉入到层。

    aws lambda update-function-configuration --function-name bash-runtime \ --layers arn:aws:lambda:us-east-1:123456789012:layer:bash-runtime:1

    这会将运行时添加到 /opt 目录中的函数中。为确保 Lambda 使用层中的运行时系统,您必须从函数的部署包中移除 boostrap,如接下来的两个步骤所示。

  2. 创建包含函数代码的 .zip 文件。

    zip function-only.zip function.sh
  3. 更新函数代码以仅包含处理程序脚本。

    aws lambda update-function-code --function-name bash-runtime --zip-file fileb://function-only.zip
  4. 调用函数以确认它适用于运行时系统层。

    aws lambda invoke --function-name bash-runtime --payload '{"text":"Hello"}' response.txt --cli-binary-format raw-in-base64-out

    如果使用 cli-binary-format 版本 2,则 Amazon CLI 选项是必需的。要将其设为默认设置,请运行 aws configure set cli-binary-format raw-in-base64-out。有关更多信息,请参阅版本 2 的 Amazon Command Line Interface 用户指南中的 Amazon CLI 支持的全局命令行选项

    应出现如下响应:

    { "StatusCode": 200, "ExecutedVersion": "$LATEST" }
  5. 验证响应。

    cat response.txt

    应出现如下响应:

    Echoing request: '{"text":"Hello"}'

更新运行时

  1. 要记录有关执行环境的信息,请更新运行时脚本以输出环境变量。

    例 引导
    #!/bin/sh set -euo pipefail # Configure runtime to output environment variables echo "## Environment variables:" env # Load function handler source $LAMBDA_TASK_ROOT/"$(echo $_HANDLER | cut -d. -f1).sh" # Processing while true do HEADERS="$(mktemp)" # Get an event. The HTTP request will block until one is received EVENT_DATA=$(curl -sS -LD "$HEADERS" "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next") # Extract request ID by scraping response headers received above REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2) # Run the handler function from the script RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA") # Send the response curl "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response" -d "$RESPONSE" done
  2. 创建包含新版本 bootstrap 文件的 .zip 文件。

    zip runtime.zip bootstrap
  3. 创建新版本的 bash-runtime 层。

    aws lambda publish-layer-version --layer-name bash-runtime --zip-file fileb://runtime.zip
  4. 配置函数以使用新版本的层。

    aws lambda update-function-configuration --function-name bash-runtime \ --layers arn:aws:lambda:us-east-1:123456789012:layer:bash-runtime:2

共享层

要向另一个账户授予层使用权限,请使用 add-layer-version-permission 命令向层版本的权限策略添加语句。在每个语句中,您可以向单个账户、所有账户或组织授予权限。

以下示例向账户 111122223333 授予访问 bash-runtime 层版本 2 的权限。

aws lambda add-layer-version-permission --layer-name bash-runtime --statement-id xaccount \ --action lambda:GetLayerVersion --principal 111122223333 --version-number 2 --output text

您应该可以看到类似于如下所示的输出内容:

e210ffdc-e901-43b0-824b-5fcd0dd26d16 {"Sid":"xaccount","Effect":"Allow","Principal":{"AWS":"arn:aws:iam::111122223333:root"},"Action":"lambda:GetLayerVersion","Resource":"arn:aws:lambda:us-east-1:123456789012:layer:bash-runtime:2"}

权限仅适用于单个层版本。每次创建新的层版本时都需重复此过程。

清理

删除每个版本的层。

aws lambda delete-layer-version --layer-name bash-runtime --version-number 1 aws lambda delete-layer-version --layer-name bash-runtime --version-number 2

由于函数包含对版本 2 的层的引用,因此该层仍然存在于 Lambda 中。函数可继续工作,但无法再被配置为使用删除的版本。如果您修改了函数的层的列表,则必须指定新版本或忽略已删除的层。

使用 delete-function 命令删除函数。

aws lambda delete-function --function-name bash-runtime