使用测试触发器或计划的 AWS Lambda 函数(超时)
AWS Lambda function using test trigger or schedule (Timeout)
所以我创建了一个 lambda 函数(其目的不再重要)并测试了它在 运行 从我的笔记本电脑上工作时是否有效。然而,更大的问题是我无法在测试事件中或在 AWS 中按计划完成 运行。
当我尝试从 AWS 运行 它时,出现 300 秒超时错误。
以下内容供您考虑:
- 函数
- 日志
- 触发事件
- 政策
- VPC相关配置
如果有人能告诉我可能是什么问题,我将不胜感激,因为我已经搜索了大约 3 天的解决方案。
功能:
from __future__ import print_function
def lambda_handler(event, context):
if event["account"] == "123456789012":
print("Passed!!")
return event['time']
import boto3
import datetime
def find_auto_scaling_instances():
"""
Find Auto-scaling Instances
"""
client=boto3.client("autoscaling")
auto_scaling=client.describe_auto_scaling_groups()
dict={}
for group in auto_scaling["AutoScalingGroups"]:
print("hello")
auto_scaling_group_name=group["AutoScalingGroupName"]
number_of_instances=len(group["Instances"])
if number_of_instances == 0:
continue
else:
for i in range(number_of_instances):
if group["Instances"][i]["LifecycleState"] == "InService":
instance_id=group["Instances"][i]["InstanceId"]
dict[auto_scaling_group_name]=instance_id
break
return dict
def find_staging_instances():
"""
Find Static Instances
"""
stg_list=[]
tag_list=["Y-qunie-stepsrv-1a","S-StepSvr"]
for i in range(num_of_instances):
print("hello2")
target=instances[i]["Instances"][0]
number_of_tags=len(target["Tags"])
for tag in range(number_of_tags):
if target["Tags"][tag]["Value"] in tag_list:
stg_list+=[target["InstanceId"]]
return stg_list
def volumes_per_instance():
"""
Find the EBS associated with the Instances
"""
instance_disk={}
for i in range(num_of_instances):
print("hello3")
target=instances[i]["Instances"][0]
if target["InstanceId"] in instance_list:
instance_disk[target["InstanceId"]]=[]
for disk in range(len(target["BlockDeviceMappings"])):
print("hello4")
instance_disk[target["InstanceId"]]+=\
target["BlockDeviceMappings"][disk]["Ebs"]["VolumeId"]]
return instance_disk
#Group instances together and prepare to process
instance_in_asgroup_dict=find_auto_scaling_instances()
as_instance_list=[]
for group in instance_in_asgroup_dict:
print("hello5")
as_instance_list+=[instance_in_asgroup_dict[group]]
client=boto3.client("ec2")
instances=client.describe_instances()["Reservations"]
num_of_instances=len(instances)
staging_instances=find_staging_instances()
instance_list=[]
instance_list+=as_instance_list
instance_list+=staging_instances
#Gather Disk Information
inst_disk_set=volumes_per_instance()
date=str(datetime.datetime.now()).replace(" \
","_").replace(":","").replace(".","")
#Create Disk Images
as_image={}
image=[]
for instance in instance_list:
print("hello6")
if instance in as_instance_list:
as_image[instance]=client.create_image(
InstanceId=instance,
Name=instance+"-"+date+"-AMI",
Description="AMI for instance "+instance+".",
NoReboot=True
)
else:
image+=[client.create_image(
InstanceId=instance,
Name=instance+"-"+date+"-AMI",
Description="AMI for instance "+instance+".",
NoReboot=True
)]
日志:
18:03:30
START RequestId: 0ca9e0a3-7f11-11e6-be11-6974d9213102 Version: $LATEST
18:08:30
END RequestId: 0ca9e0a3-7f11-11e6-be11-6974d9213102
18:08:30
REPORT RequestId: 0ca9e0a3-7f11-11e6-be11-6974d9213102 Duration: 300001.99 ms Billed Duration: 300000 ms Memory Size: 128 MB Max Memory Used: 24 MB
18:08:30
2016-09-20T09:08:30.544Z 0ca9e0a3-7f11-11e6-be11-6974d9213102 Task timed out after 300.00 seconds
TRIGGER_EVENT:
{
"account": "123456789012",
"region": "us-east-1",
"detail": {},
"detail-type": "Scheduled Event",
"source": "aws.events",
"time": "1970-01-01T00:00:00Z",
"id": "cdc73f9d-aea9-11e3-9d5a-835b769c0d9c",
"resources": [
"arn:aws:events:us-east-1:123456789012:rule/my-schedule"
]
}
EDIT-1
IAM 政策:
据我了解,允许 VPC 访问我的函数所需要做的就是将以下权限添加到 lambda 函数的分配策略中。
- ec2:创建网络接口
- ec2:删除网络接口
- ec2:DescribeNetworkInterfaces
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"ec2:CreateNetworkInterface",
"ec2:DescribeNetworkInterfaces",
"ec2:DeleteNetworkInterface"
],
"Resource": "*"
},
{
"Action": [
"ec2:DescribeInstances",
"ec2:CreateImage",
"autoscaling:DescribeAutoScalingGroups"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
}
] }
编辑 2
配置:
附加到函数的子网、安全组和 VPC。
编辑 3(结论)
Mark 给出了一个很好的答案,告诉我我已经在 VPC 中将我的函数设置为 运行 但我没有访问 VPC 中的资源。相反,我正在访问 Amazon API 端点,这要求我可以访问互联网,否则交易会超时。
因此,有两种方法可以解决这种情况。
- 删除我的 VPC 设置
- 在我的 VPC 中创建一个 NAT 网关
我选择了最便宜的那个。
您为 Lambda 函数启用了 VPC 访问。所以现在它只能访问您的 VPC 内的资源。请注意,AWS API 存在于您的 VPC 之外。任何访问 VPC 之外的内容的尝试都将导致网络超时。这就是您看到超时问题的原因。
要解决此问题,您可以将 Lambda 函数移到 VPC 之外,或者您可以将 NAT 网关添加到您的 VPC。我在您的代码中没有看到任何访问 VPC 内任何内容的内容,因此从 Lambda 函数中删除 VPC 设置可能是最便宜和最简单的方法。
所以我创建了一个 lambda 函数(其目的不再重要)并测试了它在 运行 从我的笔记本电脑上工作时是否有效。然而,更大的问题是我无法在测试事件中或在 AWS 中按计划完成 运行。
当我尝试从 AWS 运行 它时,出现 300 秒超时错误。
以下内容供您考虑:
- 函数
- 日志
- 触发事件
- 政策
- VPC相关配置
如果有人能告诉我可能是什么问题,我将不胜感激,因为我已经搜索了大约 3 天的解决方案。
功能:
from __future__ import print_function
def lambda_handler(event, context):
if event["account"] == "123456789012":
print("Passed!!")
return event['time']
import boto3
import datetime
def find_auto_scaling_instances():
"""
Find Auto-scaling Instances
"""
client=boto3.client("autoscaling")
auto_scaling=client.describe_auto_scaling_groups()
dict={}
for group in auto_scaling["AutoScalingGroups"]:
print("hello")
auto_scaling_group_name=group["AutoScalingGroupName"]
number_of_instances=len(group["Instances"])
if number_of_instances == 0:
continue
else:
for i in range(number_of_instances):
if group["Instances"][i]["LifecycleState"] == "InService":
instance_id=group["Instances"][i]["InstanceId"]
dict[auto_scaling_group_name]=instance_id
break
return dict
def find_staging_instances():
"""
Find Static Instances
"""
stg_list=[]
tag_list=["Y-qunie-stepsrv-1a","S-StepSvr"]
for i in range(num_of_instances):
print("hello2")
target=instances[i]["Instances"][0]
number_of_tags=len(target["Tags"])
for tag in range(number_of_tags):
if target["Tags"][tag]["Value"] in tag_list:
stg_list+=[target["InstanceId"]]
return stg_list
def volumes_per_instance():
"""
Find the EBS associated with the Instances
"""
instance_disk={}
for i in range(num_of_instances):
print("hello3")
target=instances[i]["Instances"][0]
if target["InstanceId"] in instance_list:
instance_disk[target["InstanceId"]]=[]
for disk in range(len(target["BlockDeviceMappings"])):
print("hello4")
instance_disk[target["InstanceId"]]+=\
target["BlockDeviceMappings"][disk]["Ebs"]["VolumeId"]]
return instance_disk
#Group instances together and prepare to process
instance_in_asgroup_dict=find_auto_scaling_instances()
as_instance_list=[]
for group in instance_in_asgroup_dict:
print("hello5")
as_instance_list+=[instance_in_asgroup_dict[group]]
client=boto3.client("ec2")
instances=client.describe_instances()["Reservations"]
num_of_instances=len(instances)
staging_instances=find_staging_instances()
instance_list=[]
instance_list+=as_instance_list
instance_list+=staging_instances
#Gather Disk Information
inst_disk_set=volumes_per_instance()
date=str(datetime.datetime.now()).replace(" \
","_").replace(":","").replace(".","")
#Create Disk Images
as_image={}
image=[]
for instance in instance_list:
print("hello6")
if instance in as_instance_list:
as_image[instance]=client.create_image(
InstanceId=instance,
Name=instance+"-"+date+"-AMI",
Description="AMI for instance "+instance+".",
NoReboot=True
)
else:
image+=[client.create_image(
InstanceId=instance,
Name=instance+"-"+date+"-AMI",
Description="AMI for instance "+instance+".",
NoReboot=True
)]
日志:
18:03:30
START RequestId: 0ca9e0a3-7f11-11e6-be11-6974d9213102 Version: $LATEST
18:08:30
END RequestId: 0ca9e0a3-7f11-11e6-be11-6974d9213102
18:08:30
REPORT RequestId: 0ca9e0a3-7f11-11e6-be11-6974d9213102 Duration: 300001.99 ms Billed Duration: 300000 ms Memory Size: 128 MB Max Memory Used: 24 MB
18:08:30
2016-09-20T09:08:30.544Z 0ca9e0a3-7f11-11e6-be11-6974d9213102 Task timed out after 300.00 seconds
TRIGGER_EVENT:
{
"account": "123456789012",
"region": "us-east-1",
"detail": {},
"detail-type": "Scheduled Event",
"source": "aws.events",
"time": "1970-01-01T00:00:00Z",
"id": "cdc73f9d-aea9-11e3-9d5a-835b769c0d9c",
"resources": [
"arn:aws:events:us-east-1:123456789012:rule/my-schedule"
]
}
EDIT-1
IAM 政策:
据我了解,允许 VPC 访问我的函数所需要做的就是将以下权限添加到 lambda 函数的分配策略中。
- ec2:创建网络接口
- ec2:删除网络接口
- ec2:DescribeNetworkInterfaces
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents", "ec2:CreateNetworkInterface", "ec2:DescribeNetworkInterfaces", "ec2:DeleteNetworkInterface" ], "Resource": "*" }, { "Action": [ "ec2:DescribeInstances", "ec2:CreateImage", "autoscaling:DescribeAutoScalingGroups" ], "Effect": "Allow", "Resource": "*" }, { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:*" } ] }
编辑 2
配置:
附加到函数的子网、安全组和 VPC。
编辑 3(结论)
Mark 给出了一个很好的答案,告诉我我已经在 VPC 中将我的函数设置为 运行 但我没有访问 VPC 中的资源。相反,我正在访问 Amazon API 端点,这要求我可以访问互联网,否则交易会超时。
因此,有两种方法可以解决这种情况。
- 删除我的 VPC 设置
- 在我的 VPC 中创建一个 NAT 网关
我选择了最便宜的那个。
您为 Lambda 函数启用了 VPC 访问。所以现在它只能访问您的 VPC 内的资源。请注意,AWS API 存在于您的 VPC 之外。任何访问 VPC 之外的内容的尝试都将导致网络超时。这就是您看到超时问题的原因。
要解决此问题,您可以将 Lambda 函数移到 VPC 之外,或者您可以将 NAT 网关添加到您的 VPC。我在您的代码中没有看到任何访问 VPC 内任何内容的内容,因此从 Lambda 函数中删除 VPC 设置可能是最便宜和最简单的方法。