我正在使用 API 调用request_spot_instances
来创建 Spot 实例而不指定任何可用区。通常,API 会选择一个随机 AZ。Spot 请求有时会返回无容量状态,而我可以通过另一个 AZ 中的 AWS 控制台成功请求 Spot 实例。在调用 request_spot_instance 之前检查特定实例类型的现场实例的可用性的正确方法是什么?
问问题
2538 次
2 回答
4
没有用于检查 Spot 实例可用性的公共 API。话虽如此,您仍然可以按照以下步骤实现您想要的:
- 请改用request_spot_fleet,并将其配置为启动单个实例。
- 灵活使用您使用的实例类型,尽可能多地选择并将它们包含在请求中。为了帮助您选择实例,请查看Spot Instance advisor以了解实例中断和节省率。
- 根据 Spot 队列请求,配置此选项
AllocationStrategy
将允许队列从实例列表中最可用capacityOptimized
的 Spot 实例分配容量,并降低 Spot 中断的可能性。 - 不要设置最高价格
SpotPrice
,将使用默认的 Spot 实例价格。Spot 的定价模式发生了变化,不再基于竞价,因此 Spot 价格更加稳定,不会波动。
于 2020-10-20T06:00:29.690 回答
1
这对于您要查找的内容可能有点矫枉过正,但通过部分代码,您可以找到过去一小时的现货价格历史记录(可以更改)。它会为您提供实例类型、可用区和其他信息。从那里您可以循环访问实例类型到 AZ。如果在 30 秒内没有出现 Spot 实例,请尝试下一个 AZ。
对于 Ahmed 在他的回答中的观点,这些信息可以在 spot_fleet_request 中使用,而不是在 AZ 中循环。如果你在 Spot Fleet 请求中传递了错误的 AZ 或子网,它可能会通过 dryrun api 调用,但仍然会导致实际调用失败。如果您使用的是 dryrun 参数,请注意这一点。
以下是以下代码的输出:
In [740]: df_spot_instance_options
Out[740]:
AvailabilityZone InstanceType SpotPrice MemSize vCPUs CurrentGeneration Processor
0 us-east-1d t3.nano 0.002 512 2 True [x86_64]
1 us-east-1b t3.nano 0.002 512 2 True [x86_64]
2 us-east-1a t3.nano 0.002 512 2 True [x86_64]
3 us-east-1c t3.nano 0.002 512 2 True [x86_64]
4 us-east-1d t3a.nano 0.002 512 2 True [x86_64]
.. ... ... ... ... ... ... ...
995 us-east-1a p2.16xlarge 4.320 749568 64 True [x86_64]
996 us-east-1b p2.16xlarge 4.320 749568 64 True [x86_64]
997 us-east-1c p2.16xlarge 4.320 749568 64 True [x86_64]
998 us-east-1d p2.16xlarge 14.400 749568 64 True [x86_64]
999 us-east-1c p3dn.24xlarge 9.540 786432 96 True [x86_64]
[1000 rows x 7 columns]
这是代码:
ec2c = boto3.client('ec2')
ec2r = boto3.resource('ec2')
#### The rest of this code maps the instance details to spot price in case you are looking for certain memory or cpu
paginator = ec2c.get_paginator('describe_instance_types')
response_iterator = paginator.paginate( )
df_hold_list = []
for page in response_iterator:
df_hold_list.append(pd.DataFrame(page['InstanceTypes']))
df_instance_specs = pd.concat(df_hold_list, axis=0).reset_index(drop=True)
df_instance_specs['Spot'] = df_instance_specs['SupportedUsageClasses'].apply(lambda x: 1 if 'spot' in x else 0)
df_instance_spot_specs = df_instance_specs.loc[df_instance_specs['Spot']==1].reset_index(drop=True)
#unapck memory and cpu dictionaries
df_instance_spot_specs['MemSize'] = df_instance_spot_specs['MemoryInfo'].apply(lambda x: x.get('SizeInMiB'))
df_instance_spot_specs['vCPUs'] = df_instance_spot_specs['VCpuInfo'].apply(lambda x: x.get('DefaultVCpus'))
df_instance_spot_specs['Processor'] = df_instance_spot_specs['ProcessorInfo'].apply(lambda x: x.get('SupportedArchitectures'))
#look at instances only between 30MB and 70MB
instance_list = df_instance_spot_specs['InstanceType'].unique().tolist()
#---------------------------------------------------------------------------------------------------------------------
# You can use this section by itself to get the instancce type and availability zone and loop through the instance you want
# just modify instance_list with one instance you want informatin for
#look only in us-east-1
client = boto3.client('ec2', region_name='us-east-1')
prices = client.describe_spot_price_history(
InstanceTypes=instance_list,
ProductDescriptions=['Linux/UNIX', 'Linux/UNIX (Amazon VPC)'],
StartTime=(datetime.now() -
timedelta(hours=1)).isoformat(),
# AvailabilityZone='us-east-1a'
MaxResults=1000)
df_spot_prices = pd.DataFrame(prices['SpotPriceHistory'])
df_spot_prices['SpotPrice'] = df_spot_prices['SpotPrice'].astype('float')
df_spot_prices.sort_values('SpotPrice', inplace=True)
#---------------------------------------------------------------------------------------------------------------------
# merge memory size and cpu information into this dataframe
df_spot_instance_options = df_spot_prices[['AvailabilityZone', 'InstanceType', 'SpotPrice']].merge(df_instance_spot_specs[['InstanceType', 'MemSize', 'vCPUs',
'CurrentGeneration', 'Processor']], left_on='InstanceType', right_on='InstanceType')
于 2020-12-06T17:12:21.713 回答