Last active
August 24, 2018 18:46
-
-
Save peterhurford/a80e6b2b156c19ce9985c05af5275aa7 to your computer and use it in GitHub Desktop.
Find the best deals in AWS spot instances across all availability zones and multiple instance types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# For every AWS availability zone and instance I care about, check the spot | |
# price for the last ninety days and generate stats about which spot instance | |
# gives the best deal. | |
import boto | |
import boto.ec2 | |
from vowpal_platypus.utils import mean | |
REGIONS = {'us-east-1': ['us-east-1a', 'us-east-1b', 'us-east-1c', 'us-east-1e'], | |
'us-west-1': ['us-west-1a', 'us-west-1b'], | |
'us-west-2': ['us-west-2a', 'us-west-2b', 'us-west-2c']} | |
INSTANCES = {'m4.10xlarge': {'cpu': 40, 'ram': 160, 'odprice': 2}, | |
'm4.16xlarge': {'cpu': 64, 'ram': 256, 'odprice': 3.2}, | |
'c4.4xlarge': {'cpu': 16, 'ram': 30, 'odprice': 0.796}, | |
'c4.8xlarge': {'cpu': 36, 'ram': 60, 'odprice': 1.591}, | |
'x1.16xlarge': {'cpu': 64, 'ram': 976, 'odprice': 6.669}, | |
'x1.32xlarge': {'cpu': 128, 'ram': 1952, 'odprice': 13.338}, | |
'r4.4xlarge': {'cpu': 16, 'ram': 122, 'odprice': 1.064}, | |
'r4.8xlarge': {'cpu': 32, 'ram': 244, 'odprice': 2.128}, | |
'r4.16xlarge': {'cpu': 64, 'ram': 488, 'odprice': 4.256}} | |
def find_best(data, label, fn): | |
return fn(map(lambda y: (y[0], y[1][0], y[1][1][label]), | |
map(lambda x: (x[0], fn(x[1].items(), key=lambda x: x[1][label])), | |
data.items())), key=lambda z: z[2]) | |
data = {} | |
for region, zones in REGIONS.iteritems(): | |
print('REGION: ' + str(region)) | |
ec2 = boto.ec2.connect_to_region(region) | |
for zone in zones: | |
print('...ZONE: ' + str(zone)) | |
data[zone] = {} | |
for instance, instance_data in INSTANCES.iteritems(): | |
print('... ...Instance: ' + str(instance)) | |
prices = ec2.get_spot_price_history(start_time='2017-03-01T22:54:13', | |
end_time='2017-06-01T22:53:09', | |
instance_type=instance, | |
availability_zone=zone) | |
if len(prices) > 0: | |
spot_price = mean(map(lambda x: x.price, prices)) | |
odprice = instance_data['odprice'] | |
data[zone][instance] = {'odprice': odprice, | |
'spot_price': spot_price, | |
'diff': odprice - spot_price, | |
'discount': 1 - spot_price / float(odprice), | |
'odprice_per_core': odprice / float(instance_data['cpu']), | |
'odprice_per_ram': odprice / float(instance_data['ram']), | |
'spot_price_per_core': spot_price / float(instance_data['cpu']), | |
'spot_price_per_ram': spot_price / float(instance_data['ram'])} | |
data[zone][instance]['od_spot_per_core_diff'] = data[zone][instance]['odprice_per_core'] - data[zone][instance]['spot_price_per_core'] | |
data[zone][instance]['od_spot_per_core_discount'] = 1 - data[zone][instance]['spot_price_per_core'] / float(data[zone][instance]['odprice_per_core']) | |
data[zone][instance]['od_spot_per_ram_diff'] = data[zone][instance]['odprice_per_ram'] - data[zone][instance]['spot_price_per_ram'] | |
data[zone][instance]['od_spot_per_ram_discount'] = 1 - data[zone][instance]['spot_price_per_ram'] / float(data[zone][instance]['odprice_per_ram']) | |
for instance, instance_data in INSTANCES.iteritems(): | |
print((instance, instance_data['odprice'], mean(filter(lambda y: y is not None, map(lambda x: x[1][instance].get('spot_price') if x[1].get(instance) else None, data.items()))))) | |
for instance, instance_data in INSTANCES.iteritems(): | |
print((instance, mean(filter(lambda y: y is not None, map(lambda x: x[1][instance].get('spot_price_per_core') if x[1].get(instance) else None, data.items()))))) | |
for instance, instance_data in INSTANCES.iteritems(): | |
print((instance, mean(filter(lambda y: y is not None, map(lambda x: x[1][instance].get('spot_price_per_ram') if x[1].get(instance) else None, data.items()))))) | |
print('LOWEST SPOT PRICE') | |
print(find_best(data, 'spot_price', fn=min)) | |
print('LARGEST OD-SPOT PRICE DISCOUNT') | |
print(find_best(data, 'discount', fn=max)) | |
print('BEST OD PRICE PER CORE') | |
print(find_best(data, 'odprice_per_core', fn=min)) | |
print('BEST SPOT PRICE PER CORE') | |
print(find_best(data, 'spot_price_per_core', fn=min)) | |
print('BEST OD-SPOT PRICE DISCOUNT PER CORE') | |
print(find_best(data, 'od_spot_per_core_discount', fn=max)) | |
print('BEST OD PRICE PER RAM') | |
print(find_best(data, 'odprice_per_ram', fn=min)) | |
print('BEST SPOT PRICE PER RAM') | |
print(find_best(data, 'spot_price_per_ram', fn=min)) | |
print('BEST OD-SPOT PRICE DISCOUNT PER RAM') | |
print(find_best(data, 'od_spot_per_ram_discount', fn=max)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment