教程:构建自定义运行时系统
在本教程中,您将创建一个具有自定义运行时的 Lambda 函数。首先,您在函数的部署程序包中包含运行时。然后,您将其迁移到一个您独立于函数管理的层。最后,您通过更新运行时层的基于资源的权限策略来将运行时层与全球共享。
先决条件
本教程假设您对 Lambda 基本操作和 Lambda 控制台有一定了解。如果您还没有了解,请按照 使用控制台创建 Lambda 函数 中的说明创建您的第一个 Lambda 函数。
要完成以下步骤,您需要 AWS 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
您需要一个 IAM 角色来创建 Lambda 函数。该角色需要权限方可将日志发送到 CloudWatch Logs 并访问您的函数使用的 AWS 服务。如果您没有函数开发的角色,请立即创建一个。
创建执行角色
-
在 IAM 控制台中,打开 Roles(角色)页面
。 -
选择创建角色。
-
创建具有以下属性的角色。
-
Trusted entity(可信任的实体)– Lambda。
-
Permissions(权限)– AWSLambdaBasicExecutionRole。
-
Role name(角色名称)–
lambda-role
。
AWSLambdaBasicExecutionRole 策略具有函数将日志写入 CloudWatch Logs 所需的权限。
-
创建函数
使用自定义运行时创建 Lambda 函数。此示例包含两个文件:一个运行时系统 bootstrap
文件和一个函数处理程序。两个文件都在 Bash 中实施。
-
为项目创建一个目录,然后切换到该目录。
mkdir runtime-tutorial cd runtime-tutorial
-
创建名为
bootstrap
的新文件。这是自定义运行时系统。例 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
标头。注意
运行时还具有其他职责(包括错误处理),并向处理程序提供上下文信息。有关详细信息,请参阅要求。
-
为函数创建脚本。以下示例脚本将定义一个处理程序函数,该函数将选取事件数据,将该数据记录到
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
-
使文件可执行并将其添加到 .zip 文件存档。这就是部署包。
chmod 755 function.sh bootstrap zip function.zip function.sh bootstrap
-
创建名为
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
-
调用函数。
aws lambda invoke --function-name bash-runtime --payload '{"text":"Hello"}' response.txt --cli-binary-format raw-in-base64-out
如果使用 cli-binary-format 版本 2,则 AWS CLI 选项是必需的。要将其设为默认设置,请运行
aws configure set cli-binary-format raw-in-base64-out
。有关更多信息,请参阅版本 2 的 AWS Command Line Interface 用户指南中的 AWS CLI 支持的全局命令行选项。应出现如下响应:
{ "StatusCode": 200, "ExecutedVersion": "$LATEST" }
-
验证响应。
cat response.txt
应出现如下响应:
Echoing request: '{"text":"Hello"}'
创建层
要将运行时代码与函数代码分开,请创建一个仅包含运行时的层。层可让您单独开发函数的各个依赖项,而且,通过对多个函数使用相同的层,还可以减少存储使用。有关更多信息,请参阅 使用层管理 Lambda 依赖项。
-
创建包含
bootstrap
文件的 .zip 文件。zip runtime.zip bootstrap
-
使用 publish-layer-version
命令创建层。 aws lambda publish-layer-version --layer-name bash-runtime --zip-file fileb://runtime.zip
这将创建第一个版本的层。
更新函数
要在函数中使用运行时系统层,请将函数配置为使用该层,并从函数中删除运行时代码。
-
更新函数配置以拉入到层。
aws lambda update-function-configuration --function-name bash-runtime \ --layers arn:aws:lambda:us-east-1:
123456789012
:layer:bash-runtime:1这会将运行时添加到
/opt
目录中的函数中。为确保 Lambda 使用层中的运行时系统,您必须从函数的部署包中移除boostrap
,如接下来的两个步骤所示。 -
创建包含函数代码的 .zip 文件。
zip function-only.zip function.sh
-
更新函数代码以仅包含处理程序脚本。
aws lambda update-function-code --function-name bash-runtime --zip-file fileb://function-only.zip
-
调用函数以确认它适用于运行时系统层。
aws lambda invoke --function-name bash-runtime --payload '{"text":"Hello"}' response.txt --cli-binary-format raw-in-base64-out
如果使用 cli-binary-format 版本 2,则 AWS CLI 选项是必需的。要将其设为默认设置,请运行
aws configure set cli-binary-format raw-in-base64-out
。有关更多信息,请参阅版本 2 的 AWS Command Line Interface 用户指南中的 AWS CLI 支持的全局命令行选项。应出现如下响应:
{ "StatusCode": 200, "ExecutedVersion": "$LATEST" }
-
验证响应。
cat response.txt
应出现如下响应:
Echoing request: '{"text":"Hello"}'
更新运行时
-
要记录有关执行环境的信息,请更新运行时脚本以输出环境变量。
例 bootstrap
#!/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 -
创建包含新版本
bootstrap
文件的 .zip 文件。zip runtime.zip bootstrap
-
创建新版本的
bash-runtime
层。aws lambda publish-layer-version --layer-name bash-runtime --zip-file fileb://runtime.zip
-
配置函数以使用新版本的层。
aws lambda update-function-configuration --function-name bash-runtime \ --layers arn:aws:lambda:us-east-1:
123456789012
:layer:bash-runtime:2
共享层
要与其他 AWS 账户 共享层,请在该层的基于资源的策略中添加跨账户权限语句。执行 add-layer-version-permissionprincipal
。在每个语句中,您可以向 AWS Organizations 中的单个账户、所有账户或组织授予权限。
以下示例向账户 111122223333 授予访问 bash-runtime
层版本 2 的权限。
aws lambda add-layer-version-permission \ --layer-name bash-runtime \ --version-number 2 \ --statement-id xaccount \ --action lambda:GetLayerVersion \ --principal 111122223333 \ --output text
您应该可以看到类似于如下所示的输出内容:
{"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