将出站联网连接到 VPC 中的资源 - Amazon Lambda
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

将出站联网连接到 VPC 中的资源

您可以配置 Lambda 函数来连接到您 Amazon 账户中虚拟私有云(VPC)的私有子网。使用 Amazon Virtual Private Cloud (Amazon VPC) 为资源(如数据库、缓存实例或内部服务)创建私有网络。将函数连接到 VPC,以便在函数运行时访问私有资源。这一部分提供了 Lambda VPC 连接的摘要。有关 Lambda 中的 VPC 联网的详细信息,请参阅使用 VPC 进行私有联网

提示

要配置 Lambda 函数访问 VPC 和子网,您可以使用 Lambda 控制台或 API。

要配置您的函数 CreateFunction,请参阅中的VpcConfig部分。有关详细步骤,请参阅 配置 VPC 访问(控制台) 和 配置 VPC 访问 (API)

将函数连接到 VPC 时,Lambda 会在函数的 VPC 配置中将函数分配到每个子网的一个 Hyperplane ENI(弹性网络接口)。首次为账户中支持 VPC 的函数定义唯一的子网和安全组组合时,Lambda 将会创建一个 Hyperplane ENI。

Lambda 创建 Hyperplane ENI 时,您无法执行针对该函数的其他操作,例如创建版本或更新函数的代码。对于新函数,在函数状态从 Pending 更改为 Active 之前,您无法调用该函数。对于现有函数,在更新过程中您仍然可以调用之前的版本。有关 Hyperplane ENI 生命周期的详细信息,请参阅 Lambda Hyperplane ENI

Lambda 函数无法直接连接到具有专用实例租赁的 VPC。要连接到专用 VPC 中的资源,请使其与具有默认租赁的第二个 VPC 对等

管理 VPC 连接

如果多个函数共享同一个子网和安全组,则这些函数可以共享一个网络接口。与创建新的网络接口相比,将附加函数连接到具有现有 Lambda 托管式网络接口的相同 VPC 配置(子网和安全组)要远远更快。

如果您的函数长时间未处于活动状态,则 Lambda 会回收其网络接口,且函数变为 Idle。要重新激活空闲函数,请调用它。此调用失败,并且函数再次进入 Pending 状态,直到网络接口可用。

如果您将函数更新为访问其他 VPC,则它将会终止从 Hyperplane ENI 到旧 VPC 的连接。更新至新 VPC 的连接可能需要几分钟的时间。在此期间,Lambda 会将函数调用连接到之前的 VPC。更新完成后,新的调用将开始使用新的 VPC,并且 Lambda 函数不再连接到旧 VPC。

对于短期操作(如 DynamoDB 查询),设置 TCP 连接的延迟开销可能大于操作本身。为了确保重复使用短期/不经常调用函数的连接,我们建议您为在函数初始化期间创建的连接使用 TCP keep-alive,以免为后续调用创建新连接。有关借助 keep-alive 重复使用连接的更多信息,请参阅有关重复使用连接的 Lambda 文档

执行角色和用户权限

Lambda 使用函数的权限来创建和管理网络接口。要连接到 VPC,您的函数的执行角色必须具有以下权限:

执行角色权限
  • ec2: CreateNetworkInterface

  • ec2: DescribeNetworkInterfaces — 此操作仅在所有资源上都允许的情况下才有效 ("Resource": "*")。

  • ec2: DeleteNetworkInterface — 如果您未在执行角色DeleteNetworkInterface中为指定资源 ID,则您的函数可能无法访问 VPC。请指定唯一的资源 ID,或包含所有资源 ID,例如 "Resource": "arn:aws:ec2:us-west-2:123456789012:*/*"

  • ec2: AssignPrivateIpAddresses

  • ec2: UnassignPrivateIpAddresses

这些权限包含在Amazon托管策略中AWSLambdaVPCAccessExecutionRole。请注意,仅在创建 ENI 时需要这些权限,而调用您的 VPC 函数时则不需要。换句话说,即便您从执行角色中删除了这些权限,仍然能够成功调用您的 VPC 函数。要完全取消您的 Lambda 函数与 VPC 的关联,请使用控制台或 UpdateFunctionConfigurationAPI 更新该函数的 VPC 配置设置。

配置 VPC 连接时,Lambda 使用您的权限来验证网络资源。要配置函数以连接到 VPC,您的用户需要以下权限:

用户权限
  • ec2: DescribeSecurityGroups

  • ec2: DescribeSubnets

  • ec2: DescribeVpcs

配置 VPC 访问(控制台)

如果您的 IAM 权限仅允许创建连接到 VPC 的 Lambda 函数,则必须在创建函数时配置 VPC。如果您的 IAM 权限允许您创建未连接到 VPC 的函数,则可以在创建函数后添加 VPC 配置。

