教程 – 发布自定义运行时
在本教程中,您将创建一个具有自定义运行时的 Lambda 函数。首先,您在函数的部署程序包中包含运行时。然后,您将其迁移到一个您独立于函数管理的层。最后,您通过更新运行时层的基于资源的权限策略来将运行时层与全球共享。
先决条件
本教程假设您对 Lambda 基本操作和 Lambda 控制台有一定了解。如果您还没有了解,请按照 使用控制台创建 Lambda 函数 中的说明创建您的第一个 Lambda 函数。
要完成以下步骤,您需要命令行终端或 Shell,以便运行命令。在单独的数据块中列出了命令和预期输出:
aws --version
您应看到以下输出:
aws-cli/2.0.57 Python/3.7.4 Darwin/19.6.0 exe/x86_64
对于长命令,使用转义字符 (\
) 将命令拆分为多行。
在 Linux 和 macOS 中,可使用您首选的外壳程序和程序包管理器。在 Windows 10 中,您可以 安装 Windows Subsystem for Linux
您需要一个 IAM 角色来创建 Lambda 函数。该角色需要权限方可将日志发送到 CloudWatch Logs 并访问您的函数使用的Amazon服务。如果您没有函数开发的角色,请立即创建一个。
创建执行角色
-
在 IAM 控制台中,打开 Roles(角色)页面
。 -
选择 Create role(创建角色)。
-
创建具有以下属性的角色。
-
Trusted entity(可信任的实体)– Lambda。
-
Permissions(权限)– AWSLambdaBasicExecutionRole。
-
Role name(角色名称)–
lambda-role
。
AWSLambdaBasicExecutionRole 策略具有函数将日志写入 CloudWatch Logs 所需的权限。
-
创建函数
使用自定义运行时创建 Lambda 函数。此示例包含两个文件 - 一个运行时 bootstrap
文件和一个函数处理程序。两个文件都在 Bash 中实施。
运行时将从部署程序包加载函数脚本。它使用两个变量来查找脚本。LAMBDA_TASK_ROOT
向它告知在何处提取程序包,_HANDLER
包含脚本的名称。
例 引导
#!/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" -X GET "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 -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response" -d "$RESPONSE" done
加载脚本后,运行时将在一个循环中处理事件。它会使用运行时 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 文件存档。
runtime-tutorial$
chmod 755 function.sh bootstrap
runtime-tutorial$zip function.zip function.sh bootstrap
adding: function.sh (deflated 24%) adding: bootstrap (deflated 39%)
创建名为 bash-runtime
的函数。
runtime-tutorial$
aws lambda create-function --function-name bash-runtime \ --zip-file fileb://function.zip --handler function.handler --runtime provided \ --role arn:aws:iam::
{ "FunctionName": "bash-runtime", "FunctionArn": "arn:aws:lambda:us-west-2:123456789012:function:bash-runtime", "Runtime": "provided", "Role": "arn:aws:iam::123456789012:role/lambda-role", "Handler": "function.handler", "CodeSha256": "mv/xRv84LPCxdpcbKvmwuuFzwo7sLwUO1VxcUv3wKlM=", "Version": "$LATEST", "TracingConfig": { "Mode": "PassThrough" }, "RevisionId": "2e1d51b0-6144-4763-8e5c-7d5672a01713", ... }123456789012
:role/lambda-role
调用函数并验证响应。
runtime-tutorial$
aws lambda invoke --function-name bash-runtime --payload '{"text":"Hello"}' response.txt --cli-binary-format raw-in-base64-out
{ "StatusCode": 200, "ExecutedVersion": "$LATEST" } runtime-tutorial$cat response.txt
Echoing request: '{"text":"Hello"}'
创建层
要将运行时代码与函数代码分开,请创建一个仅包含运行时的层。层可让您单独开发函数的各个依赖项,而且,通过对多个函数使用相同的层,还可以减少存储使用。
创建一个包含 bootstrap
文件的层存档。
runtime-tutorial$
zip runtime.zip bootstrap
adding: bootstrap (deflated 39%)
使用 publish-layer-version
命令创建层。
runtime-tutorial$
aws lambda publish-layer-version --layer-name bash-runtime --zip-file fileb://runtime.zip
{ "Content": { "Location": "https://awslambda-us-west-2-layers.s3.us-west-2.amazonaws.com/snapshots/123456789012/bash-runtime-018c209b...", "CodeSha256": "bXVLhHi+D3H1QbDARUVPrDwlC7bssPxySQqt1QZqusE=", "CodeSize": 584, "UncompressedCodeSize": 0 }, "LayerArn": "arn:aws:lambda:us-west-2:123456789012:layer:bash-runtime", "LayerVersionArn": "arn:aws:lambda:us-west-2:123456789012:layer:bash-runtime:1", "Description": "", "CreatedDate": "2018-11-28T07:49:14.476+0000", "Version": 1 }
这将创建第一个版本的层。
更新函数
要将运行时层与函数一起使用,请将函数配置为使用该层,并从函数中删除运行时代码。
更新函数配置以拉入到层。
runtime-tutorial$
aws lambda update-function-configuration --function-name bash-runtime \ --layers arn:aws:lambda:us-west-2:
{ "FunctionName": "bash-runtime", "Layers": [ { "Arn": "arn:aws:lambda:us-west-2:123456789012:layer:bash-runtime:1", "CodeSize": 584, "UncompressedCodeSize": 679 } ] ... }123456789012
:layer:bash-runtime:1
这会将运行时添加到 /opt
目录中的函数中。Lambda 会使用此运行时,但前提是您将其从函数的部署包中删除。更新函数代码以仅包含处理程序脚本。
runtime-tutorial$
zip function-only.zip function.sh
adding: function.sh (deflated 24%) runtime-tutorial$aws lambda update-function-code --function-name bash-runtime --zip-file fileb://function-only.zip
{ "FunctionName": "bash-runtime", "CodeSize": 270, "Layers": [ { "Arn": "arn:aws:lambda:us-west-2:123456789012:layer:bash-runtime:7", "CodeSize": 584, "UncompressedCodeSize": 679 } ] ... }
调用函数以验证它是否适用于运行时层。
runtime-tutorial$
aws lambda invoke --function-name bash-runtime --payload '{"text":"Hello"}' response.txt --cli-binary-format raw-in-base64-out
{ "StatusCode": 200, "ExecutedVersion": "$LATEST" } runtime-tutorial$cat response.txt
Echoing request: '{"text":"Hello"}'
更新运行时
要记录有关执行环境的信息,请更新运行时脚本以输出环境变量。
例 引导
#!/bin/sh set -euo pipefail echo "## Environment variables:" env # Initialization - load function handler source $LAMBDA_TASK_ROOT/"$(echo $_HANDLER | cut -d. -f1).sh" ...
使用新代码创建另一个版本的层。
runtime-tutorial$
zip runtime.zip bootstrap
updating: bootstrap (deflated 39%) runtime-tutorial$aws lambda publish-layer-version --layer-name bash-runtime --zip-file fileb://runtime.zip
配置函数以使用新版本的层。
runtime-tutorial$
aws lambda update-function-configuration --function-name bash-runtime \ --layers arn:aws:lambda:us-west-2:
123456789012
:layer:bash-runtime:2
共享层
将权限语句添加到运行时层以将其与其他账户共享。
runtime-tutorial$
aws lambda add-layer-version-permission --layer-name bash-runtime --version-number 2 \ --principal "*" --statement-id publish --action lambda:GetLayerVersion
{ "Statement": "{\"Sid\":\"publish\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"lambda:GetLayerVersion\",\"Resource\":\"arn:aws:lambda:us-west-2:123456789012:layer:bash-runtime:2\"}", "RevisionId": "9d5fe08e-2a1e-4981-b783-37ab551247ff" }
您可以添加多个语句,每个语句都会向单个账户、组织中的账户或所有账户授予权限。
清除
删除每个版本的层。
runtime-tutorial$
aws lambda delete-layer-version --layer-name bash-runtime --version-number 1
runtime-tutorial$aws lambda delete-layer-version --layer-name bash-runtime --version-number 2
由于函数包含对版本 2 的层的引用,因此该层仍然存在于 Lambda 中。函数可继续工作,但无法再被配置为使用删除的版本。如果您随后修改了函数的层的列表,则必须指定新版本或忽略已删除的层。
使用 delete-function
命令删除教程函数。
runtime-tutorial$
aws lambda delete-function --function-name bash-runtime