启用 VPC 的 Lambda 函数无法在同一 VPC 中启动/访问 EC2
Posted
技术标签:
【中文标题】启用 VPC 的 Lambda 函数无法在同一 VPC 中启动/访问 EC2【英文标题】:VPC-enabled Lambda function cannot launch/access EC2 in the same VPC 【发布时间】:2019-12-31 20:58:00 【问题描述】:我有一个启用 VPC 的 Lambda 函数,它尝试使用启动模板启动 EC2。 EC2 启动步骤 (run_instances) 失败并出现以下一般网络错误。
调用调用 API 操作失败并显示以下消息:网络错误
我可以直接从启动模板成功启动实例,所以我认为启动模板一切正常。我在启动模板中配置了以下内容
亚马逊机器映像 ID 实例类型 密钥对 我在使用特定(VPC、子网、安全组)组合之前创建的网络接口 (ENI)。 IAM 角色Lambda 函数包含以下代码-
import json
import boto3
import time
def lambda_handler(event, context):
ec2_cl = boto3.client('ec2')
launch_temp = "LaunchTemplateId": "<<Launch Template ID>>"
resp_ec2_launch = ec2_cl.run_instances(MaxCount=1, MinCount=1, LaunchTemplate=launch_temp, SubnetId="<<Subnet ID>>")
关于 Lambda 函数的一些事情-
我在 run_instances() 调用中使用了子网,因为这不是默认的 vpc/子网。 使用启动模板中使用的相同(VPC、子网、安全组)组合设置该功能 执行角色设置为与启动模板中使用的 IAM 角色相同 您看到的功能只需要访问 EC2,不需要 Internet 访问 我将 run_instances() 替换为 describe_instance_status(使用直接从启动模板创建的实例 ID)并得到相同的错误。该错误是网络错误,因此我假设一切都很好(至少到目前为止)授予 IAM 角色的权限。如果 IAM 角色错过了任何政策,我确信会有不同的错误。
有人可以指出我可能缺少什么吗?
【问题讨论】:
boto 需要公共互联网,因此如果您的 lambda 在私有 vpc 中,您需要一个 nat 网关。 @Lamanus- 感谢您的回复。我不知道 boto3 默认需要访问互联网。我的 Lambda 代码无法访问 Internet,因此假设不需要 Internet 访问。我将尝试为我的 Lambda 提供 Internet 访问。 【参考方案1】:问题似乎在于您的 AWS Lambda 函数能够访问 Internet,因为 Amazon EC2 API 端点位于 Internet 上。
如果 Lambda 函数未附加到 VPC,则它可以自动访问 Internet。
如果 Lambda 函数附加到 VPC 并且需要 Internet 访问权限,则配置应为:
仅将 Lambda 函数附加到私有子网 在公共子网中启动 NAT 网关 配置私有子网上的路由表以通过 NAT 网关发送 Internet 绑定流量 (0.0.0.0/0
)
【讨论】:
感谢您的回复。正在启动的 EC2 在 VPC 内。你能告诉我为什么你说EC2 API端点在互联网上吗?我的理解是它在 VPC 内。 所有 AWS API 调用的端点都在 Internet 上(请参阅 AWS Service Endpoints - AWS General Reference)。这意味着,例如,可以从 Internet 上的任何位置请求启动 Amazon EC2 实例。这与启动实例的位置无关。如果您希望完全在 VPC 内调用AWS,则需要VPC Endpoint。 谢谢。创建 EC2 VPC 终端节点后,是否应该将其包含在其他位置(启动模板或 run_instances API)?我创建了一个 EC2 VPC 端点并测试了 Lambda 函数,但它失败并出现相同的网络错误,因此出现了问题。我可能需要在某处提及 EC2 VPC 端点。【参考方案2】:您的 VPC 似乎没有 Internet 网关,但它有一个用于 EC2 的 VPC 端点。
因此,为了尝试重现您的情况,我执行了以下操作:
创建了一个新的 VPC,只有一个子网,但没有 Internet 网关 向子网添加了 EC2 的 VPC 端点 创建了一个 Lambda 函数,它将调用DescribeInstances()
并将 Lambda 函数附加到子网
在 VPC Endpoint 和 Lambda 函数上打开了安全组,以允许来自任何地方的所有流量(嘿,这只是一个测试!)
我的 Lambda 函数:
import json
import boto3
def lambda_handler(event, context):
ec2 = boto3.client('ec2',region_name='ap-southeast-2')
print(ec2.describe_instances())
结果: Lambda 函数成功收到来自 EC2 的响应,其中包含区域中的实例列表。无需代码或更改。
【讨论】:
感谢您抽出宝贵时间回复。我的 Lambda 需要访问 VPC 中的 EC2,所以我不明白为什么应该允许来自任何地方的流量。不对外开放就不能实现吗? 要进行run_instances()
调用,Lambda 函数需要能够访问 Internet 上的 EC2 Endpoint(不是在 VPC 中)。因此,它要么需要访问 Internet(通过 NAT 网关),要么需要通过 EC2 的 VPC 端点访问。以上是关于启用 VPC 的 Lambda 函数无法在同一 VPC 中启动/访问 EC2的主要内容,如果未能解决你的问题,请参考以下文章
AWS Lambda 无法调用没有 VPC 的另一个 AWS Lambda - NodeJs
从没有 VPC 的 Lambda 连接到公共 Redshift 数据库
允许 VPC 中的 Lambda 访问同一 VPC 中的 Elasticsearch 域