关于 aws-cost-cleanup
aws-cost-cleanup 是用于发现和清理闲置 AWS 资源的自动化技能,适合需要检查云资源浪费的运维人员。它覆盖存储、计算和网络资源,并强调先只读发现、试运行和验证,再执行删除。
主要功能
- 01发现多类闲置 AWS 资源
- 02生成潜在成本影响报告
- 03提供清理脚本和 Lambda 示例
- 04按发现、验证、执行和核验组织流程
- 05包含删除前安全检查
适用场景
- 01查找未挂载的 EBS 卷并评估清理
- 02清理过期快照和未完成的 S3 上传
- 03检查闲置 EC2、弹性 IP 和网络资源
- 04规划跨 AWS 账户的资源检查
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill aws-cost-cleanup安装后在 Claude Code 中输入/aws-cost-cleanup确认已加载。
详细介绍
AWS 成本清理
自动识别并移除未使用的 AWS 资源,消除浪费。
何时使用此技能
需要自动清理未使用的 AWS 资源以降低成本、消除浪费时,请使用此技能。
自动清理目标
存储
- 未挂载的 EBS 卷
- 过期的 EBS 快照(>90 天)
- 未完成的 S3 分段上传
- 已启用版本控制的存储桶中的旧 S3 版本
计算
- 已停止的 EC2 实例(>30 天)
- 未使用的 AMI 及其关联快照
- 未使用的弹性 IP
网络
- 未使用的弹性负载均衡器
- 未使用的 NAT 网关
- 孤立的 ENI
清理脚本
安全清理(先进行试运行)
#!/bin/bash
# cleanup-unused-ebs.sh
echo "Finding unattached EBS volumes..."
VOLUMES=$(aws ec2 describe-volumes \
--filters Name=status,Values=available \
--query 'Volumes[*].VolumeId' \
--output text)
for vol in $VOLUMES; do
echo "Would delete: $vol"
# Uncomment to actually delete:
# aws ec2 delete-volume --volume-id $vol
done
#!/bin/bash
# cleanup-old-snapshots.sh
CUTOFF_DATE=$(date -d '90 days ago' --iso-8601)
aws ec2 describe-snapshots --owner-ids self \
--query "Snapshots[?StartTime<='$CUTOFF_DATE'].[SnapshotId,StartTime,VolumeSize]" \
--output text | while read snap_id start_time size; do
echo "Snapshot: $snap_id (Created: $start_time, Size: ${size}GB)"
# Uncomment to delete:
# aws ec2 delete-snapshot --snapshot-id $snap_id
done
#!/bin/bash
# release-unused-eips.sh
aws ec2 describe-addresses \
--query 'Addresses[?AssociationId==null].[AllocationId,PublicIp]' \
--output text | while read alloc_id public_ip; do
echo "Would release: $public_ip ($alloc_id)"
# Uncomment to release:
# aws ec2 release-address --allocation-id $alloc_id
done
S3 生命周期自动化
# Prepare a lifecycle proposal. This replaces bucket lifecycle configuration;
# retrieve/merge existing rules and scope the prefix before any authorized apply.
cat > lifecycle-policy.json <<EOF
{
"Rules": [
{
"Id": "Archive old objects",
"Status": "Enabled",
"Transitions": [
{
"Days": 90,
"StorageClass": "STANDARD_IA"
},
{
"Days": 180,
"StorageClass": "GLACIER"
}
],
"NoncurrentVersionExpiration": {
"NoncurrentDays": 30
},
"AbortIncompleteMultipartUpload": {
"DaysAfterInitiation": 7
}
}
]
}
EOF
# After explicit review only, apply the merged policy to the confirmed bucket.
成本影响计算器
#!/usr/bin/env python3
# calculate-savings.py
import boto3
from datetime import datetime, timedelta
ec2 = boto3.client('ec2')
# Calculate EBS volume savings
volumes = ec2.describe_volumes(
Filters=[{'Name': 'status', 'Values': ['available']}]
)
total_size = sum(v['Size'] for v in volumes['Volumes'])
monthly_cost = total_size * 0.10 # illustrative input, not a verified gp3 rate
print(f"Unattached EBS Volumes: {len(volumes['Volumes'])}")
print(f"Total Size: {total_size} GB")
print(f"Monthly Savings: ${monthly_cost:.2f}")
# Calculate Elastic IP savings
addresses = ec2.describe_addresses()
unused = [a for a in addresses['Addresses'] if 'AssociationId' not in a]
eip_cost = len(unused) * 3.65 # $0.005/hour * 730 hours
print(f"\nUnused Elastic IPs: {len(unused)}")
print(f"Monthly Savings: ${eip_cost:.2f}")
print(f"\nTotal Monthly Savings: ${monthly_cost + eip_cost:.2f}")
print(f"Annual Savings: ${(monthly_cost + eip_cost) * 12:.2f}")
自动清理 Lambda
import boto3
from datetime import datetime, timedelta
def lambda_handler(event, context):
ec2 = boto3.client('ec2')
# Discover candidates only; creation age is not detachment age.
volumes = ec2.describe_volumes(
Filters=[{'Name': 'status', 'Values': ['available']}]
)
cutoff = datetime.now() - timedelta(days=7)
deleted = 0
for vol in volumes['Volumes']:
create_time = vol['CreateTime'].replace(tzinfo=None)
if create_time < cutoff:
try:
print(f"Candidate only (not deleted): {vol['VolumeId']}")
except Exception as e:
print(f"Error deleting {vol['VolumeId']}: {e}")
return {
'statusCode': 200,
'body': 'Dry run only; no volumes deleted'
}
清理工作流
-
发现阶段(只读)
- 运行所有 describe 命令
- 生成成本影响报告
- 与团队审核
-
验证阶段
- 确认资源确实未被使用
- 检查依赖关系
- 通知资源所有者
-
执行阶段(先进行试运行)
- 以试运行模式运行清理脚本
- 审核拟议的变更
- 执行实际清理
-
验证阶段
- 确认资源已删除
- 监控是否出现问题
- 记录节省的成本
安全检查清单
- 先以试运行模式运行
- 确认资源没有依赖项
- 检查资源标签以确认所有权
- 删除前通知相关方
- 为关键数据创建快照
- 先在非生产环境中测试
- 准备好回滚计划
- 记录所有删除操作
示例提示词
发现
- “查找所有未使用的资源并计算潜在节省金额”
- “为我的 AWS 账户生成清理报告”
- “哪些资源可以安全删除?”
执行
- “创建一个清理未挂载 EBS 卷的脚本”
- “删除所有超过 90 天的快照”
- “释放未使用的弹性 IP”
自动化
- “为旧快照设置自动清理”
- “创建用于每周清理的 Lambda 函数”
- “安排每月资源清理”
与 AWS Organizations 集成
# Run cleanup across multiple accounts
for account in $(aws organizations list-accounts \
--query 'Accounts[*].Id' --output text); do
echo "Checking account: $account"
aws ec2 describe-volumes \
--filters Name=status,Values=available \
--profile account-$account
done
监控和提醒
# Create CloudWatch alarm for cost anomalies
aws cloudwatch put-metric-alarm \
--alarm-name high-cost-alert \
--alarm-description "Alert when daily cost exceeds threshold" \
--metric-name EstimatedCharges \
--namespace AWS/Billing \
--statistic Maximum \
--period 86400 \
--evaluation-periods 1 \
--threshold 100 \
--comparison-operator GreaterThanThreshold
最佳实践
- 在维护时段安排清理
- 删除前始终创建最终快照
- 使用资源标签识别待清理对象
- 为生产环境实施审批工作流
- 记录所有清理操作以供审计
- 设置成本异常检测
- 每周审核清理结果
风险缓解
中风险操作:
- 删除未挂载的卷(确保没有计划重新挂载)
- 移除旧快照(确认没有合规要求)
- 释放弹性 IP(检查 DNS 记录)
始终做到:
- 保留 30 天备份
- 对关键资源使用 AWS Backup
- 测试恢复流程
- 记录清理决策
Kiro CLI 集成
# Analyze and cleanup in one command
kiro-cli chat "Use aws-cost-cleanup to find and remove unused resources"
# Generate cleanup script
kiro-cli chat "Create a safe cleanup script for my AWS account"
# Schedule automated cleanup
kiro-cli chat "Set up weekly automated cleanup using aws-cost-cleanup"
更多资源
限制
- 仅当任务明确符合上述范围时,才使用此技能。
- 不要将输出视为针对特定环境进行验证、测试或专家审核的替代方案。
- 如果缺少必要的输入、权限、安全边界或成功标准,请停止并请求澄清。
未附加、已停止或较旧的资源仍可能是必需的恢复资产。删除前,应确认账户/区域、所有权、明确的候选 ID、依赖项检查、保留要求以及经过测试的备份/恢复计划。创建时间无法表明卷从何时起不再使用。默认保留试运行;单独获批的执行操作必须重新检查状态/标签和 IAM 范围。在预期的各个区域内分页发现资源,使用当前区域/类型/IOPS/吞吐量/IPv4 定价,并区分预估可避免成本与实际已实现的账单节省额。GNU date -d 在 macOS 上不可移植。
评论
支持 Markdown