2. 云账单数据解剖
做云成本分摊与Showback,第一步不是写分摊规则,而是把账单“读对”。三大公有云的原始账单在结构、粒度、字段命名和交付方式上差异很大:AWS CUR 是列式明细、Azure Cost Details 是行式明细、GCP Billing Export 是带标签的宽表。如果对字段含义理解偏差,后续按标签、按项目、按资源的分摊结果就会整体失真。本节先建立“账单解剖”的统一视角,再逐家拆解关键字段与常见数据质量问题。
一、先建立统一视角:账单的四个维度
无论哪家云,账单明细都可以用四个维度来定位一条记录:时间维度(计费周期、使用起止时间)、资源维度(资源ID、资源类型、区域)、归属维度(账号、订阅、项目、标签)、金额维度(用量、单价、费用、币种、抵扣)。分摊工程真正依赖的是“归属维度”和“金额维度”的交叉:只有把每条费用准确挂到某个成本中心或业务单元,Showback 才有意义。
需要特别区分三类金额:List Cost(标价)、Effective Cost(实际成本)、Amortized Cost(摊销成本)。标价是未打折的目录价;实际成本是扣除折扣、优惠券、私有定价后的应付金额;摊销成本则把一次性预付(如 Reserved Instance、Savings Plan、CUD)按使用周期摊到每一天。做内部 Showback 时,通常应使用摊销成本,否则会出现“买预留的月份成本暴涨、后续月份成本为零”的失真现象。
二、AWS CUR:列式明细与摊销成本
AWS 的 Cost and Usage Report(CUR)以 Parquet 或 CSV 形式投递到 S3,通常配合 Athena 或 Data Exports 查询。它的核心特征是“一行一计量”,同一资源在同一小时内可能产生多行:使用行、抵扣行、税费行、退款行。关键字段包括 lineItem/UsageStartDate、lineItem/UnblendedCost、lineItem/ResourceId、product/ProductName,以及标签列 resourceTags/user:CostCenter。
做摊销时,不能直接用 UnblendedCost。正确做法是:对按需资源取 lineItem/UnblendedCost;对 RI 覆盖的资源取 reservation/EffectiveCost;对 Savings Plan 覆盖的资源取 savingsPlan/SavingsPlanEffectiveCost。这三者相加才是该资源当天的真实摊销成本。示例:某 EC2 实例当天按需部分 12.00 美元,RI 覆盖部分 EffectiveCost 为 8.50 美元,则摊销成本为 20.50 美元,而不是按需账单上显示的 12.00 美元。
三、Azure Cost Details:行式明细与标签解析
Azure 的 Cost Details 通过 Cost Management 导出到 Storage Account,字段以行式组织,一行代表某天某计量的一次费用。核心字段有 Date、CostInBillingCurrency、ResourceId、MeterCategory、Tags、PricingModel。其中 Tags 是 JSON 字符串,例如 {"CostCenter":"CC-1024","Env":"Prod"},在入库前必须解析展开,否则无法按标签聚合。
Azure 的常见坑是标签大小写不一致:CostCenter 与 costcenter 会被视为两个不同标签,导致同一成本中心被拆成两行。建议在 ETL 阶段统一转为小写并做映射表。另外,PricingModel 为 Reservation 的行需要与按需行合并,按实际使用量做摊销,否则预留购买当月会出现成本尖峰。
四、GCP Billing Export:BigQuery 宽表与抵扣处理
GCP 的 Billing Export 直接写入 BigQuery 数据集,表按天分区,字段是嵌套结构。核心字段包括 usage_start_time、cost、currency、project.id、service.description、sku.description、labels、credits、cost_type。其中 labels 是数组,需要用 UNNEST 展开;credits 是抵扣明细数组,必须从 cost 中扣除才是净成本。
一个典型查询片段如下,用于按成本中心汇总净成本:
SELECT
l.value AS cost_center,
SUM(b.cost) + SUM(IFNULL(c.amount, 0)) AS net_cost
FROM `project.billing.gcp_billing_export_v1_XXXX` b
LEFT JOIN UNNEST(b.labels) AS l
ON l.key = 'cost_center'
LEFT JOIN UNNEST(b.credits) AS c
ON TRUE
WHERE b.usage_start_time >= '2024-06-01'
GROUP BY cost_center;
注意 credits.amount 通常为负值,直接相加即可完成抵扣。若忽略 credits,GCP 成本会被系统性高估。
五、跨云数据质量检查清单
在把三家账单接入分摊引擎前,建议先跑一遍数据质量检查。以下清单可直接作为 ETL 验收项:
| 检查项 | AWS CUR | Azure Cost Details | GCP Billing Export |
|---|---|---|---|
| 时间字段是否完整 | UsageStartDate 非空 | Date 非空 | usage_start_time 非空 |
| 金额字段是否可加总 | UnblendedCost + EffectiveCost | CostInBillingCurrency | cost + credits.amount |
| 标签是否可解析 | resourceTags 列存在 | Tags JSON 可解析 | labels 可 UNNEST |
| 未分配占比 | < 5% 为健康 | < 5% 为健康 | < 5% 为健康 |
| 币种是否统一 | 检查 currency 列 | BillingCurrency | currency |
| 抵扣是否已扣除 | RI/SP 行已合并 | BenefitId 已处理 | credits 已 JOIN |