在创建函数时配置 VPC
  1. 打开 Lamba 控制台的 Functions page(函数页面)。

  2. 选择 Create function(创建函数)。

  3. 基本信息下的函数名称中输入函数的名称。

  4. 展开 Advanced settings(高级设置)。

  5. 选择启用 VPC,然后选择您希望函数访问的 VPC。

  6. (可选)要允许出站 IPv6 流量,请选择允许双堆栈子网的 IPv6 流量

  7. 选择子网和安全组。如果您已选择允许双堆栈子网的 IPv6 流量,则所有选定的子网都必须具有 IPv4 CIDR 块和 IPv6 CIDR 块。

    注意

    要访问私有资源,请将函数连接到私有子网。如果您的函数需要 Internet 访问权限,请使用网络地址转换 (NAT)。将函数连接到公有子网不会授予其 Internet 访问权限或公有 IP 地址。

  8. 选择 Create function(创建函数)。

为现有函数配置 VPC
  1. 打开 Lamba 控制台的 Functions page(函数页面)。

  2. 选择函数。

  3. 选择 Configuration(配置),然后选择 VPC

  4. VPC 下,选择 Edit(编辑)。

  5. 选择您希望函数访问的 VPC。

  6. (可选)要允许出站 IPv6 流量,请选择允许双堆栈子网的 IPv6 流量

  7. 选择子网和安全组。如果您已选择允许双堆栈子网的 IPv6 流量,则所有选定的子网都必须具有 IPv4 CIDR 块和 IPv6 CIDR 块。

    注意

    要访问私有资源,请将函数连接到私有子网。如果您的函数需要 Internet 访问权限,请使用网络地址转换 (NAT)。将函数连接到公有子网不会授予其 Internet 访问权限或公有 IP 地址。

  8. 选择 Save(保存)。

配置 VPC 访问 (API)

要将 Lambda 函数连接到 VPC,您可以使用以下 API 操作:

要创建函数并使用 Amazon Command Line Interface (Amazon CLI) 将其连接到 VPC,您可以使用带 create-function 选项的 VpcConfig 命令。以下示例会创建具有 VPC 连接的函数。该函数可以访问两个子网和一个安全组,并允许出站 IPv6 流量

aws lambda create-function --function-name my-function \ --runtime nodejs20.x --handler index.js --zip-file fileb://function.zip \ --role arn:aws:iam::123456789012:role/lambda-role \ --vpc-config Ipv6AllowedForDualStack=true,SubnetIds=subnet-071f712345678e7c8,subnet-07fd123456788a036,SecurityGroupIds=sg-085912345678492fb

要将现有函数连接到 VPC,请将 update-function-configuration 命令与 vpc-config 选项结合使用。

aws lambda update-function-configuration --function-name my-function \ --vpc-config SubnetIds=subnet-071f712345678e7c8,subnet-07fd123456788a036,SecurityGroupIds=sg-085912345678492fb

要断开函数与 VPC 的连接,请使用子网和安全组的空白列表更新函数配置。

aws lambda update-function-configuration --function-name my-function \ --vpc-config SubnetIds=[],SecurityGroupIds=[]

将 IAM 条件键用于 VPC 设置

您可以将特定于 Lambda 的条件键用于 VPC 设置,从而为您的 Lambda 函数提供额外的权限控制。例如,您可以要求组织中的所有函数都连接到 VPC。您还可以指定函数的用户可以使用和不能使用的子网和安全组。

Lambda 在 IAM policy 中支持以下条件键:

  • lambda: VpcIds — 允许或拒绝一个或多个 VPC。

  • lambda: SubnetIds — 允许或拒绝一个或多个子网。

  • lambda: SecurityGroupIds — 允许或拒绝一个或多个安全组。

Lambda API 操作CreateFunctionUpdateFunctionConfiguration支持这些条件密钥。有关在 IAM policy 中使用条件键的更多信息,请参阅《IAM 用户指南》中的IAM JSON policy 元素:条件

提示

如果您的函数已包含来自前一个 API 请求的 VPC 配置,则可以发送不带 VPC 配置的 UpdateFunctionConfiguration 请求。

带有用于 VPC 设置的条件键的示例策略

以下示例演示如何将条件键用于 VPC 设置。创建具有所需限制的策略语句后,为目标用户或角色附加策略语句。

确保用户仅部署与 VPC 连接的函数

要确保所有用户仅部署与 VPC 连接的函数,您可以拒绝不包含有效 VPC ID 的函数创建和更新操作。

请注意,VPC ID 不是 CreateFunctionUpdateFunctionConfiguration 请求的输入参数。Lambda 根据子网和安全组参数检索 VPC ID 值。

