
打开云费用账单的那一刻,我愣住了——120 台 ECS、3 个 ACK 集群、50+ SLB 实例,每月 28 万。更扎心的是,AI 分析告诉我:超过六成的钱花在了"不需要"的资源上。闲置的机器在跑、过度分配的 CPU 在浪费、低谷期的 Pod 在空转。
我负责的阿里云账号下 120+ 台 ECS、3 个 ACK 集群、50+ 个 SLB 实例,每月云费约 28 万元。经过 AI 分析,发现大量浪费:
浪费类型 | 占比 | 月度浪费金额 | 说明 |
|---|---|---|---|
闲置 ECS | 15% | 4.2 万 | CPU < 5% 持续 7 天 |
过度分配 | 25% | 7.0 万 | Request 远大于实际用量 |
弹性不足 | 10% | 2.8 万 | 低谷期未缩容 |
闲置 SLB | 8% | 2.2 万 | 无后端服务却未释放 |
磁盘未清理 | 5% | 1.4 万 | 未挂载的云盘 |
合计 | — | 17.6 万 | 占总费用 63% |
人工巡检根本看不过来,AI 才是解决规模化的出路。


图:云资源成本分析仪表盘,直观展示各服务费用占比和闲置资源分布情况
核心思路:指标采集 → AI 分析 → 自动治理,形成完整闭环。

维度 | 优化前 | 优化后 | 改善 |
|---|---|---|---|
月度云费 | 28 万 | 17.4 万 | ⬇️ 38% |
ECS 平均利用率 | 18% | 52% | ⬆️ 189% |
闲置资源数 | 35 台 | 3 台 | ⬇️ 91% |
弹性响应延迟 | 10 分钟 | 2 分钟 | ⬇️ 80% |
闲置判定不是简单的"CPU 低就标记",而是多层条件组合:利用率阈值 → 持续时间 → 关联资源检查(SLB 流量)→ 最终判定。

单日低利用率可能是业务低谷,7 天持续低利用率才是真正的闲置。
#!/usr/bin/env python3
"""
闲置资源检测脚本
基于阿里云 OpenAPI + Prometheus 指标
"""
import requests
from datetime import datetime, timedelta
from alibabacloud_ecs20140526.client import Client as ECSClient
from alibabacloud_ecs20140526 import models as ecs_models
PROMETHEUS_URL = "http://localhost:9090"
# 闲置判定阈值
IDLE_THRESHOLD = {
"cpu_avg_percent": 5, # CPU 7天均值 < 5%
"cpu_peak_percent": 15, # CPU 7天峰值 < 15%
"network_kb_per_sec": 10, # 网络流量 < 10KB/s
"duration_days": 7 # 持续天数
}
def get_ecs_instances() -> list:
"""获取所有运行中的 ECS 实例"""
client = ECSClient(...)
request = ecs_models.DescribeInstancesRequest(
region_id="cn-hangzhou",
status="Running"
)
response = client.describe_instances(request)
return response.body.instances.instance
def check_instance_utilization(instance_id: str) -> dict:
"""检查实例利用率"""
end = datetime.now()
start = end - timedelta(days=7)
cpu_avg_query = f'avg_over_time(acs_ecs_cpu_total{{instanceId="{instance_id}"}}[7d])'
cpu_peak_query = f'max_over_time(acs_ecs_cpu_total{{instanceId="{instance_id}"}}[7d])'
net_query = f'avg_over_time(acs_ecs_network_rate{{instanceId="{instance_id}"}}[7d])'
cpu_avg = query_prometheus(cpu_avg_query)
cpu_peak = query_prometheus(cpu_peak_query)
net_avg = query_prometheus(net_query)
is_idle = (
cpu_avg < IDLE_THRESHOLD["cpu_avg_percent"]
and cpu_peak < IDLE_THRESHOLD["cpu_peak_percent"]
and net_avg < IDLE_THRESHOLD["network_kb_per_sec"]
)
return {
"instance_id": instance_id,
"cpu_avg": round(cpu_avg, 2),
"cpu_peak": round(cpu_peak, 2),
"network_avg": round(net_avg, 2),
"is_idle": is_idle
}
def query_prometheus(query: str) -> float:
"""查询 Prometheus 指标"""
resp = requests.get(
f"{PROMETHEUS_URL}/api/v1/query",
params={"query": query}
)
results = resp.json()["data"]["result"]
ifnot results:
return0.0
return float(results[0]["value"][1])
def scan_idle_resources() -> list:
"""扫描所有闲置资源"""
instances = get_ecs_instances()
idle_list = []
for inst in instances:
util = check_instance_utilization(inst.instance_id)
if util["is_idle"]:
idle_list.append({
**util,
"instance_name": inst.instance_name,
"instance_type": inst.instance_type,
"monthly_cost": estimate_cost(inst.instance_type)
})
idle_list.sort(key=lambda x: x["monthly_cost"], reverse=True)
return idle_list
def estimate_cost(instance_type: str) -> float:
"""估算实例月度费用"""
PRICE_MAP = {
"ecs.c6.large": 280,
"ecs.c6.xlarge": 560,
"ecs.g6.large": 320,
"ecs.g6.xlarge": 640,
"ecs.r6.large": 380,
}
return PRICE_MAP.get(instance_type, 200)
=== 闲置资源检测报告 ===
扫描时间: 2026-06-28 10:00:00
扫描范围: cn-hangzhou 运行中实例
闲置实例列表:
1. dev-test-03 (ecs.c6.xlarge) CPU均值:2.1% 月费:560元
2. staging-api-02 (ecs.g6.large) CPU均值:3.8% 月费:320元
3. legacy-worker (ecs.r6.large) CPU均值:1.5% 月费:380元
潜在节省: 1,260 元/月

