阿里云成本分析模块

所属项目:UniOps 统一运维工作台
核心功能:月度消费分析 · 浪费检测 · 长期趋势追踪


目录

  1. 概述
  2. 凭证配置
  3. 页面导航
  4. 成本分析(/aliyun/aliyun-cost)
  5. 浪费检测(/aliyun/aliyun-cost/aliyun-waste)
  6. 技术实现
  7. API 接口
  8. 数据说明
  9. 常见问题

概述

阿里云成本模块是 UniOps 的核心功能模块,解决以下问题:

  • 钱花在哪了? — 按产品线(ECS、OSS、SLB、RDS…)展示月度消费排行
  • 趋势如何? — 近6个月费用折线图,红涨绿跌,一眼看清变化
  • 有无浪费? — 自动发现已停机但仍产生费用的 ECS 实例,按计费项(系统盘、实例配置)拆分金额
  • 环比变化? — 3 个月链式对比,精确到百分比

解决的问题

问题 方案
每月账单几十万,不知道哪些产品花得多 产品线消费排行,≥2% 单独展示
停机了还在扣费?扣的什么费? 浪费检测自动匹配停机实例 + 账单,按计费项拆分
成本到底是涨了还是降了? 近6个月趋势折线图 + 3 个月环比
每次刷新都要等 API 慢慢查? 文件级持久缓存 + 内存加速,毫秒级加载

在这里插入图片描述
在这里插入图片描述


凭证配置

获取 AccessKey

  1. 登录阿里云 RAM 控制台 → AccessKey 管理
  2. 创建 AccessKey,记录 AccessKey IDAccessKey Secret
  3. 授予以下权限策略:
策略 用途
AliyunBSSReadOnlyAccess 读取账单(BSS API)
AliyunECSReadOnlyAccess 读取 ECS 实例列表

配置到 UniOps

编辑项目根目录的 .env 文件:

ALIBABA_ACCESS_KEY=LTAI5txxxxxxxxxxxxxxxx
ALIBABA_SECRET_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxx
ALIBABA_REGION=cn-hangzhou

ALIBABA_REGION 仅用于指定默认区域,模块会自动发现所有可用区域。


页面导航

首页 (/)
└── 阿里云 (/aliyun)                    ← Hub,显示 ECS 统计 & 成本预览
    └── 成本 (/aliyun/aliyun-cost)      ← 月度消费分析主页面
        └── 浪费检测 (/aliyun/aliyun-cost/aliyun-waste)
                                         ← 已停机 ECS 浪费详情

成本分析

路径/aliyun/aliyun-cost

页面组成

1. 3 个月链式对比(顶部)

展示最近 3 个完整月的消费金额和环比变化百分比:

┌──────────┐ ┌──────────┐ ┌──────────┐
│  02 月   │ │  03 月   │ │  04 月   │
│ ¥714,609 │ │ ¥726,624 │ │ ¥716,282 │
│          │ │  ↑1.7%   │ │  ↓2.7%   │
└──────────┘ └──────────┘ └──────────┘
  • 当前月份高亮显示(蓝色下划线)
  • 涨为红色(↑),跌为绿色(↓)
2. 月度总览 Hero
┌──────────────────────────────────────────────────┐
│  ¥716,282        ┌─── 近6个月费用趋势 ─────────┐  │
│  ↑1.3%           │  📈 折线图(红涨绿跌)      │  │
│                  └──────────────────────────────┘  │
└──────────────────────────────────────────────────┘
  • 左侧:本月消费总额 + 环比变化百分比
  • 右侧:近6个月费用趋势折线图
    • 每个数据点标注具体金额
    • 数据点颜色:涨(红色)、跌(绿色)、持平(灰色)
    • 渐变填充区域
3. 浪费检测入口
💡 上月浪费预估 ¥3,298 — 47 台已停机 ECS 仍在产生费用 · 点击查看详情 →
4. 按产品线消费排行

展示所有产品线(ECS、OSS、SLB、RDS、PolarDB…)的消费排行:

  • 条形图:最大项填充 85% 宽度,其余按比例缩放
  • 阈值规则:≥ 2% 单独展示,< 2% 合并为「其他」
    • 「其他」中 ≥ 1% 的产品显示明细(灰色小字)
  • 每行显示:产品名、金额、占比

示例数据(上月):