{ "Version": "2012-10-17", "Statement": [ { "Sid": "EnforceVPCFunction", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Deny", "Resource": "*", "Condition": { "Null": { "lambda:VpcIds": "true" } } } ] }

拒绝用户访问特定的 VPC、子网或安全组

要拒绝用户访问特定 VPC,请使用 StringEquals 检查 lambda:VpcIds 条件的值。以下示例拒绝用户访问 vpc-1vpc-2

{ "Version": "2012-10-17", "Statement": [ { "Sid": "EnforceOutOfVPC", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Deny", "Resource": "*", "Condition": { "StringEquals": { "lambda:VpcIds": ["vpc-1", "vpc-2"] } } }

要拒绝用户访问特定子网,请使用 StringEquals 检查 lambda:SubnetIds 条件的值。以下示例拒绝用户访问 subnet-1subnet-2

{ "Sid": "EnforceOutOfSubnet", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Deny", "Resource": "*", "Condition": { "ForAnyValue:StringEquals": { "lambda:SubnetIds": ["subnet-1", "subnet-2"] } } }

要拒绝用户访问特定安全组,请使用 StringEquals 检查 lambda:SecurityGroupIds 条件的值。以下示例拒绝用户访问 sg-1sg-2

{ "Sid": "EnforceOutOfSecurityGroups", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Deny", "Resource": "*", "Condition": { "ForAnyValue:StringEquals": { "lambda:SecurityGroupIds": ["sg-1", "sg-2"] } } } ] }

允许用户使用特定 VPC 设置创建和更新函数

要允许用户访问特定的 VPC,请使用 StringEquals 检查 lambda:VpcIds 条件的值。以下示例允许用户访问 vpc-1vpc-2

{ "Version": "2012-10-17", "Statement": [ { "Sid": "EnforceStayInSpecificVpc", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Allow", "Resource": "*", "Condition": { "StringEquals": { "lambda:VpcIds": ["vpc-1", "vpc-2"] } } }

要允许用户访问特定子网,请使用 StringEquals 检查 lambda:SubnetIds 条件的值。以下示例允许用户访问 subnet-1subnet-2

{ "Sid": "EnforceStayInSpecificSubnets", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Allow", "Resource": "*", "Condition": { "ForAllValues:StringEquals": { "lambda:SubnetIds": ["subnet-1", "subnet-2"] } } }

要允许用户访问特定的安全组, 请使用 StringEquals 检查 lambda:SecurityGroupIds 条件的值。以下示例允许用户访问 sg-1sg-2

{ "Sid": "EnforceStayInSpecificSecurityGroup", "Action": [ "lambda:CreateFunction", "lambda:UpdateFunctionConfiguration" ], "Effect": "Allow", "Resource": "*", "Condition": { "ForAllValues:StringEquals": { "lambda:SecurityGroupIds": ["sg-1", "sg-2"] } } } ] }

VPC 连接函数的 Internet 和服务访问

默认情况下,Lambda 在可访问 Amazon 服务和互联网的安全 VPC 中运行您的函数。Lambda 拥有此 VPC,该 VPC 未连接到您账户的默认 VPC。在将函数连接到您账户中的 VPC 时,除非 VPC 提供访问权限,否则此函数将无法访问 Internet。

注意

一些Amazon服务提供了 VPC 端点。您可以使用 VPC 端点从 VPC 内连接到Amazon服务,而无需互联网访问权限。

从私有子网访问 Internet 需要网络地址转换 (NAT)。要使您的函数能够访问 Internet,请将出站流量路由到公有子网中的 NAT 网关。NAT 网关具有公共 IP 地址,可以通过 VPC 的互联网网关连接到互联网。空闲 NAT 网关连接将在 350 秒后超时。有关更多信息,请参阅如何在 VPC 中为我的 Lambda 函数提供 Internet 访问权限?

VPC 教程

在以下教程中,您会将 Lambda 函数连接到 VPC 中的资源。

VPC 配置示例

您可以使用以下示例 Amazon CloudFormation 模板创建要与 Lambda 函数一起使用的 VPC 配置。本指南的 GitHub 存储库中有两个模板可用:

  • vpc-private.yaml – 此 VPC 具有两个用于 Amazon Simple Storage Service (Amazon S3) 与 Amazon DynamoDB 的私有子网和 VPC 端点。使用此模板为不需要 Internet 访问权限的函数创建 VPC。此配置支持与 Amazon 软件开发工具包一起使用 Simple Storage Service (Amazon S3) 和 DynamoDB,以及通过本地网络连接访问相同 VPC 中的数据库资源。

  • vpc-privatepublic.yaml – 此 VPC 具有两个私有子网、VPC 端点、一个具有 NAT 网关的公有子网,以及一个互联网网关。来自私有子网中函数的 Internet 相关流量将通过路由表路由到 NAT 网关。

要使用模板创建 VPC,请在 Amazon CloudFormation 控制台的 Stacks(堆栈)页面上选择 Create stack(创建堆栈),然后按照 Create stack(创建堆栈)向导中的说明操作。