图:弹性伸缩策略配置界面,展示 HPA 优化前后的参数差异
为什么不让运维手动调 HPA?120+ 个服务,每个服务的流量模式都不同,人工调参既慢又不准。
# AI 优化前(默认配置)
apiVersion:autoscaling/v2
kind:HorizontalPodAutoscaler
metadata:
name:order-service-hpa
spec:
minReplicas:3
maxReplicas:10
metrics:
-type:Resource
resource:
name:cpu
target:
type:Utilization
averageUtilization:70# 粗暴固定值
---
# AI 优化后(根据历史流量模式调整)
apiVersion:autoscaling/v2
kind:HorizontalPodAutoscaler
metadata:
name:order-service-hpa
annotations:
optimized-by:ai-cost-engine
optimized-at:"2026-06-28"
spec:
minReplicas:2 # 低谷期 2 副本足够
maxReplicas:15 # 高峰期允许更多扩容
behavior:
scaleDown:
stabilizationWindowSeconds:300# 缩容稳定窗口 5 分钟
policies:
-type:Percent
value:25 # 每次缩容不超过 25%
periodSeconds:60
scaleUp:
stabilizationWindowSeconds:0 # 扩容立即响应
policies:
-type:Percent
value:100 # 紧急时翻倍扩容
periodSeconds:30
metrics:
-type:Resource
resource:
name:cpu
target:
type:Utilization
averageUtilization:55# 提前扩容,避免过载
-type:Pods
pods:
metric:
name:http_requests_per_second
target:
type:AverageValue
averageValue:"500"# 每副本 500 QPS
时段 | 优化前副本数 | 优化后副本数 | 节省实例小时 |
|---|---|---|---|
00:00-06:00 | 3 | 2 | 6 小时 |
06:00-09:00 | 3 | 3 | 0 |
09:00-12:00 | 5 | 5 | 0 |
12:00-14:00 | 5 | 3 | 10 小时 |
14:00-18:00 | 7 | 6 | 5 小时 |
18:00-21:00 | 5 | 3 | 10 小时 |
21:00-24:00 | 3 | 2 | 3 小时 |
日节省 | — | — | 34 实例小时 |
现象:批处理实例仅在凌晨 2:00-4:00 运行,其余时间 CPU 接近 0,被标记为闲置并通知释放。
原因:检测逻辑只看整体均值,没有考虑定时任务的特殊调度模式。
解决:增加"定时任务白名单"机制,标注了 schedule-job=true 的实例跳过闲置检测。
提醒:不是所有低利用率实例都是"闲置",要区分"不用"和"按需使用"。
现象:流量从高峰回落后,HPA 在 1 分钟内缩容 50%,剩余 Pod 无法承载残余流量。
原因:默认缩容策略没有稳定窗口,stabilizationWindowSeconds 设为 0。
解决:设置缩容稳定窗口为 5 分钟,且单次缩容比例不超过 25%:
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 25
periodSeconds: 60
提醒:扩容要快、缩容要慢,这是弹性伸缩的基本原则。
现象:AI 推荐将 20 台按量付费 ECS 转为包年包月,但下季度业务扩张需要新增 15 台,规格可能变化。
原因:预留实例推荐只基于历史用量,没有纳入业务增长预测。
解决:预留实例推荐加入"增长因子",只推荐当前用量 70% 的包年包月,留出弹性空间:
def recommend_reserved(current_count: int, growth_rate: float = 0.3) -> int:
"""推荐预留实例数量"""
reserved = int(current_count * 0.7)
predicted = int(current_count * (1 + growth_rate))
return min(reserved, predicted)
提醒:包年包月是"锁价"也是"锁量",弹性需求大的场景要谨慎。
AI 成本优化不是一次性的,需要持续监控优化效果,避免误回收导致服务受影响。
监控项 | 采集方式 | 更新间隔 | 告警阈值 | 严重级别 |
|---|---|---|---|---|
月度云费用增长率 | 云账单 API | 86400s | > 上月 10% | P1 |
闲置资源误回收 | 用户投诉 + 日志 | 3600s | 任何误回收 | P0 |
弹性伸缩频次 | HPA 指标 | 300s | > 10 次/小时 | P2 |
资源利用率 | Prometheus | 300s | < 20% 持续 7 天 | P2 |
包年包月 vs 按量比例 | 云账单 API | 86400s | 按量 > 40% | P3 |
AI 成本优化的核心价值:
适合谁用:云资源规模大(50+ 实例)、费用持续增长、缺乏成本治理流程的团队
不适合谁用:资源规模小(< 20 实例)、业务强关联无法缩容、合规要求固定资源
💬 你的团队每月云费多少?有没有做过成本优化?评论区聊聊~