首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >云成本治理实战:AI 弹性伸缩与闲置资源回收,月费直降 38%

云成本治理实战:AI 弹性伸缩与闲置资源回收,月费直降 38%

作者头像
行者全栈架构师
发布2026-07-16 21:33:53
发布2026-07-16 21:33:53
680
举报

打开云费用账单的那一刻,我愣住了——120 台 ECS、3 个 ACK 集群、50+ SLB 实例,每月 28 万。更扎心的是,AI 分析告诉我:超过六成的钱花在了"不需要"的资源上。闲置的机器在跑、过度分配的 CPU 在浪费、低谷期的 Pod 在空转。

01 先看看云资源浪费有多严重

我负责的阿里云账号下 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 才是解决规模化的出路。

图:云资源成本分析仪表盘,直观展示各服务费用占比和闲置资源分布情况

02 成本优化架构:AI 引擎 + 自动治理

核心思路:指标采集 → AI 分析 → 自动治理,形成完整闭环。

整体架构

成本优化前后对比

维度

优化前

优化后

改善

月度云费

28 万

17.4 万

⬇️ 38%

ECS 平均利用率

18%

52%

⬆️ 189%

闲置资源数

35 台

3 台

⬇️ 91%

弹性响应延迟

10 分钟

2 分钟

⬇️ 80%

03 闲置资源自动检测:把"僵尸"机器揪出来

闲置判定不是简单的"CPU 低就标记",而是多层条件组合:利用率阈值 → 持续时间 → 关联资源检查(SLB 流量)→ 最终判定。

闲置检测决策流程

为什么用 7 天窗口?

单日低利用率可能是业务低谷,7 天持续低利用率才是真正的闲置。

检测脚本实现

代码语言:javascript
复制
#!/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)

检测报告示例

代码语言:javascript
复制
=== 闲置资源检测报告 ===
扫描时间: 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 优化前后的参数差异

04 弹性伸缩策略优化:让 HPA 更"聪明"

为什么不让运维手动调 HPA?120+ 个服务,每个服务的流量模式都不同,人工调参既慢又不准。

HPA 参数 AI 调优

代码语言:javascript
复制
# 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 实例小时

05 三个踩坑实录,每一个都是钱买来的教训

坑 1:闲置检测误判——定时任务被当成闲置

现象:批处理实例仅在凌晨 2:00-4:00 运行,其余时间 CPU 接近 0,被标记为闲置并通知释放。

原因:检测逻辑只看整体均值,没有考虑定时任务的特殊调度模式。

解决:增加"定时任务白名单"机制,标注了 schedule-job=true 的实例跳过闲置检测。

提醒:不是所有低利用率实例都是"闲置",要区分"不用"和"按需使用"。

坑 2:HPA 缩容过快导致请求排队

现象:流量从高峰回落后,HPA 在 1 分钟内缩容 50%,剩余 Pod 无法承载残余流量。

原因:默认缩容策略没有稳定窗口,stabilizationWindowSeconds 设为 0。

解决:设置缩容稳定窗口为 5 分钟,且单次缩容比例不超过 25%:

代码语言:javascript
复制
behavior:
  scaleDown:
    stabilizationWindowSeconds: 300
    policies:
      - type: Percent
        value: 25
        periodSeconds: 60

提醒:扩容要快、缩容要慢,这是弹性伸缩的基本原则。

坑 3:预留实例推荐忽略了业务增长

现象:AI 推荐将 20 台按量付费 ECS 转为包年包月,但下季度业务扩张需要新增 15 台,规格可能变化。

原因:预留实例推荐只基于历史用量,没有纳入业务增长预测。

解决:预留实例推荐加入"增长因子",只推荐当前用量 70% 的包年包月,留出弹性空间:

代码语言:javascript
复制
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)

提醒:包年包月是"锁价"也是"锁量",弹性需求大的场景要谨慎。

06 配套监控:持续看护优化效果

AI 成本优化不是一次性的,需要持续监控优化效果,避免误回收导致服务受影响。

监控项

采集方式

更新间隔

告警阈值

严重级别

月度云费用增长率

云账单 API

86400s

> 上月 10%

P1

闲置资源误回收

用户投诉 + 日志

3600s

任何误回收

P0

弹性伸缩频次

HPA 指标

300s

> 10 次/小时

P2

资源利用率

Prometheus

300s

< 20% 持续 7 天

P2

包年包月 vs 按量比例

云账单 API

86400s

按量 > 40%

P3

07 总结:谁适合做云成本优化?

AI 成本优化的核心价值:

  • 月度云费:从 28 万 → 17.4 万(⬇️ 38%)
  • 资源利用率:从 18% → 52%(⬆️ 189%)
  • 闲置资源:从 35 台 → 3 台(⬇️ 91%)

适合谁用:云资源规模大(50+ 实例)、费用持续增长、缺乏成本治理流程的团队

不适合谁用:资源规模小(< 20 实例)、业务强关联无法缩容、合规要求固定资源

💬 你的团队每月云费多少?有没有做过成本优化?评论区聊聊~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-07-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 行者架构谈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 01 先看看云资源浪费有多严重
  • 02 成本优化架构:AI 引擎 + 自动治理
    • 整体架构
    • 成本优化前后对比
  • 03 闲置资源自动检测:把"僵尸"机器揪出来
    • 闲置检测决策流程
    • 为什么用 7 天窗口?
    • 检测脚本实现
    • 检测报告示例
  • 04 弹性伸缩策略优化:让 HPA 更"聪明"
    • HPA 参数 AI 调优
    • 伸缩效果对比
  • 05 三个踩坑实录,每一个都是钱买来的教训
    • 坑 1:闲置检测误判——定时任务被当成闲置
    • 坑 2:HPA 缩容过快导致请求排队
    • 坑 3:预留实例推荐忽略了业务增长
  • 06 配套监控:持续看护优化效果
  • 07 总结:谁适合做云成本优化?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档