Hotdry.
ai-engineering

使用 AWS Lambda 和 Cost Explorer API 实现成本异常自动化修复管道

面向 AWS 成本异常,给出 Lambda 自动化修复管道的实现与参数配置。

在 AWS 云环境中,成本异常往往源于资源误配置,如闲置的 EC2 实例和未附加的 EBS 卷。这些资源虽未被有效利用,却持续产生计费,导致账单峰值突然飙升。根据 AWS 官方数据,优化此类闲置资源可节省高达 30% 的月度支出。本文聚焦于构建自动化修复管道,利用 Cost Explorer API 检测异常,并通过 Lambda 函数执行修复操作,实现高效的成本治理。

问题分析:成本异常的常见成因

AWS 账单峰值多源于运维疏忽引发的资源浪费。闲置 EC2 实例指那些 CPU 利用率长期低于 10% 或处于 stopped 状态的计算资源,它们虽不消耗计算费用,但关联的 EBS 卷仍按容量计费。未附加 EBS 卷则处于 available 状态,未挂载到任何实例,却每月按 GB 收取存储费。举例而言,一个 100 GB 的未附加 gp3 卷在 us-east-1 区域每月约 10 美元,若账户中有数十个此类卷,累积成本可达数百美元。

证据显示,Gartner 报告指出,73% 的企业云支出超标,主要因闲置资源未及时清理。AWS Cost Explorer 可通过历史数据分析,识别 EC2 和 EBS 服务下的异常增长,例如当月 EBS 存储费用较上月增加 50% 时触发警报。这类异常往往不是业务增长所致,而是配置遗漏的结果,如开发环境实例终止后 EBS 未删除。

解决方案架构:自动化检测与修复

核心架构采用事件驱动模式:CloudWatch Events 定时触发 Lambda 函数,函数先调用 Cost Explorer API 查询近期成本数据,若检测到异常(如 EBS 费用峰值),则切换到 EC2 API 执行修复。整个管道无需人工干预,支持 dry_run 模式测试,确保安全。

关键组件包括:

  • Cost Explorer API:用于成本查询和异常检测,支持按服务、时间粒度过滤。
  • Lambda 函数:Python 运行时,集成 boto3 SDK 执行资源扫描和操作。
  • SNS 通知:修复前后发送报告,便于审计。
  • CloudWatch Logs:记录执行日志,支持告警。

此架构的优势在于可扩展性强,可轻松集成到现有 CI/CD 流程中。相比手动审查,它将响应时间从几天缩短至分钟级。

实现步骤:从检测到修复

1. Cost Explorer 异常检测

首先,配置 Lambda 函数调用 get_cost_and_usage API,查询过去 7 天的 EBS 和 EC2 成本。设置阈值:若 EBS 费用超过预算 20%,视为异常。

示例代码片段(boto3):

import boto3
from datetime import datetime, timedelta

ce = boto3.client('ce')
end_date = datetime.now()
start_date = end_date - timedelta(days=7)
response = ce.get_cost_and_usage(
    TimePeriod={'Start': start_date.strftime('%Y-%m-%d'), 'End': end_date.strftime('%Y-%m-%d')},
    Granularity='DAILY',
    Metrics=['UnblendedCost'],
    GroupBy=[{'Type': 'DIMENSION', 'Key': 'SERVICE'}]
)
ebs_cost = next((group['Metrics']['UnblendedCost']['Amount'] for group in response['ResultsByTime'][0]['Groups'] if group['Keys'][0] == 'Amazon Elastic Block Store'), 0)
if float(ebs_cost) > 50:  # 阈值示例
    # 触发修复
    pass

此查询返回每日成本,按服务分组,便于 pinpoint 峰值来源。“AWS Cost Explorer 提供细粒度账单分析,支持预算告警。”(引用自 AWS 文档)

2. Lambda 修复脚本:清理闲置资源

检测到异常后,函数扫描 EC2 实例和 EBS 卷。

  • 闲置 EC2:查询 describe_instances,过滤 CPUUtilization < 10% 的 running 实例,或 stopped 实例超过 14 天。使用 stop_instances API 停止它们。
  • 未附加 EBS:查询 describe_volumes,过滤 State='available' 且 CreateTime > retention_days 的卷。先 create_snapshot 备份,然后 delete_volume。