产品 金额 占比
ECS 实例 ¥523,386 73.1%
弹性 IP ¥61,903 8.6%
PolarDB 数据库 ¥47,275 6.6%
其他 ¥36,230 5.1%

浪费检测

路径/aliyun/aliyun-cost/aliyun-waste

页面组成

1. HERO 区域
┌──────────────────────────────────────────────────┐
│  ¥3,298           ┌─── 近6个月浪费趋势 ────────┐  │
│  47 台已停机 ECS   │  📈 折线图(红涨绿跌)      │  │
│                    └──────────────────────────────┘  │
└──────────────────────────────────────────────────┘
  • 左侧:月浪费总额 + 已停机实例数量
  • 右侧:近6个月浪费趋势折线图
2. 统计卡片
停机实例 产生费用中 2026年5月 浪费总额
47 47 ¥3,298
3. 已停机 ECS 列表(TOP 5 + 展开)

默认展示消费金额最高的 5 台,点击「展开全部 N 项 ▼」查看全部:

实例名称 IP 配置 费用明细 区域 月合计
应用01-旧-暂关机 10.0.0.1 4vCPU · 8 GiB 系统盘 ¥56.40
云服务器配置 ¥543.88
北京 ¥600.29
堡垒机 10.0.0.5 2vCPU · 4 GiB 系统盘 ¥18.95
实例 ¥213.35
数据盘 ¥37.91
北京 ¥270.21
  • 按消费金额从高到低排序
  • 产生费用的行高亮(淡红色背景)
  • 费用明细按计费项(BillingItem)拆分:系统盘(SystemDiskSize)、云服务器配置(InstanceType)等

什么是浪费?

阿里云 ECS 实例在 已停止(Stopped) 状态下,以下资源仍会产生费用:

计费项 说明 是否可避免
系统盘(SystemDiskSize) 系统盘容量占用,按小时计费 ❌ 释放实例才免
实例配置(InstanceType) vCPU + 内存,按小时计费 ❌ 释放实例才免
数据盘(DataDisk) 挂载的云盘 ❌ 释放实例才免
镜像(ImageOS) 免费,¥0

因此,已停机 ≠ 不产生费用。只要不释放实例,系统盘和实例配置会持续计费。


技术实现

架构

浏览器 (JS 渲染)           FastAPI 服务             阿里云 API
     │                        │                        │
     │── GET /api/cost ──────→│── DescribeInstanceBill →│
     │                        │← 账单数据 ─────────────│
     │← JSON (含缓存) ───────│                        │
     │                        │                        │
     │── GET /api/waste ─────→│── DescribeInstanceBill →│
     │                        │── DescribeInstances ───→│
     │                        │← 账单 + 实例数据 ──────│
     │← JSON (含趋势) ──────│                        │

阿里云 API 调用

API 用途 频率
DescribeInstanceBill 获取实例级账单(含/不含计费项拆分) 缓存在 data/
QueryBill 获取月度消费总额 同上
DescribeInstances 查询 ECS 实例列表及状态 同上
DescribeRegions 自动发现可用区域 同上

不使用阿里云 Python SDK(Python 3.13 不兼容),改用直接 HTTP 调用 + HMAC-SHA1 签名。

签名算法

阿里云 API 使用 HMAC-SHA1 签名(非 ROA 风格):

string_to_sign = f"GET&%2F&{urlencode(sorted_params)}"
signature = base64(hmac_sha1(f"{secret}&", string_to_sign))

详见 monitors/providers/aliyun/_auth.py

缓存策略

层级 存储 TTL 用途
内存 Python dict 5 分钟 高频访问加速
文件 data/aliyun_cost.json 永久(按月份校验) 重启不丢
文件 data/aliyun_waste.json 永久 同上
文件 data/aliyun_ecs.json 永久 同上
  • 历史月份数据不变,读取一次永久缓存
  • 强制刷新:API 路径加 ?refresh=1
  • 月份校验:缓存中的 main_month 与当前应查月份一致才使用

数据流

阿里云 API
    ↓ (并发查询,最多 6 线程)
_fetch_cost_summary() / _fetch_waste_detail()
    ↓ (写入)
data/aliyun_cost.json / data/aliyun_waste.json
    ↓ (读取)
get_cost_summary() / get_waste_detail()
    ↓ (FastAPI 路由)
