aws-cost-cleanup

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

AWS Cost Cleanup

AWS成本清理

Automate the identification and removal of unused AWS resources to eliminate waste.
自动识别并移除未使用的AWS资源,消除资源浪费。

When to Use This Skill

何时使用该技能

Use this skill when you need to automatically clean up unused AWS resources to reduce costs and eliminate waste.
当你需要自动清理未使用的AWS资源以降低成本、减少浪费时,可以使用该技能。

Automated Cleanup Targets

自动清理目标

Storage
  • Unattached EBS volumes
  • Old EBS snapshots (>90 days)
  • Incomplete multipart S3 uploads
  • Old S3 versions in versioned buckets
Compute
  • Stopped EC2 instances (>30 days)
  • Unused AMIs and associated snapshots
  • Unused Elastic IPs
Networking
  • Unused Elastic Load Balancers
  • Unused NAT Gateways
  • Orphaned ENIs
存储
  • 未挂载的EBS卷
  • 超过90天的旧EBS快照
  • S3未完成的分片上传任务
  • 版本控制存储桶中的旧S3版本
计算
  • 已停止超过30天的EC2实例
  • 未使用的AMI及关联快照
  • 未使用的弹性IP
网络
  • 未使用的弹性负载均衡器
  • 未使用的NAT网关
  • 孤立的弹性网卡(ENI)

Cleanup Scripts

清理脚本

Safe Cleanup (Dry-Run First)

安全清理(先执行Dry-Run)

bash
#!/bin/bash
bash
#!/bin/bash

cleanup-unused-ebs.sh

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

```bash
#!/bin/bash
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

```bash
#!/bin/bash

cleanup-old-snapshots.sh

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

```bash
#!/bin/bash
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

```bash
#!/bin/bash

release-unused-eips.sh

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
undefined
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
undefined

S3 Lifecycle Automation

S3生命周期自动化

bash
undefined
bash
undefined

Apply lifecycle policy to transition old objects to cheaper storage

Apply lifecycle policy to transition old objects to cheaper storage

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
aws s3api put-bucket-lifecycle-configuration
--bucket my-bucket
--lifecycle-configuration file://lifecycle-policy.json
undefined
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
aws s3api put-bucket-lifecycle-configuration
--bucket my-bucket
--lifecycle-configuration file://lifecycle-policy.json
undefined

Cost Impact Calculator

成本影响计算器

python
#!/usr/bin/env python3
python
#!/usr/bin/env python3

calculate-savings.py

calculate-savings.py

import boto3 from datetime import datetime, timedelta
ec2 = boto3.client('ec2')
import boto3 from datetime import datetime, timedelta
ec2 = boto3.client('ec2')

Calculate EBS volume savings

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 # $0.10/GB-month for gp3
print(f"Unattached EBS Volumes: {len(volumes['Volumes'])}") print(f"Total Size: {total_size} GB") print(f"Monthly Savings: ${monthly_cost:.2f}")
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 # $0.10/GB-month for gp3
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

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}")
undefined
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}")
undefined

Automated Cleanup Lambda

自动清理Lambda函数

python
import boto3
from datetime import datetime, timedelta

def lambda_handler(event, context):
    ec2 = boto3.client('ec2')
    
    # Delete unattached volumes older than 7 days
    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:
                ec2.delete_volume(VolumeId=vol['VolumeId'])
                deleted += 1
                print(f"Deleted volume: {vol['VolumeId']}")
            except Exception as e:
                print(f"Error deleting {vol['VolumeId']}: {e}")
    
    return {
        'statusCode': 200,
        'body': f'Deleted {deleted} volumes'
    }
python
import boto3
from datetime import datetime, timedelta

def lambda_handler(event, context):
    ec2 = boto3.client('ec2')
    
    # Delete unattached volumes older than 7 days
    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:
                ec2.delete_volume(VolumeId=vol['VolumeId'])
                deleted += 1
                print(f"Deleted volume: {vol['VolumeId']}")
            except Exception as e:
                print(f"Error deleting {vol['VolumeId']}: {e}")
    
    return {
        'statusCode': 200,
        'body': f'Deleted {deleted} volumes'
    }

Cleanup Workflow

