【问题标题】:Why can't an AWS lambda function inside a public subnet in a VPC connect to the internet?为什么 VPC 中公有子网内的 AWS lambda 函数无法连接到 Internet?
【发布时间】:2019-03-30 05:34:01
【问题描述】:

我按照教程 here 创建了一个具有公共子网和私有子网的 VPC。

然后我在公共子网中设置了一个 AWS lambda 函数来测试它是否可以连接到外部互联网。

这是我用 python3 编写的 lambda 函数

import requests

def lambda_handler(event, context):
    r = requests.get('http://www.google.com')
    print(r)

当我在 VPC 的公共子网中设置http://www.google.com 时,上述函数无法获取它的内容。

这是错误信息:

"errorMessage": "HTTPConnectionPool(host='www.google.com', port=80): url 超出最大重试次数:/(由 NewConnectionError(': 建立新连接失败:[Errno 110] 连接超时',))", "errorType": "ConnectionError",

我不明白为什么。

公有子网的路由表如下所示:

GEThttp://www.google.com 的请求应与 igw-XXXXXXXXX 目标匹配。为什么 internet-gateway(igw) 无法将请求发送到http://www.google.com 并取回网站内容?

这个article 说我必须在私有子网中设置 lambda 函数才能访问互联网。

如果您的 Lambda 函数需要访问私有 VPC 资源(例如 例如,Amazon RDS 数据库实例或 Amazon EC2 实例),您必须 将函数与 VPC 关联。如果您的功能还需要 互联网访问(例如,访问公共 AWS 服务端点), 您的函数必须使用 NAT 网关或实例。

但这并没有解释为什么我不能在公共子网中设置 lambda 函数。

【问题讨论】:

标签: amazon-web-services aws-lambda vpc


【解决方案1】:

连接到 VPC 公有子网的 Lambda 函数通常无法访问互联网。

要从公共子网访问互联网,您需要一个公共 IP,或者您需要通过本身具有公共 IP 的 NAT 进行路由。您还需要一个Internet Gateway (IGW)。然而:

  1. Lambda 函数没有也不能拥有公共 IP 地址,并且
  2. VPC 公共子网中的默认路由目标是 IGW,而不是 NAT

因此,由于 Lambda 函数只有一个私有 IP,并且它的流量被路由到 IGW 而不是 NAT,所以从 Lambda 函数到互联网的所有数据包都将在 IGW 被丢弃。

我应该为 VPC 访问配置我的 Lambda 函数吗?

如果您的 Lambda 函数不需要访问您的 VPC 内的私有资源(例如 RDS 数据库或 Elasticsearch 集群),则不要将 Lambda 函数配置为连接到 VPC。

如果您的 Lambda 函数确实需要访问 VPC 内的私有资源,则将 Lambda 函数配置为连接到私有子网(并且仅连接到私有子网)。

NAT 与否?

如果 Lambda 函数只需要访问 VPC 中的资源(例如私有子网中的 RDS 数据库),那么您不需要通过 NAT 路由。

如果 Lambda 函数只需要访问 VPC 中的资源和访问所有通过私有 VPC Endpoint 可用的 AWS 服务,那么您不需要通过 NAT 进行路由。使用 VPC 终端节点。

如果您的 Lambda 函数需要访问 Internet 上的终端节点,请确保从 Lambda 函数的私有子网到公有子网中的 NAT 实例或 NAT 网关的默认路由。如果需要,还可以配置 IGW,否则无法访问 Internet。

请注意 NAT gateway charges 每小时和每 GB 处理,因此值得了解 how to reduce data transfer costs for NAT gateway

最佳实践

在为 VPC 访问配置 Lambda 函数时,HA 最佳实践是跨不同可用区 (AZ) 配置多个(私有)子网。

间歇性连接

确保您为 Lambda 函数配置的所有子网都是私有子网。例如,配置 1 个私有子网和 1 个公共子网是一个常见错误。这将导致您的 Lambda 函数有时可以正常工作,而有时会在没有任何明显原因的情况下失败。

例如,Lambda 函数可能连续成功 5 次,然后超时失败(无法访问某些 Internet 资源或 AWS 服务)。发生这种情况是因为第一次启动在私有子网中,启动 2-5 在同一个私有子网中重用了相同的 Lambda 函数执行环境(所谓的“热启动”),然后启动 6 在公有子网中(a “冷启动”),其中 Lambda 函数没有到 Internet 的路由。

【讨论】:

  • 您是否有理由建议在私有子网中运行 lambda?与在公共平台上运行相比有什么缺点吗?
  • @LLL 退后一步,如果您需要在 VPC 中运行 Lambda 函数,例如因为他们需要访问私有资源,例如 VPC 内的 MySQL 数据库或 S3 存储桶,因此通过私有端点限制了对特定 VPC 的访问。在 VPC 中运行的缺点是冷启动延迟比不在 VPC 中运行时高(因为必须附加 ENI)。公共子网和私有子网之间的区别在于路由(0.0.0.0/0 默认路由指向,IGW 或 NAT)。如果您的 Lambda 需要出站访问,那么它将无法在公共子网中工作,因为默认路由是 IGW。
  • 谢谢!我没有意识到只有私有子网才能拥有 NAT GW,所以这很有意义。顺便说一句,在去这个兔子洞的时候,我还发现你实际上可以让一个 lambda 从公共子网访问互联网,但是需要将一个弹性 IP 附加到它的 ENI。我知道这很愚蠢,但很高兴知道。
  • 这一切又发生了变化。 AWS 已经听取了冷启动和 ENI 消耗问题,现在支持 Hyperplain for Lambda,您仍然需要额外添加适当的 IAM 权限,但看起来有重大改进:aws.amazon.com/blogs/compute/…
  • 谢谢!这是一个非常清楚的解释。
猜你喜欢
  • 2019-10-28
  • 2019-07-27
  • 2021-01-07
  • 2020-03-02
  • 2019-11-02
  • 2016-12-26
  • 2018-12-25
相关资源
最近更新 更多