Доступность спотовых инстансов AWS EC2
Я использую вызов API
request_spot_instances
для создания спотового экземпляра без указания зоны доступности. Обычно API выбирает случайную зону доступности. Спотовый запрос иногда возвращал статус отсутствия емкости, тогда как я мог успешно запросить спотовый инстанс через консоль AWS в другой зоне доступности. Как правильно проверить доступность спотового экземпляра определенного типа перед вызовом request_spot_instance?
2 ответа
Общедоступного API для проверки доступности спотовых инстансов нет. Сказав это, вы все равно можете достичь желаемого, выполнив следующие шаги:
- Вместо этого используйте request_spot_fleet и настройте его для запуска одного экземпляра.
- Будьте гибкими с типами экземпляров, которые вы используете, выберите как можно больше и включите их в запрос. Чтобы помочь вам выбрать экземпляры, проверьте советник по спотовым инстансам, чтобы узнать о показателях прерывания и экономии экземпляров.
- По запросу Spot Fleet настройте
AllocationStrategy
кcapacityOptimized
это позволит флоту выделить мощность из наиболее доступного спотового инстанса из вашего списка инстансов и снизить вероятность прерывания работы спотового сервера. - Не устанавливайте максимальную цену
SpotPrice
, будет использоваться цена спотового инстанса по умолчанию. Модель ценообразования для Spot изменилась, и она больше не основана на торгах, поэтому цены Spot более стабильны и не колеблются.
Это может быть немного излишним для того, что вы ищете, но с помощью частей кода вы можете найти историю спотовых цен за последний час (это можно изменить). Это даст вам тип экземпляра, AZ и дополнительную информацию. Оттуда вы можете прокрутить тип экземпляра до AZ. Если спотовый экземпляр не появится, скажем, через 30 секунд, попробуйте следующую зону доступности.
И, по мнению Ахмеда в его ответе, эта информация может быть использована в запросе spot_fleet_request вместо того, чтобы перебирать AZ. Если вы передадите неправильную зону доступности или подсеть в запросе спотовой группы, вызов 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')