清理工作流

  1. Discovery Phase (Read-only)
    • Run all describe commands
    • Generate cost impact report
    • Review with team
  2. Validation Phase
    • Verify resources are truly unused
    • Check for dependencies
    • Notify resource owners
  3. Execution Phase (Dry-run first)
    • Run cleanup scripts with dry-run
    • Review proposed changes
    • Execute actual cleanup
  4. Verification Phase
    • Confirm deletions
    • Monitor for issues
    • Document savings
  1. 发现阶段(只读)
    • 运行所有查询命令
    • 生成成本影响报告
    • 与团队共同评审
  2. 验证阶段
    • 确认资源确实未被使用
    • 检查依赖关系
    • 通知资源所有者
  3. 执行阶段(先Dry-Run)
    • 试运行清理脚本
    • 评审拟执行的变更
    • 执行实际清理操作
  4. 核验阶段
    • 确认删除操作完成
    • 监控是否出现问题
    • 记录节省的成本

Safety Checklist

安全检查清单

  • Run in dry-run mode first
  • Verify resources have no dependencies
  • Check resource tags for ownership
  • Notify stakeholders before deletion
  • Create snapshots of critical data
  • Test in non-production first
  • Have rollback plan ready
  • Document all deletions
  • 先运行Dry-Run模式
  • 确认资源没有依赖
  • 检查资源标签确认归属
  • 删除前通知相关干系人
  • 为关键数据创建快照
  • 先在非生产环境测试
  • 准备好回滚方案
  • 记录所有删除操作

Example Prompts

示例提示词

Discovery
  • "Find all unused resources and calculate potential savings"
  • "Generate a cleanup report for my AWS account"
  • "What resources can I safely delete?"
Execution
  • "Create a script to cleanup unattached EBS volumes"
  • "Delete all snapshots older than 90 days"
  • "Release unused Elastic IPs"
Automation
  • "Set up automated cleanup for old snapshots"
  • "Create a Lambda function for weekly cleanup"
  • "Schedule monthly resource cleanup"
发现类
  • "查找所有未使用的资源并计算可节省的成本"
  • "为我的AWS账户生成一份清理报告"
  • "哪些资源我可以安全删除?"
执行类
  • "创建一个清理未挂载EBS卷的脚本"
  • "删除所有超过90天的快照"
  • "释放未使用的弹性IP"
自动化类
  • "为旧快照配置自动清理机制"
  • "创建一个每周执行清理的Lambda函数"
  • "调度每月一次的资源清理任务"

Integration with AWS Organizations

与AWS Organizations集成

bash
undefined
bash
undefined

Run cleanup across multiple accounts

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
undefined
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
undefined

Monitoring and Alerts

监控与告警

bash
undefined
bash
undefined

Create CloudWatch alarm for cost anomalies

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
undefined
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
undefined

Best Practices

最佳实践

  • Schedule cleanup during maintenance windows
  • Always create final snapshots before deletion
  • Use resource tags to identify cleanup candidates
  • Implement approval workflow for production
  • Log all cleanup actions for audit
  • Set up cost anomaly detection
  • Review cleanup results weekly
  • 在维护窗口内调度清理任务
  • 删除前务必创建最终快照
  • 使用资源标签识别可清理的候选资源
  • 生产环境实现审批工作流
  • 记录所有清理操作用于审计
  • 配置成本异常检测
  • 每周评审清理结果

Risk Mitigation

风险缓解

Medium Risk Actions:
  • Deleting unattached volumes (ensure no planned reattachment)
  • Removing old snapshots (verify no compliance requirements)
  • Releasing Elastic IPs (check DNS records)
Always:
  • Maintain 30-day backup retention
  • Use AWS Backup for critical resources
  • Test restore procedures
  • Document cleanup decisions
中风险操作:
  • 删除未挂载的卷(确认没有计划重新挂载)
  • 移除旧快照(确认没有合规保留要求)
  • 释放弹性IP(检查DNS记录)
通用要求:
  • 保留30天的备份周期
  • 对关键资源使用AWS Backup
  • 测试恢复流程
  • 记录清理决策

Kiro CLI Integration

Kiro CLI集成

bash
undefined
bash
undefined

Analyze and cleanup in one command

Analyze and cleanup in one command

kiro-cli chat "Use aws-cost-cleanup to find and remove unused resources"
kiro-cli chat "Use aws-cost-cleanup to find and remove unused resources"

Generate cleanup script

Generate cleanup script

kiro-cli chat "Create a safe cleanup script for my AWS account"
kiro-cli chat "Create a safe cleanup script for my AWS account"

Schedule automated cleanup

Schedule automated cleanup

kiro-cli chat "Set up weekly automated cleanup using aws-cost-cleanup"
undefined
kiro-cli chat "Set up weekly automated cleanup using aws-cost-cleanup"
undefined

Additional Resources

额外资源