武汉勇远科技
勇远科技微信二维码
微信咨询
扫一扫获取方案
24小时服务热线
177 6259 3139

企业云成本治理:编写AWS Boto3脚本自动清理闲置EBS存储卷

1. 背景与企业痛点

当企业把业务全部搬上云(如 AWS, 阿里云)后,工程师们最常说的一句话是:“先开台机器跑跑看”。久而久之,企业往往面临巨大的云账单刺客
1. 云盘孤岛:EC2 实例被终止(Terminate)时,如果创建时未勾选“随实例删除(Delete on termination)”,其挂载的 EBS 云盘就会沦为孤立状态(Available 而非 In-use)。这些无主云盘每个月仍在按 GB 持续扣费。
2. 人工巡检困难:面对数以千计的云资源标签,靠人工去控制台找闲置资源无异于大海捞针,财务与运维部门经常相互推诿扯皮。

本文将演示如何利用 Python 结合 AWS SDK (Boto3),编写一个可集成在 AWS Lambda 或日常定时任务中的运维脚本,精准识别、过滤白名单,并自动销毁超过保留期限的孤儿 EBS 卷。

2. 脚本开发准备

首先,内网运维服务器需要配置 AWS 凭证,并安装 boto3

pip install boto3
aws configure
# 输入你的 AWS Access Key ID 和 Secret Access Key

3. 编写自动清理 Python 脚本

此脚本的核心逻辑如下:
1. 遍历特定 Region 下所有状态为 available(即闲置未挂载)的 EBS 卷。
2. 过滤掉包含特定标签(如 Retain=True 或打上了“核心备份”标签)的卷。
3. 执行删除操作(支持 Dry Run 试运行机制防误删)。

创建一个 cleanup_ebs.py 文件:

#!/usr/bin/env python3
import boto3
import logging
from botocore.exceptions import ClientError

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# 初始化 EC2 客户端 (指定要巡检的区域)
ec2 = boto3.client('ec2', region_name='ap-northeast-1')

def get_unattached_volumes():
    """获取所有状态为 'available' 的闲置 EBS 卷"""
    unattached_vols = []
    try:
        # 使用过滤器在云端直接过滤,提升效率
        response = ec2.describe_volumes(
            Filters=[{'Name': 'status', 'Values': ['available']}]
        )
        volumes = response.get('Volumes', [])
        for vol in volumes:
            vol_id = vol['VolumeId']
            size = vol['Size']
            tags = vol.get('Tags', [])

            # 安全白名单校验逻辑
            retain = False
            for tag in tags:
                # 如果业务侧打上了无需删除的保护标签,跳过
                if tag['Key'] == 'Protection' and tag['Value'] == 'Retain':
                    retain = True
                    break

            if not retain:
                unattached_vols.append({'id': vol_id, 'size': size})

    except ClientError as e:
        logging.error(f"无法获取卷列表: {e}")
    return unattached_vols

def delete_volumes(volumes, dry_run=True):
    """执行删除逻辑"""
    if not volumes:
        logging.info("太棒了!本区域未发现闲置云盘。")
        return

    total_saved_gb = sum(vol['size'] for vol in volumes)
    logging.info(f"发现 {len(volumes)} 块闲置云盘,总计浪费空间 {total_saved_gb} GB。")

    for vol in volumes:
        vol_id = vol['id']
        if dry_run:
            logging.info(f"[Dry Run - 测试模式] 模拟删除卷: {vol_id} (Size: {vol['size']} GB)")
        else:
            try:
                logging.warning(f"正在永久销毁闲置卷: {vol_id} ...")
                ec2.delete_volume(VolumeId=vol_id)
                logging.info(f"卷 {vol_id} 销毁成功。")
            except ClientError as e:
                logging.error(f"卷 {vol_id} 删除失败: {e}")

if __name__ == "__main__":
    # 步骤1:获取闲置列表
    vols_to_delete = get_unattached_volumes()

    # 步骤2:执行删除。强烈建议第一次跑的时候把 dry_run 设为 True
    # 确认日志列表没问题后,再将 dry_run 改为 False 执行真正的斩首行动
    delete_volumes(vols_to_delete, dry_run=True)

4. 进阶:如何集成与执行

你可以将上述脚本包装成 AWS Lambda 函数,利用 EventBridge (原 CloudWatch Events) 设定一个 cron 表达式(如每周日凌晨 2 点执行):
cron(0 18 ? * SUN *) (UTC 时间)

并在执行前后加上对钉钉/企业微信 Webhook 的调用,将清理出来的存储量和“本周为公司节省的账单金额”推送给技术总监群里,极大提升运维部门的价值感知。

5. 总结

“ FinOps (云财务运营) ”正在成为当代运维不可或缺的核心技能。技术人不能只懂造轮子,更要懂拆轮子。通过简单的几行 Python 与 Boto3 脚本,我们把枯燥的资源巡检变成了防漏水的水龙头,杜绝企业的预算流失。将代码思维引入财务管控,这就是 IT 运维在企业降本增效大潮下的核心壁垒。