完整脚本逻辑:

def cleanup_resources(region, retention_days=14, dry_run=True):
    ec2 = boto3.client('ec2', region_name=region)
    
    # 清理未附加 EBS
    volumes = ec2.describe_volumes(Filters=[{'Name': 'status', 'Values': ['available']}])['Volumes']
    for vol in volumes:
        create_time = vol['CreateTime']
        if (datetime.now(vol['CreateTime'].tzinfo) - create_time).days > retention_days:
            # 检查豁免标签
            if any(tag['Key'] == 'DoNotDelete' and tag['Value'] == 'true' for tag in vol.get('Tags', [])):
                continue
            if not dry_run:
                snapshot = ec2.create_snapshot(VolumeId=vol['VolumeId'], Description=f"Auto-backup {vol['VolumeId']}")
                ec2.delete_volume(VolumeId=vol['VolumeId'])
                print(f"Deleted {vol['VolumeId']}")
            else:
                print(f"[DRY_RUN] Would delete {vol['VolumeId']}")
    
    # 清理闲置 EC2
    instances = ec2.describe_instances(Filters=[{'Name': 'instance-state-name', 'Values': ['running']}])['Reservations']
    for res in instances:
        for inst in res['Instances']:
            # 假设通过 CloudWatch 获取低利用率(简化)
            if inst.get('CpuUtilization', 0) < 10:  # 伪代码,实际需 Metrics
                if not dry_run:
                    ec2.stop_instances(InstanceIds=[inst['InstanceId']])
                print(f"Stopped {inst['InstanceId']}")

部署时,将此函数设置为 EventBridge 规则触发,每日执行一次。

3. IAM 权限配置

为 Lambda 角色授予最小权限:

  • ce:GetCostAndUsage
  • ec2:DescribeVolumes, ec2:DescribeInstances, ec2:CreateSnapshot, ec2:DeleteVolume, ec2:StopInstances
  • sns:Publish

使用 IAM Policy Simulator 测试,避免过度授权。

可落地参数与清单

参数配置

  • Retention Days:EBS 保留期 7-30 天,建议 14 天平衡数据恢复与成本。
  • Utilization Threshold:EC2 CPU < 10%,内存 < 20%,基于 Compute Optimizer 推荐。
  • Dry Run:初始 7 天启用,观察日志无误后关闭。
  • Timeout:Lambda 15 分钟,处理大账户分批(每批 50 资源)。
  • Region:多区域账户,函数参数化 region。

部署清单

  1. 创建 Lambda 函数,上传代码包(包含 boto3,无需额外层)。
  2. 配置 EventBridge 规则:cron (0 2 * * ? *) 每日凌晨 2 点。
  3. 设置 SNS Topic,订阅管理员邮箱。
  4. 启用 CloudWatch Alarm:若修复卷数 > 10,触发通知。
  5. 测试:手动调用 Lambda,验证 dry_run 输出。
  6. 监控:Dashboard 显示月节省 = ∑(删除卷大小 × $0.10/GB-month × 剩余月)。

回滚策略

  • 快照保留 30 天,手动恢复若误删。
  • 标签豁免:关键卷加 DoNotDelete=true。
  • 分阶段:先通知不删除,确认后自动化。

风险控制与最佳实践

主要风险是误操作导致数据丢失,故始终备份。限额方面,EC2 API 调用上限 40/sec,Lambda 可添加重试逻辑(boto3 retry config)。最佳实践包括:

  • 集成 Trusted Advisor,每周审查补充。
  • 使用 Savings Plans 覆盖剩余 EC2 负载。
  • 定期审计:每月 Cost Explorer 报告验证节省。

通过此管道,企业可实现 20-50% EBS 成本降低,具体取决于资源规模。

监控与扩展

部署后,监控 Lambda 指标:Invocations、Errors、Duration。扩展可添加 RDS 闲置检查,或集成 Budgets API 预预算警报。未来,可用 ML(如 SageMaker)预测峰值。

总之,此自动化管道将成本治理从被动转为主动,确保 AWS 支出高效可控。

资料来源

  • AWS 官方文档:Cost Explorer API 和 EC2 API 参考。
  • CSDN 博客:AWS EBS 未挂载资源识别与清理方案(2025-10-30)。

(正文字数约 1250 字)

查看归档