/api/aliyun/cost → cost.html (客户端渲染)
/api/aliyun/waste → waste.html (客户端渲染)

6 个月趋势计算

当前已停机实例列表 (ECS API)
    ↓ (对每个月分别查询账单)
12月账单 → 匹配停机实例 → ¥4,537
 1月账单 → 匹配停机实例 → ¥3,298
 2月账单 → 匹配停机实例 → ¥2,986
 ... (共 6 个月,ThreadPoolExecutor 并行)
    ↓
趋势数据: [{month, amount, change_pct}, ...]
    ↓
SVG 折线图(红涨绿跌)

API 接口

成本

GET /api/aliyun/cost?refresh=1

响应结构

{
  "configured": true,
  "main_month": "2026-05",
  "main_total": 716282.26,
  "chain": [
    { "month": "2026-03", "total": 726624.04, "change_pct": 1.7 },
    { "month": "2026-04", "total": 707233.89, "change_pct": -2.7 },
    { "month": "2026-05", "total": 716282.26, "change_pct": 1.3 }
  ],
  "by_product": [
    { "product": "ECS 实例", "code": "ecs", "amount": 523386.12, "pct": 73.1 },
    ...
  ],
  "trend": [
    { "month": "2025-12", "amount": 785404.34, "change_pct": null },
    { "month": "2026-01", "amount": 768506.51, "change_pct": -2.2 },
    ...
  ],
  "waste": {
    "total": 3298.09,
    "stopped_count": 47,
    "items": [...]
  }
}

浪费检测

GET /api/aliyun/waste?refresh=1

响应结构

{
  "configured": true,
  "main_month": "2026-05",
  "total": 3298.09,
  "stopped": [
    { "id": "i-xxx", "name": "实例名", "status": "Stopped", "cpu": 4, "memory": "8 GiB", ... }
  ],
  "items": [
    {
      "instance_id": "i-xxx",
      "instance_name": "实例名",
      "region": "cn-beijing",
      "amount": 600.29,
      "items": [
        { "name": "SystemDiskSize", "amount": 56.40 },
        { "name": "InstanceType", "amount": 543.88 }
      ]
    }
  ],
  "trend": [
    { "month": "2025-12", "amount": 4536.57, "change_pct": null },
    { "month": "2026-01", "amount": 3298.09, "change_pct": -27.3 },
    ...
  ]
}

数据说明

时间范围

  • 成本分析:展示最近 3 个完整月的消费情况(不含当月)
  • 浪费检测:展示上个月的计费数据
  • 趋势图:展示最近 6 个完整月的趋势(不含当月)

数据准确性

  • 数据来源:阿里云 BSS(Billing Service)API,与阿里云控制台「费用中心」数据一致
  • 已验证:API 数据与 CSV 导出账单逐项对照,金额一致
  • 已停机实例状态来自 ECS API,实时反映当前状态

产品线映射

常见阿里云产品代码与中文名称映射:

产品代码 中文名
ecs ECS 实例
oss OSS 对象存储
slb SLB 负载均衡
rds RDS 数据库
polardb PolarDB 数据库
eip 弹性 IP
nas NAS 文件存储
sas 云安全中心
waf WAF
dds MongoDB
elasticsearch Elasticsearch
snapshot 快照
redis Redis
vpc VPC
ons 消息队列
sls 日志服务 SLS

常见问题

Q: 页面一直显示「加载中…」

A: 首次加载需要调用阿里云 API 获取数据,耗时约 5-15 秒(6 个月账单并行查询)。之后走缓存,毫秒级加载。

Q: 为什么浪费金额比预期少/多?

A: 浪费检测只统计已停机 ECS 实例本月仍在产生的费用(系统盘 + 实例配置 + 数据盘)。如果实例已释放,不会计入。

Q: 趋势图中的金额为什么有波动?

A: 趋势计算方式:用当前的已停机实例列表去匹配过去每个月的账单。如果某台机器上个月还在运行,上个月的趋势中就不会包含它的费用。

Q: 支持实时数据吗?

A: 不实时。模块展示的是已出账的完整月份数据(上月),不查询当月未出账数据。这是有意设计——未出账数据不稳定,不适合做分析。

Q: 如何强制刷新数据?

A: 在 API 路径末尾加 ?refresh=1,或清空 data/ 目录下的 JSON 文件后重启服务。


阿里云成本模块 — 让每一分钱都花得明白。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