AWS 通过账单提取S3桶存储量大小

如何通过AWS的CUR账单1提取S3桶的存储量大小?

需求描述

通过CUR, 提取S3桶的存储量大小数据, 提取按天/按小时等间隔的打点数据, 用于后续图表制作

分析过程

对现有情况进行分析. 已知情况:

  • S3存储计费说明统一的计算单位为: CURRENCY x.y/GB/mo, 如: CNY 0.195 per GB - first 50 TB / month of storage used
  • line_item_usage_type(行使用类型描述)中对于存储类型的描述为: REGION-TimedStorage-TYPE-ByteHrs, 如: CNN1-TimedStorage-ByteHrs

分析可知:

  1. AWS对于S3桶的计费逻辑其实为ByteHrs, 即字节/小时, 但是由于精度问题, 只能使用GB/mo作为计费维度以降低误差

  2. 如果对于未清洗的CUR数据, 其每小时打点数据的计费单元为: GBHrs即: CURRENCY x.y/GB/hrs

    gantt
        title S3桶计费图
        dateFormat  YYYY-MM-DD
        section Bucket
        1st hour          :a1, 2023-01-01, 1h
        2nd hour          :a2, after a1, 1h
        3rd hour          :a3, after a2, 1h
        4th hour          :a4, after a3, 1h
        many hours        :a5, after a4, 30d
        last hour         :a6, after a5, 1h

    参见上方示意甘特图, 假设一个bucket容量及使用类型不变的情况下, 聚合整月line_item_usage_type数据为其总容量(GB), 那么每小时打点的line_item_usage_type值则表示该容量分散到了单位小时计费的容量(GB)

初步假设

每小时数据

如果需要采集每小时数据, 需要做一些转换, 将CUR计费规则与其每小时打点数据进行结合, 即\(¥/GB/mo\) ➡️ \(¥/GB/hrs\)

猜想1: 按720计算

\[ 1 mo(Month) = 720 hrs(Hours) = 24 * 30 (每天24小时, 每个月以30天计) \]

猜想2: 按730计算

\[ 1 mo(Month) = 730 hrs(Hours) = \frac {24 * 365} {12} (每天24小时, 一年以365天计, 一年12个月) \]

猜想3: 按自然小时数计算

该比率值按实际自然日*242计算? 可能性较低, 但不排除这种可能性

汇总

\[ GB / mo = \frac {1}{720} GB / hrs\ 或 \ GB / mo = \frac {1}{730} GB / hrs\ 或\ GB / mo = ? GB / hrs \]

即, 对于每小时打点的数据, 其line_item_usage_type值应扩大720/730倍或根据实际自然小时数扩大倍数, 则为该时间点的数据总量(GB)

每天数据

同样地, 如果需要采集每天数据, 将计费规则转换, 即\(¥/GB/mo\)➡️\(¥/GB/d\)

猜想1: 按30天计算

\[ 1 mo(Month) = 30 d(每个月以30天计) \]

猜想2: 按平均天数计算

\[ 1 mo(Month) = \frac {365} {12} = 30.4166666667 d(一年以365天计, 一年12个月) \]

由于计算后非整数, 极大概率本猜想为

猜想3: 按自然日计算

该比率值按实际自然日3计算? 可能性较低, 但不排除这种可能性

汇总

\[ GB / mo = \frac {1}{30} GB / d 或GB/mo = ? GB/d \]

即, 对于每天打点的数据, 其line_item_usage_type求和值应扩大30倍或根据实际自然日扩大倍数, 则为该时间点的数据总量(GB)

以字节计算

由于存储桶大小规则不一致, 可以考虑使用Byte(字节)作为数据单位格式, 依据不同大小, 分配合适的单位, 如TB/GB/MB等, 满足: \[ 1 Gigabyte(GB) = 1024 Megabyte(MB) = 1024^2 Kilobyte(KB) = 1024^3 byte(B) \] 因此对于line_item_usage_type计算后结果, 应扩大10243倍用于计算其字节数

验证

获取验证数据, 以某一个账号, 某个仅使用标准存储的资源为例.

