自动化巡检脚本:清理未绑定EIP和闲置云盘,降成本

云账号中常出现未绑定的EIP和长期闲置的云盘,每月产生隐性支出。本文分享一套可落地的自动化巡检脚本,定时扫描、推送告警并自动释放,帮助团队将成本控制融入日常运维。

自动化巡检脚本:清理未绑定EIP和闲置云盘,降成本
封面图:ZuCDN · ZuCDN 原创

为什么需要自动化巡检

容易忽略的细节

自动化巡检看似简单,真正落地时却很容易踩坑。弹性公网IP(EIP)按小时计费,即使未绑定任何实例也会持续产生费用;云盘(云硬盘)创建后若不挂载,仍然占用存储容量并计费。中小团队经常遇到“创建后忘记释放”的场景,一次两次可能金额不大,但累积数月后往往是一笔可观的隐性支出。人工排查效率低、容易遗漏,而自动化巡检可以每天定时运行,精准定位闲置资源并触发清理流程。

本文将演示一套基于云厂商API + Shell脚本的自动化巡检方案,覆盖EIP和云盘两种常见浪费场景,并提供完整的脚本示例与调度策略。

设计思路:巡检脚本的核心模块

整套自动化巡检脚本分为三个模块:

  • 资源发现:通过云API获取当前账号下所有EIP和云盘的列表与状态。
  • 闲置判定:根据绑定关系、挂载状态及最近使用时间过滤出闲置资源。
  • 处置动作:发送告警通知(钉钉/企微/邮件)并可选自动释放,或仅生成日报供人工审批。

前置条件

  • 云厂商的AccessKey和SecretKey(建议使用子账号,仅授予Describe/DescribeVolumes/UnbindEIP等最小权限)。
  • Python3环境(用于调用SDK)或直接使用云CLI工具(如阿里云CLI、腾讯云CLI)。
  • 网络连通性:脚本运行服务器能访问云API端点。

脚本实现:识别未绑定EIP

配置前的检查

以阿里云为例,使用阿里云CLI查询所有EIP并过滤已绑定的实例ID。未绑定的EIP的InstanceId字段为空。脚本核心逻辑如下:

#!/bin/bash
# 获取所有EIP
all_eips=$(aliyun vpc DescribeEipAddresses --RegionId cn-hangzhou --PageSize 50 | jq -r '.EipAddresses.EipAddress[]')

# 筛选未绑定的EIP
unbound_eips=$(echo "$all_eips" | jq -r 'select(.InstanceId == null or .InstanceId == "") | .AllocationId')

if [ -n "$unbound_eips" ]; then
    echo "未绑定EIP列表:"
    echo "$unbound_eips"
    # 发送告警到企业微信
    curl -X POST -H "Content-Type: application/json" -d '{"msgtype":"text","text":{"content":"未绑定EIP数量: '$(echo "$unbound_eips" | wc -l)',请及时处理。"}}' "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx"
fi

如果团队允许自动释放,可以在确认通知后追加aliyun vpc ReleaseEipAddress --AllocationId $id。但建议第一次运行时仅通知,待运维人员确认无业务依赖后再开启自动释放开关。

脚本实现:识别闲置云盘

故障定位思路

闲置云盘的判定标准:Status != In_useAttachments数组为空。同时建议增加“创建时间超过7天”的过滤条件,避免刚创建还未挂载的云盘被误清理。

#!/bin/bash
# 获取所有云盘
disks=$(aliyun ecs DescribeDisks --RegionId cn-hangzhou --PageSize 100 | jq -r '.Disks.Disk[]')

# 筛选闲置云盘(未挂载 + 创建超过7天)
idle_disks=$(echo "$disks" | jq -r 'select(.Status != "In_use" and (now - (.CreationTime | fromdate) > 604800)) | .DiskId')

if [ -n "$idle_disks" ]; then
    # 输出到日志并告警
    echo "$(date) 发现闲置云盘: $idle_disks" >> /var/log/cloud_audit.log
    # 调用钉钉机器人
    curl -X POST -H "Content-Type: application/json" -d '{"msgtype":"text","text":{"content":"闲置云盘数量: '$(echo "$idle_disks" | wc -l)',详情见日志。"}}' "https://oapi.dingtalk.com/robot/send?access_token=xxx"
fi

自动化调度:crontab与异常处理与自动化巡检

实际操作要点

将上述两个脚本合并为一个主脚本cleanup_audit.sh,通过crontab每天运行一次:

0 9 * * * /path/to/cleanup_audit.sh >> /var/log/cleanup_audit.log 2>&1

几点注意事项:

  • 日志要保留至少30天,便于回溯。
  • 如果API调用失败(网络超时或配额限制),脚本应输出错误并按静默方式退出,避免重复告警。
  • 对于云盘自动删除,务必先创建快照备份,脚本中可增加aliyun ecs CreateSnapshot --DiskId $id步骤。

成本节省效果估算

实际操作要点

以一个中等规模账号为例,假设有3个未绑定的EIP(每个约0.02元/小时),10个闲置的40GB云盘(每GB约0.007元/小时),每月浪费金额计算:

  • EIP:3 × 0.02 × 24 × 30 = 43.2元/月
  • 云盘:10 × 40 × 0.007 × 24 × 30 = 2016元/月
  • 合计约2059元/月。

而编写这套自动化巡检脚本仅需半天时间,之后长期自动运行——投入产出比非常可观。

扩展:多云环境统一巡检

如果团队同时使用阿里云、腾讯云、AWS,可以改写脚本为多模块,或者使用Terraform、Pulumi的state文件来检测资源状态。更成熟的做法是集成到内部CMDB或运维平台,将巡检结果打上标签,自动生成工单。但核心原理不变:自动化巡检的价值在于持续、无遗漏地发现代价高昂的闲置资源。

常见问题与风险控制

误清理如何避免?

只清理创建时间超过30天的闲置资源;对于云盘,坚持“先快照、后删除”原则;对于EIP,先检查是否存在任何安全组或NAT网关的引用(少数情况下EIP虽未绑定但被配置在NAT中)。

脚本权限过大怎么办?

使用RAM子账号,仅赋予只读+释放/删除权限。禁止赋予创建资源的权限。

告警疲劳如何解决?

如果团队无法及时处理,脚本可以先输出到日志,每周汇总一次发送报表,由运维统一决策。

总结

未绑定的EIP和闲置云盘是云成本中的常见“出血点”。通过自动化巡检脚本,我们可以将人工排查转化为定时、自动的检查与处置流程。本文提供的脚本可以直接复用或根据云厂商调整API参数,关键在于把成本优化从一次性的“大扫除”变为日常运维的固定环节。建议各团队根据自身资源规模设置巡检频率与告警策略,并持续审计效果,真正实现降本增效。

延伸阅读