亚马逊网络服务定价是否有任何API可用?

48

有没有任何API可以提供亚马逊网络服务的最新定价信息?例如,可以查询给定区域的S3或EC2最新价格等。

谢谢


2
https://dev59.com/22s05IYBdhLWcg3wR_63 - auselen
AWS现在有一个价格列表API了 https://aws.amazon.com/blogs/aws/new-aws-price-list-api/ - Joshua Robinson
使用CLI...示例: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
12个回答

38

更新:

现在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,因此我不建议期望数据格式的稳定性甚至源头的持续存在。但是它确实存在,并且比将定价数据转录到静态配置/源文件中要好得多!


1
值得注意的是,从API读取现货价格历史记录时需要注意一个警告 - 它只会显示您开始和结束时间之间的更改。某些实例类型在某些可用性区域中不受支持(检测这一点相当困难,因为如果您要求过去24小时的现货价格数据,则未更改的价格看起来像该地区不支持的实例类型(或反之亦然)。 - Peter
4
请注意,截至2014年4月,这些URL已被弃用并且价格信息已过时。它们现在位于http://a0.awsstatic.com/pricing/1/ec2/linux-od.min.js和 http://a0.awsstatic.com/pricing/1/s3/pricing-storage-s3.min.js。如果您查看任何定价页面的源代码并搜索“json”,您将找到相应的链接。 - Tim Dorr
@TimDorr,如果上面的内容已经过时了,你能否编辑帖子或者发布你的答案? - CMCDragonkai
AWS现在有一个价格列表API了 https://aws.amazon.com/blogs/aws/new-aws-price-list-api/ - Joshua Robinson

14

对于想要使用亚马逊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'
}

8
我已经用Python快速而简单地创建了一个API,用于访问JSON文件中的定价数据,并将其转换为相关值(正确的翻译和正确的实例类型)。
您可以在此处获取代码:https://github.com/erans/ec2instancespricing 并在此处阅读更多信息:http://forecastcloudy.net/2012/04/03/quick-dirty-api-for-accessing-amazon-web-services-aws-ec2-pricing-data/ 您可以将此文件用作模块并调用函数以获得带有结果的Python字典,或者您可以将其用作命令行工具,以获得人类可读的表格、JSON或CSV输出,以与其他命令行工具结合使用。

非常好,但我注意到它不包括先前的实例,比如t1.micro - 是否有另一个.js文件包含这些价格? - Trevor North

4
以下链接提供了一个非常好用的API,你可以使用它来查询AWS的定价信息。 http://info.awsstream.com 如果你对筛选器进行一些试验,就可以看到如何构建查询以返回你需要的特定信息,例如区域、实例类型等。例如,要返回包含eu-west-1地区Linux实例的EC2定价的json,可以按照以下格式编写查询。 http://info.awsstream.com/instances.json?region=eu-west-1&os=linux 只需将上面的查询中的json替换为xml即可返回以xml格式呈现的信息。
注意 - 与其他贡献者发布的URL类似,我认为这不是官方认可的AWS API。然而,根据我在过去几天进行的一些抽样检查,我可以确认在发布时定价信息似乎是正确的。

1

对于那些需要全面的AWS实例定价数据(EC2、RDS、ElastiCache和Redshift)的人,这里是一个Python模块,它是从Eran Sandler建议的模块发展而来的:

https://github.com/ilia-semenov/awspricingfull

它包含了上一代实例和当前的实例(包括最新的d2系列),提供预留和按需定价。可用的格式有JSON、表格和CSV。

1

我没有找到有关基本定价的任何信息,但是Deltacloud是一个非常有趣的跨云信息和管理项目http://deltacloud.org/。 - edla
我也没有看到一个通用的定价API。最接近的是brokenbeatnik所描述的现货价格历史记录。 - David J.

1

我也需要一个API来获取AWS的定价。惊讶的是,尽管AWS资源有大量的API可用,但并没有找到什么。

我的首选语言是Ruby,所以我编写了一个名为AWSCosts的Gem,提供对AWS定价的程序化访问。

以下是查找m1.medium Linux实例按需价格的示例。

AWSCosts.region('us-east-1').ec2.on_demand(:linux).price('m1.medium')


0

另一个快速而简单的方法,但是将其转换为更方便的最终数据格式

 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

0

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接