有没有任何API可以提供亚马逊网络服务的最新定价信息?例如,可以查询给定区域的S3或EC2最新价格等。
谢谢
有没有任何API可以提供亚马逊网络服务的最新定价信息?例如,可以查询给定区域的S3或EC2最新价格等。
谢谢
更新:
现在AWS有定价API了:https://aws.amazon.com/blogs/aws/new-aws-price-list-api/
原回答:
之前我曾经通过AWS的传教士和调查要求过这个功能,但是一直没有出现。我猜AWS的人们对未来有更有趣的创新。
正如@brokenbeatnik所指出的那样,有一个用于竞价历史记录的API。API文档在这里:http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSpotPriceHistory.html
我觉得很奇怪的是,竞价历史价格有一个官方的API,但他们没有同时为按需服务做这件事。无论如何,回答问题,您可以查询广告中的AWS价格......
我能想到的最好方法是检查各种服务定价页面的(客户端)源代码。在其中,您会发现表格是使用JS构建并填充JSON数据的,您可以获取这些数据。例如:
但这只是解决了一半的问题,接下来您必须分析对象格式以获取所需的值,例如,在Python中,这会获取弗吉尼亚州Hi-CPU按需额外大型Linux实例的定价:
>>> import json
>>> import urllib2
>>> response = urllib2.urlopen('http://aws.amazon.com/ec2/pricing/pricing-on-demand-instances.json')
>>> pricejson = response.read()
>>> pricing = json.loads(pricejson)
>>> pricing['config']['regions'][0]['instanceTypes'][3]['sizes'][1]['valueColumns'][0]['prices']['USD']
u'0.68'
免责声明:显然这不是AWS官方的API,因此我不建议期望数据格式的稳定性甚至源头的持续存在。但是它确实存在,并且比将定价数据转录到静态配置/源文件中要好得多!
对于想要使用亚马逊API数据的人,其中使用了像“t1.micro”这样的内容,这里提供一个翻译数组。
type_translation = {
'm1.small' : ['stdODI', 'sm'],
'm1.medium' : ['stdODI', 'med'],
'm1.large' : ['stdODI', 'lg'],
'm1.xlarge' : ['stdODI', 'xl'],
't1.micro' : ['uODI', 'u'],
'm2.xlarge' : ['hiMemODI', 'xl'],
'm2.2xlarge' : ['hiMemODI', 'xxl'],
'm2.4xlarge' : ['hiMemODI', 'xxxxl'],
'c1.medium' : ['hiCPUODI', 'med'],
'c1.xlarge' : ['hiCPUODI', 'xl'],
'cc1.4xlarge' : ['clusterComputeI', 'xxxxl'],
'cc2.8xlarge' : ['clusterComputeI', 'xxxxxxxxl'],
'cg1.4xlarge' : ['clusterGPUI', 'xxxxl'],
'hi1.4xlarge' : ['hiIoODI', 'xxxx1']
}
region_translation = {
'us-east-1' : 'us-east',
'us-west-2' : 'us-west-2',
'us-west-1' : 'us-west',
'eu-west-1' : 'eu-ireland',
'ap-southeast-1' : 'apac-sin',
'ap-northeast-1' : 'apac-tokyo',
'sa-east-1' : 'sa-east-1'
}
对于那些需要全面的AWS实例定价数据(EC2、RDS、ElastiCache和Redshift)的人,这里是一个Python模块,它是从Eran Sandler建议的模块发展而来的:
它包含了上一代实例和当前的实例(包括最新的d2系列),提供预留和按需定价。可用的格式有JSON、表格和CSV。我不相信有一个API可以涵盖标准服务的一般当前价格。然而,特别是对于EC2,您可以查看现货价格历史记录,以便您不必猜测现货实例的市场价格。更多信息请参见:
http://docs.amazonwebservices.com/AWSEC2/latest/DeveloperGuide/using-spot-instances-history.html
我也需要一个API来获取AWS的定价。惊讶的是,尽管AWS资源有大量的API可用,但并没有找到什么。
我的首选语言是Ruby,所以我编写了一个名为AWSCosts的Gem,提供对AWS定价的程序化访问。
以下是查找m1.medium Linux实例按需价格的示例。
AWSCosts.region('us-east-1').ec2.on_demand(:linux).price('m1.medium')
另一个快速而简单的方法,但是将其转换为更方便的最终数据格式
class CostsAmazon(object):
'''Class for general info on the Amazon EC2 compute cloud.
'''
def __init__(self):
'''Fetch a bunch of instance cost data from Amazon and convert it
into the following form (as self.table):
table['us-east']['linux']['m1']['small']['light']['ondemand']['USD']
'''
#
# tables_raw['ondemand']['config']['regions'
# ][0]['instanceTypes'][0]['sizes'][0]['valueColumns'][0
# ]['prices']['USD']
#
# structure of tables_raw:
# ┃
# ┗━━[key]
# ┣━━['use'] # an input 3 x ∈ { 'light', 'medium', ... }
# ┣━━['os'] # an input 2 x ∈ { 'linux', 'mswin' }
# ┣━━['scheduling'] # an input
# ┣━━['uri'] # an input (see dict above)
# ┃ # the core output from Amazon follows
# ┣━━['vers'] == 0.01
# ┗━━['config']:
# * ┣━━['regions']: 7 x
# ┃ ┣━━['region'] == ∈ { 'us-east', ... }
# * ┃ ┗━━['instanceTypes']: 7 x
# ┃ ┣━━['type']: 'stdODI'
# * ┃ ┗━━['sizes']: 4 x
# ┃ ┗━━['valueColumns']
# ┃ ┣━━['size']: 'sm'
# * ┃ ┗━━['valueColumns']: 2 x
# ┃ ┣━━['name']: ~ 'linux'
# ┃ ┗━━['prices']
# ┃ ┗━━['USD']: ~ '0.080'
# ┣━━['rate']: ~ 'perhr'
# ┣━━['currencies']: ∈ { 'USD', ... }
# ┗━━['valueColumns']: [ 'linux', 'mswin' ]
#
# The valueColumns thing is weird, it looks like they're trying
# to constrain actual data to leaf nodes only, which is a little
# bit of a conceit since they have lists in several levels. So
# we can obtain the *much* more readable:
#
# tables['regions']['us-east']['m1']['linux']['ondemand'
# ]['small']['light']['USD']
#
# structure of the reworked tables:
# ┃
# ┗━━[<region>]: 7 x ∈ { 'us-east', ... }
# ┗━━[<os>]: 2 x ∈ { 'linux', 'mswin' } # oses
# ┗━━[<type>]: 7 x ∈ { 'm1', ... }
# ┗━━[<scheduling>]: 2 x ∈ { 'ondemand', 'reserved' }
# ┗━━[<size>]: 4 x ∈ { 'small', ... }
# ┗━━[<use>]: 3 x ∈ { 'light', 'medium', ... }
# ┗━━[<currency>]: ∈ { 'USD', ... }
# ┗━━> ~ '0.080' or None
uri_base = 'http://aws.amazon.com/ec2/pricing'
tables_raw = {
'ondemand': {'scheduling': 'ondemand',
'uri': '/pricing-on-demand-instances.json',
'os': 'linux', 'use': 'light'},
'reserved-light-linux': {
'scheduling': 'ondemand',
'uri': 'ri-light-linux.json', 'os': 'linux', 'use': 'light'},
'reserved-light-mswin': {
'scheduling': 'ondemand',
'uri': 'ri-light-mswin.json', 'os': 'mswin', 'use': 'light'},
'reserved-medium-linux': {
'scheduling': 'ondemand',
'uri': 'ri-medium-linux.json', 'os': 'linux', 'use': 'medium'},
'reserved-medium-mswin': {
'scheduling': 'ondemand',
'uri': 'ri-medium-mswin.json', 'os': 'mswin', 'use': 'medium'},
'reserved-heavy-linux': {
'scheduling': 'ondemand',
'uri': 'ri-heavy-linux.json', 'os': 'linux', 'use': 'heavy'},
'reserved-heavy-mswin': {
'scheduling': 'ondemand',
'uri': 'ri-heavy-mswin.json', 'os': 'mswin', 'use': 'heavy'},
}
for key in tables_raw:
# expand to full URIs
tables_raw[key]['uri'] = (
'%s/%s'% (uri_base, tables_raw[key]['uri']))
# fetch the data from Amazon
link = urllib2.urlopen(tables_raw[key]['uri'])
# adds keys: 'vers' 'config'
tables_raw[key].update(json.loads(link.read()))
link.close()
# canonicalize the types - the default is pretty annoying.
#
self.currencies = set()
self.regions = set()
self.types = set()
self.intervals = set()
self.oses = set()
self.sizes = set()
self.schedulings = set()
self.uses = set()
self.footnotes = {}
self.typesizes = {} # self.typesizes['m1.small'] = [<region>...]
self.table = {}
# grovel through Amazon's tables_raw and convert to something orderly:
for key in tables_raw:
scheduling = tables_raw[key]['scheduling']
self.schedulings.update([scheduling])
use = tables_raw[key]['use']
self.uses.update([use])
os = tables_raw[key]['os']
self.oses.update([os])
config_data = tables_raw[key]['config']
self.currencies.update(config_data['currencies'])
for region_data in config_data['regions']:
region = self.instance_region_from_raw(region_data['region'])
self.regions.update([region])
if 'footnotes' in region_data:
self.footnotes[region] = region_data['footnotes']
for instance_type_data in region_data['instanceTypes']:
instance_type = self.instance_types_from_raw(
instance_type_data['type'])
self.types.update([instance_type])
for size_data in instance_type_data['sizes']:
size = self.instance_size_from_raw(size_data['size'])
typesize = '%s.%s' % (instance_type, size)
if typesize not in self.typesizes:
self.typesizes[typesize] = set()
self.typesizes[typesize].update([region])
self.sizes.update([size])
for size_values in size_data['valueColumns']:
interval = size_values['name']
self.intervals.update([interval])
for currency in size_values['prices']:
cost = size_values['prices'][currency]
self.table_add_row(region, os, instance_type,
size, use, scheduling,
currency, cost)
def table_add_row(self, region, os, instance_type, size, use, scheduling,
currency, cost):
if cost == 'N/A*':
return
table = self.table
for key in [region, os, instance_type, size, use, scheduling]:
if key not in table:
table[key] = {}
table = table[key]
table[currency] = cost
def instance_region_from_raw(self, raw_region):
'''Return a less intelligent given EC2 pricing name to the
corresponding region name.
'''
regions = {
'apac-tokyo' : 'ap-northeast-1',
'apac-sin' : 'ap-southeast-1',
'eu-ireland' : 'eu-west-1',
'sa-east-1' : 'sa-east-1',
'us-east' : 'us-east-1',
'us-west' : 'us-west-1',
'us-west-2' : 'us-west-2',
}
return regions[raw_region] if raw_region in regions else raw_region
def instance_types_from_raw(self, raw_type):
types = {
# ondemand reserved
'stdODI' : 'm1', 'stdResI' : 'm1',
'uODI' : 't1', 'uResI' : 't1',
'hiMemODI' : 'm2', 'hiMemResI' : 'm2',
'hiCPUODI' : 'c1', 'hiCPUResI' : 'c1',
'clusterComputeI' : 'cc1', 'clusterCompResI' : 'cc1',
'clusterGPUI' : 'cc2', 'clusterGPUResI' : 'cc2',
'hiIoODI' : 'hi1', 'hiIoResI' : 'hi1'
}
return types[raw_type]
def instance_size_from_raw(self, raw_size):
sizes = {
'u' : 'micro',
'sm' : 'small',
'med' : 'medium',
'lg' : 'large',
'xl' : 'xlarge',
'xxl' : '2xlarge',
'xxxxl' : '4xlarge',
'xxxxxxxxl' : '8xlarge'
}
return sizes[raw_size]
def cost(self, region, os, instance_type, size, use, scheduling,
currency):
try:
return self.table[region][os][instance_type][
size][use][scheduling][currency]
except KeyError as ex:
return None
这是另一个未经认可的“api”,涵盖了保留实例:http://aws.amazon.com/ec2/pricing/pricing-reserved-instances.json
目前没有定价API,但是上面提到的价格非常不错。 除了EC2价格分析器之外,我还想分享我的RDS和ElastiCache价格分析器:
https://github.com/evgeny-gridasov/rdsinstancespricing https://github.com/evgeny-gridasov/elasticachepricing
aws ec2 describe-spot-price-history --instance-types m1.xlarge --product-description "Linux/UNIX (Amazon VPC)" --start-time 2016-10-31T03:00:00 --end-time 2016-10-31T03:16:00 --query 'SpotPriceHistory[*].[Timestamp,SpotPrice]'
请参阅文档。 - Alexander McFarlane