AWS Lambda
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

教程 – 发布自定义运行时

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

先决条件

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

为了遵循本指南中的步骤,您需要命令行终端或外壳,以便运行命令。命令显示在列表中,以提示符 ($) 和当前目录名称(如果有)开头:

~/lambda-project$ this is a command this is output

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

在 Linux 和 macOS 中,可使用您首选的外壳程序和程序包管理器。在 Windows 10 中,您可以 安装 Windows Subsystem for Linux,获取 Ubuntu 和 Bash 与 Windows 集成的版本。

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

创建执行角色

  1. 打开 IAM 控制台中的“角色”页面

  2. 选择 Create role (创建角色)

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

    • 可信任的实体Lambda

    • 权限AWSLambdaBasicExecutionRole

    • 角色名称 (角色名称)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 EVENT_DATA=$(curl -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next") REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2) # Execute 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::123456789012:role/lambda-role { "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", "CodeSize": 831, "Description": "", "Timeout": 3, "MemorySize": 128, "LastModified": "2018-11-28T06:57:31.095+0000", "CodeSha256": "mv/xRv84LPCxdpcbKvmwuuFzwo7sLwUO1VxcUv3wKlM=", "Version": "$LATEST", "TracingConfig": { "Mode": "PassThrough" }, "RevisionId": "2e1d51b0-6144-4763-8e5c-7d5672a01713" }

调用函数并验证响应。

runtime-tutorial$ aws lambda invoke --function-name bash-runtime --payload '{"text":"Hello"}' response.txt { "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:123456789012:layer:bash-runtime:1 { "FunctionName": "bash-runtime", "Layers": [ { "Arn": "arn:aws:lambda:us-west-2:123456789012:layer:bash-runtime:1", "CodeSize": 584, "UncompressedCodeSize": 679 } ] ... }

这会将运行时添加到 /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 { "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