启用 VPC 的 Lambda 函数不能 launch/access 同一 VPC 中的 EC2
VPC-enabled Lambda function cannot launch/access EC2 in the same VPC
我有一个启用了 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/subnet。
- 该功能使用与启动模板中使用的相同(VPC、子网、安全组)组合设置
- 执行角色设置为与启动模板中使用的 IAM 角色相同
- 您看到的功能只需要访问 EC2,不需要互联网访问
- 我将 run_instances() 替换为 describe_instance_status(使用直接从启动模板创建的实例 ID)并得到相同的错误。
该错误是网络错误,因此我假设授予 IAM 角色的权限一切正常(至少到目前为止)。如果 IAM 角色错过任何政策,我敢肯定会有不同的错误。
谁能指出我可能遗漏了什么?
看来问题出在您的 AWS Lambda 函数能够访问互联网,因为 Amazon EC2 API 端点在互联网上。
如果 Lambda 函数未附加到 VPC,它可以自动访问 Internet。
如果 Lambda 函数附加到 VPC 并且需要 Internet 访问,则配置应为:
- 仅将 Lambda 函数附加到 私有子网
- 在 public 子网
中启动 NAT 网关
- 在私有子网上配置路由Table以通过 NAT 网关发送互联网绑定流量 (
0.0.0.0/0
)
您的 VPC 似乎没有互联网网关,但它确实有一个用于 EC2 的 VPC 端点。
因此,为了尝试重现您的情况,我执行了以下操作:
- 创建了一个 新的 VPC,只有一个子网,但没有互联网网关
- 为 EC2 添加了一个 VPC 端点到子网
- 创建了一个将调用
DescribeInstances()
的 Lambda 函数 并将 Lambda 函数附加到子网
- 在 VPC 端点和 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 的响应,其中包含该区域中的实例列表。无需代码或更改。
我有一个启用了 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/subnet。
- 该功能使用与启动模板中使用的相同(VPC、子网、安全组)组合设置
- 执行角色设置为与启动模板中使用的 IAM 角色相同
- 您看到的功能只需要访问 EC2,不需要互联网访问
- 我将 run_instances() 替换为 describe_instance_status(使用直接从启动模板创建的实例 ID)并得到相同的错误。
该错误是网络错误,因此我假设授予 IAM 角色的权限一切正常(至少到目前为止)。如果 IAM 角色错过任何政策,我敢肯定会有不同的错误。
谁能指出我可能遗漏了什么?
看来问题出在您的 AWS Lambda 函数能够访问互联网,因为 Amazon EC2 API 端点在互联网上。
如果 Lambda 函数未附加到 VPC,它可以自动访问 Internet。
如果 Lambda 函数附加到 VPC 并且需要 Internet 访问,则配置应为:
- 仅将 Lambda 函数附加到 私有子网
- 在 public 子网 中启动 NAT 网关
- 在私有子网上配置路由Table以通过 NAT 网关发送互联网绑定流量 (
0.0.0.0/0
)
您的 VPC 似乎没有互联网网关,但它确实有一个用于 EC2 的 VPC 端点。
因此,为了尝试重现您的情况,我执行了以下操作:
- 创建了一个 新的 VPC,只有一个子网,但没有互联网网关
- 为 EC2 添加了一个 VPC 端点到子网
- 创建了一个将调用
DescribeInstances()
的 Lambda 函数 并将 Lambda 函数附加到子网 - 在 VPC 端点和 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 的响应,其中包含该区域中的实例列表。无需代码或更改。