亚马逊AWS官方博客
浅谈如何使用 Amazon CUR 报告做更完善的成本分析
![]() |
最近几年,随着云的使用越来越普遍,大部分公司的业务都已经在云上运行。从一开始的了解云,到正式迁移上云,再到现在新旧工作负载能在云上的都在云上,大家的关注重点也在发生变化。在大部分负载都运行在云上之后,我们会开始审视整个云的使用情况,希望能够降本增效,避免浪费。
为了让客户深入了解自己的详细资源用量,亚马逊云科技提供了详尽的账单,事无巨细地记录了所有资源使用和对应的费用,以及相关的参数。虽则详细,但是对于很多新手客户来说,动辄几百列的账单还是让人望而却步。
这就是这篇博客的写作初衷。我们希望用一个详细的案例来解读亚马逊云科技的 CUR(Cost and Usage Report,成本及用量报告)报告,并且分享一些 CUR 可视化的思路。希望通过这篇博客,更多的客户可以更深入的了解自己的云用量,监控自己的云用量变化,知道自己的每分钱是否花在了正确的位置,也知道出现意外成本时如何来做梳理和优化。
CUR 报告
要想看云用量账单,我们可以打开控制台,在「账单」服务界面下,点击菜单上的「账单」就能看到按服务拆分的账单。这个账单虽然详细,但它是一个统计结果,我们现在需要的是一条条的用量数据,比如在 2024 年 1 月 1 日 00:00 至 2024 年 1 月 1 日 01:00 之间产生了 3000 秒的 m6g.xlarge 的 EC2 用量。
要看到这个信息,我们就需要开启 CUR 报告。
仍然在「账单」服务界面下,点击「Cost & usage reports」(海外则打开「Data Exports」),就可以打开 CUR 报告导出界面。需要注意的是,CUR 报告默认是不打开的,并且也无法追溯以往的记录,只有用户手动打开之后,详细的用量数据才会被导出到指定的 Amazon S3 桶。
注:因本文写作之时尚未推出新的「Standard CUR export」,所以本文基于「Legacy CUR export」来撰写。
在开启 CUR 报告时,我们需要注意勾选「资源 ID」和「拆分成本分配数据」。「自动刷新」也需要打开,因为亚马逊云科技账单有两个状态,一个是未结算状态(Unfinalized),一个是已结算状态(Finalized),在正式结算之前,可能会发生退款等费用变化,所以我们需要打开自动刷新,在账单发生变化时,让账单服务帮我们自动更新 CUR 报告的文件。
然后我们需要选择一个 S3 桶,因为报告会以大数据常见的 Parquet 文件的格式存储到 S3 桶,方便我们查询。时间粒度我们选择「每小时」,则用量数据会按小时来进行汇总。是的,CUR 仍然有一定程度的汇总,但是粒度已经足够小,足够我们做分析。
本次我们使用 Amazon Athena 来做数据分析接口,所以数据集成我们选择「Amazon Athena」即可。这个核心作用是会生成一个帮助我们建表的 SQL 文件,在 Athena 中运行后,我们就能直接用 SQL 对 CUR 进行分析。
创建完成后,稍等几小时,我们就能在 S3 桶中看到 CUR 文件和 SQL 文件了。
成本标签
在做任何成本分析之前,我们都应该先做好成本标签。给资源附上成本标签,我们就能知道谁,哪个部分,哪个业务或哪个项目使用了这个资源。
在创建资源的时候,通常都会有标签输入选项,我们可以直接输入标签。标签以 Key-Value 的形式存在,用户可以自行定义键值对,比如 K = department / V = marketing,或者 K = project / V = miniapp 等等。
有了标签,我们还必须激活它们,才能在 CUR 里面体现。在「账单」服务界面下,点击菜单上的「成本分配标签」,就能看到现在使用的标签。选择需要激活的标签,点击「激活」按钮即可激活。
在 Athena 中建表
接下来,我们就可以同种找到使用 CUR 提供给我们的 SQL,在 Athena 中建表。可以看到这个 SQL 已经包含了所有 CUR 的字段,以及用户的标签字段,且 S3 存储位置也帮我们写好了,直接运行即可。
创建好表之后,分区信息还没有,所以我们需要做恢复分区的操作。后续我们也需要周期性执行这个命令,才能纳入新的数据。命令是:
账单预处理
因为 CUR 账单本身比较原始,所以我们还需要对账单进行预处理,才能更方便地进行处理。这里提一些整理思路,仅作抛砖引玉。
未正式出具的账单
CUR 账单中有一个字段 bill_invoice_id,这个指的是账单发票 ID,而更实际的意义,是代表这个账单是否已经正式出具,等待客户付款。在账单正式出具之前,有很多原因可能导致账单项的增减,比如算错费用,费用补助,费用修正等等。
如果这个字段为空,则账单还没正式出具,还可能有变化,在分析的时候需要注意。
账单项的 ID
CUR 账单中有一个 identity_line_item_id 字段,可能你会觉得这个就代表这个账单项的 ID 了,想用它来去拼接数据,这就掉入了陷阱。账单是按照时间段来生成的,而这个字段只能保证对于这个时间段来说是唯一的,而不是全局唯一。
要做到真唯一,我们必须把 line_item_usage_start_date 加到 ID 前面,虽然会让 ID 变得很长,但这个基本就可以做到全局唯一了,可以用来做数据拼接。
数据传输
在 CUR 账单中,数据传输并不是一个单独的服务,而是融入到了每个服务之中。如果我们想要统一地分析数据传输,就需要把这些服务中的数据传输都提取出来。识别方式是 product_product_family 字段为 Data Transfer。
至于数据传输是出站,还是跨 AZ,还是跨区域,或者是走的 CDN,这个要分析起来就比较麻烦了。每个服务都有每个服务自己的记录方式,有的使用 line_item_usage_type,有的使用 line_item_operation,还有的使用 product_transfer_type。
Amazon EC2
对于 EC2 实例机型,我们需要做的处理较多,以下简单讲解。
首先,我们可能想要找出实例的家族,比如 g5dn.xlarge 的实例家族就是 G4,其实例大家族则是 G。CUR 也提供了 product_instance_type_family 字段,但对于某些机型来说这个字段是空的,这时候我们就需要用正则来提取。
然后,是否是 Graviton,这个也是我们比较关心的问题,需要取的字段是 product_physical_processor,如果包含 Graviton 则是 Graviton 机型。
还有比较重要的是 EC2 的使用方式是按需、预留或者竞价实例。按需和竞价实例可以通过 line_item_usage_type 来判断,但预留则要复杂很多。
一次性付出的预留费用的 line_item_line_item_type 为 RIFee,但是这个无法体现实际使用了多少预留优惠。此时我们需要找 line_item_line_item_type 为 DiscountedUsage 的项目,代表实际预留的使用项。可能读者已经猜到,我们还可以把二者相减,则得到购买但未使用的预留(潜在的浪费)。
以上所有,除了要用 line_item_product_code 判断是否是 EC2 服务之外,我们还需要去除数据传输、优惠券、EBS 用量等等非实例费用才能得到最终的 EC2 费用。
Savings Plans
我们一般倾向于认为 Savings Plans(下简称「SP」)是类似预留实例的优惠,但实际上因为 Savings Plans 还可以覆盖诸如 Amazon Lambda 和 Amazon SageMaker 等资源,它被单独做成了一个服务。
不仅单独做成了一个服务,它的计费逻辑也和预留实例不同。对于预留实例,真实使用的实例,其费用显示会是 0,用户在统计的时候就不会把这些统计进去,但还是能看到预留实例优惠的实际应用情况。而 SP 则是会把实际的实例使用费用算进去。
这样,用户看到的成本就会同时包括 SP 的费用和实际实例使用的费用,就重复了。对此,SP 的解决方式是再给一个「逆向操作」,即有一个专门的条目类型 SavingsPlanNegation,这个类型会按小时来把实际实例使用的费用又再给扣除掉。
可以看出设计者的目的,是让我们更方便地计算「有多少 SP没用完」,但毕竟又多了一套算法,这里需要注意。
更多处理
以上只是简单讲解,我们已经可以看到,虽然 CUR 足够详尽,但真要做到随心所欲地进行分析和监控,还是有很多的工作要做。这些细节本文不再赘述,感兴趣的朋友可以到我们的开源方案 BetterBill 中详细了解。
BI 分析和展示示范
这里我们展示一下使用 BetterBill 处理后的 CUR 能做哪些成本分析。示范使用了 Amazon QuickSight,但我们也可以使用任意成熟的,可对接 Amazon Athena 的 BI 工具。注:数据已做过完善脱敏处理,仅供参考,不代表任何客户。
VCPU 小时数变化
当云用量有较大变化的时候,我们通常会问的第一个问题就是,到底是我的业务量变化了,还是说我做了优化,或者是产生了浪费?通过 VCPU 小时数,我们可以避开机型的影响,更真实地看到业务量的变化。
![]() |
服务费用变化
除了业务量变化,我们还希望知道每个服务的增减情况。比如某个月的服务费用增加很多,但是基本都增加在 Amazon S3 上。或者某个月开始我们开始使用了 Amazon Pinpoint 的服务,之前都没用过,等等。
![]() |
Graviton 的使用情况
这里我们想要看到的是 Graviton 的实际使用小时数,占整体的小时数的比例。这个要求我们把所有按需、预留、Savings Plans 等的实际用量都抽出来,再做计算。这个实际上比想象得要麻烦很多,但我们可以看到最真实地对比,去除了成本影响(Graviton 单价较低会导致比例较小),从而看到实际的 Graviton 使用比例。
![]() |
按 S3 桶查看存储量和智能分层
CUR 上包含了诸多信息,我们不只能看成本,也能看桶的存储量。除了存储量,我们还可以分析智能分层在整个存储中的占比,以及智能分层中具体存储级别的占比等。
![]() |
查看数据传输流向
通过对数据传输账单项的深度处理,我们可以更清晰地展示数据的传输流向。如果 BI 工具支持更复杂的流向展示,我们还可以更清楚地展示数据流向。
![]() |
总结
我们的云上旅程一般分为几个阶段。
初期一般都是粗放式的使用,有很多不合理之处,但是因为需要快速促成业务,所以很多成本问题也无暇顾及。中期开始关注成本,但是还是会比较按照传统思维来希望基建层面单独降本,或者寻求各种折扣。在 IT 建设越来越成熟之后,我们会更希望能清晰地知道每一笔费用都是用来做什么的,是谁或者哪个部门用的,以及,费用变化是否跟随业务,还是说出现了一些完全可以避免的浪费。
云的便利性和弹性让我们可以更深度地去拆分和监测我们的成本变化,但是服务的多样化和收费模式的变化,也给财务规划和预算制订带来了挑战。这篇文章仅作抛砖引玉,通过分析 CUR 和展示一些成本分析的思路,帮助读者构建起云上财务思维,在初期就做好成本相关的规划,真正把每一分钱花到实处。