获取测试数据

  1. 登录CloudWatch Management Console, 进入指标页面

    进入指标页面
  2. 全部指标页面, 依次点击S3➡️存储指标➡️☑️测试存储桶, 指标名称应为BucketSizeBytesNumberOfObjects, 参考以下图示

    全部指标页面
    S3指标页面
    测试存储桶

    为避免混淆, 选择单一类型存储为佳, 满足: 总文件计数🟰 桶内文件数量

  3. 调整时间周期, 提取指定周期内数据

    设置周期为周
    提取周期内稳定数据

    可以看到, 测试通数据量一直处于稳定态, 记录该存储桶总字节数: 4,378,330,892,612

  4. 使用Athena查询并聚合2023-03-08当天数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    SELECT SUM(line_item_usage_amount) AS "usage"
    /* 依据实际情况修改库名和表名 */
    FROM "athenacurcfn_daily_report"."dailyreport"
    WHERE line_item_product_code = 'AmazonS3'
    AND line_item_line_item_type = 'Usage'
    AND line_item_operation = 'StandardStorage'
    AND line_item_resource_id = '测试存储桶名称'
    AND line_item_usage_start_date BETWEEN
    CAST('2023-03-08 00:00:00' AS TIMESTAMP)
    AND
    /* AWS 对于时间最多支持到毫秒级别, 无法使用纳秒级别 */
    CAST('2023-03-08 23:59:59.999' AS TIMESTAMP)
    /* 这里使用纳秒级别可以将时间扩大至次日零时零分零秒 */
    AND line_item_usage_end_date <= CAST('2023-03-08 23:59:59.999999' AS TIMESTAMP)
    ;

    获取Athena执行结果

    记录查询后结果: 131.5367225621

汇总数据

测试结果一览表

项目 备注
CloudWatch监控指标-桶字节数 4378330892612 该数据平稳无波动, 即实际该存储桶容量
CUR账单-桶line_item_usage_amount求和结果 131.5367225621 该数据表示在2023-03-08当天该桶总计费单元

验证猜想

验证猜想1

按照上文猜想1对每天数据的猜测, 对于现有数据进行计算, 满足: \[ 131.5367225621 GB/hrs = 131.5367225621 * 30 GB/mo = 3946.1016768630 GB/mo \] 按照上文中的初步猜测, 对于GB➡️B的换算4, 对现有数据进行分析, 满足: \[ 3946.1016768630 GB = 3946.1016768630 * 1024^3 B = 4237094412204.3400000000 B \] 结果误差为: \(4378330892612 - 4237094412204.3400000000 = 141236480407.6640000000\)

由于误差非常大(达到千亿级别), 因此本猜想结论为

验证猜想2

按照上文猜想2对每天数据的猜测, 对于现有数据进行计算, 满足: \[ 131.5367225621 GB/hrs = 131.5367225621 * 30.4166666667 GB/mo = 4000.9086446016 GB/mo \] 按照上文中的初步猜测, 对于GB➡️B的换算5, 对现有数据进行分析, 满足: \[ 4000.9086446016 GB = 4000.9086446016 * 1024^3 B = 4295942945711.8800000000 B \] 结果误差为: \(4378330892612 - 4295942945711.8800000000 = 82387946900.1177000000\)

由于误差非常大(达到百亿级别), 不过比猜想1误差有所降低, 因此本猜想结论为

验证猜想3

按照上文猜想3对每天数据的猜测, 对于现有数据进行计算, 满足: \[ 131.5367225621 GB/hrs = 131.5367225621 * 31 GB/mo = 4077.6383994251 GB/mo \] 按照上文中的初步猜测, 对于GB➡️B的换算6, 对现有数据进行分析, 满足: \[ 4077.6383994251 GB = 4077.6383994251 * 1024^3 B = 4378330892611.1500000000 B \] 结果误差为: \(4378330892612 - 4378330892611.1500000000 = 0.8520507813\)

误差竟然<1B! 因此本猜想结论为

结果表

验证结果图

结论

按小时打点

如果需要按小时打点数据, 则需要对数据集的line_item_usage_amount列乘以当月实际自然日再乘以24计算 \[ Bucket\_Size\ (GB) = line\_item\_usage\_amount * 24 * days \]

按天打点

如果需要按天打点数据, 则需要对数据集的line_item_usage_amount列乘以当月实际自然日计算 \[ Bucket\_Size\ (GB) = line\_item\_usage\_amount * days \]

建议

无论何种打点规则, 建议数据存储以字节作为单位以最大限度降低误差 \[ Bucket\_Size\ (B) = Bucket\_Size\ (GB) * 1024^3 \]

如果需要严格计算, 一般来说, CloudWatch结果会比计算结果多1B, 对计算结果向下取整1即可 \[ Bucket\_Size\ (B) = \lfloor Bucket\_Size\ (B) \rfloor + 1 \]


  1. AWS 官方文档什么是AWS成本和使用率报告? - AWS 成本和使用情况报告↩︎

  2. 自然日定义自然日_百度百科↩︎

  3. 自然日定义自然日_百度百科↩︎

  4. 一般情况下或称严格意义上, 存储的换算单位以1024为单位, 不同于硬盘厂商等以1000为单位↩︎

  5. 一般情况下或称严格意义上, 存储的换算单位以1024为单位, 不同于硬盘厂商等以1000为单位↩︎

  6. 一般情况下或称严格意义上, 存储的换算单位以1024为单位, 不同于硬盘厂商等以1000为单位↩︎