获取近30天CPU<2%、网络IO<5Mb的AWS EC2闲置低利用率实例列表
获取低利用率AWS EC2实例列表及成本管控方案
一、前提准备
- 已配置AWS CLI并拥有权限:
ec2:DescribeInstances、cloudwatch:GetMetricStatistics、ec2:TerminateInstances(终止实例时需后者) - 确认CloudWatch已开启EC2指标自动收集(默认开启)
二、Shell脚本自动筛选(推荐)
以下脚本会遍历所有EC2实例,查询近30天的平均CPU利用率和网络I/O,输出符合条件的实例,可选自动终止:
#!/bin/bash # 定义时间范围与阈值 START_TIME=$(date -u -d "30 days ago" +"%Y-%m-%dT%H:%M:%SZ") END_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") CPU_THRESHOLD=2.0 # CPU利用率阈值(百分比) NETWORK_THRESHOLD=5.0 # 网络I/O阈值(MB) # 获取所有EC2实例ID INSTANCE_IDS=$(aws ec2 describe-instances --query 'Reservations[*].Instances[*].InstanceId' --output text) echo "正在筛选符合条件的实例..." echo "----------------------------------------" for INSTANCE_ID in $INSTANCE_IDS; do # 查询平均CPU利用率 CPU_USAGE=$(aws cloudwatch get-metric-statistics \ --namespace AWS/EC2 \ --metric-name CPUUtilization \ --dimensions Name=InstanceId,Value=$INSTANCE_ID \ --start-time $START_TIME \ --end-time $END_TIME \ --period 86400 \ --statistics Average \ --query 'Datapoints[*].Average' --output text | awk '{sum+=$1} END {print sum/NR}') # 跳过运行不足30天、无指标数据的实例 if [ -z "$CPU_USAGE" ]; then continue fi # 查询平均网络入站/出站流量,转换为MB NETWORK_IN=$(aws cloudwatch get-metric-statistics \ --namespace AWS/EC2 \ --metric-name NetworkIn \ --dimensions Name=InstanceId,Value=$INSTANCE_ID \ --start-time $START_TIME \ --end-time $END_TIME \ --period 86400 \ --statistics Average \ --query 'Datapoints[*].Average' --output text | awk '{sum+=$1} END {print sum/NR}') NETWORK_OUT=$(aws cloudwatch get-metric-statistics \ --namespace AWS/EC2 \ --metric-name NetworkOut \ --dimensions Name=InstanceId,Value=$INSTANCE_ID \ --start-time $START_TIME \ --end-time $END_TIME \ --period 86400 \ --statistics Average \ --query 'Datapoints[*].Average' --output text | awk '{sum+=$1} END {print sum/NR}') TOTAL_NETWORK_MB=$(echo "($NETWORK_IN + $NETWORK_OUT)/1048576" | bc -l) # 匹配阈值则输出实例信息 if (( $(echo "$CPU_USAGE < $CPU_THRESHOLD" | bc -l) )) && (( $(echo "$TOTAL_NETWORK_MB < $NETWORK_THRESHOLD" | bc -l) )); then echo "符合条件实例:$INSTANCE_ID" echo "平均CPU利用率:${CPU_USAGE}%,平均网络I/O:${TOTAL_NETWORK_MB}MB" echo "----------------------------------------" # 如需自动终止,取消注释以下一行 # aws ec2 terminate-instances --instance-ids $INSTANCE_ID fi done
脚本使用步骤
- 保存为
find-idle-ec2.sh,赋予执行权限:chmod +x find-idle-ec2.sh - 运行脚本:
./find-idle-ec2.sh - 确认输出的实例无业务负载后,可取消脚本中终止命令的注释,再次运行完成批量终止
三、AWS CLI快速筛选(需jq工具)
适用于快速获取符合条件的实例ID列表:
# 获取CPU利用率低于2%的实例ID CPU_IDLE_INSTANCES=$(aws cloudwatch get-metric-data --metric-data-queries '[{ "Id": "cpu", "MetricStat": { "Metric": { "Namespace": "AWS/EC2", "MetricName": "CPUUtilization", "Dimensions": [{ "Name": "InstanceId" }] }, "Period": 86400, "Stat": "Average" }, "ReturnData": true }]' --start-time $(date -u -d "30 days ago" +"%Y-%m-%dT%H:%M:%SZ") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") --query 'MetricDataResults[*].Values' --output json | jq -r '.[] | select(.[0] < 2) | .[]') # 获取网络I/O低于5MB的实例ID NETWORK_IDLE_INSTANCES=$(aws cloudwatch get-metric-data --metric-data-queries '[{ "Id": "netin", "MetricStat": { "Metric": { "Namespace": "AWS/EC2", "MetricName": "NetworkIn", "Dimensions": [{ "Name": "InstanceId" }] }, "Period": 86400, "Stat": "Average" }, "ReturnData": true }, { "Id": "netout", "MetricStat": { "Metric": { "Namespace": "AWS/EC2", "MetricName": "NetworkOut", "Dimensions": [{ "Name": "InstanceId" }] }, "Period": 86400, "Stat": "Average" }, "ReturnData": true }]' --start-time $(date -u -d "30 days ago" +"%Y-%m-%dT%H:%M:%SZ") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") --query 'MetricDataResults[*].Values' --output json | jq -r '.[] | add / 1048576 | select(. < 5) | .[]') # 取两个列表的交集(同时符合双条件的实例) comm -12 <(echo "$CPU_IDLE_INSTANCES" | sort) <(echo "$NETWORK_IDLE_INSTANCES" | sort)
四、控制台手动操作指引
- 打开CloudWatch控制台,进入「指标」→「EC2」→「按实例ID」
- 添加
CPUUtilization、NetworkIn、NetworkOut三个指标,设置时间范围为「过去30天」 - 切换图表为「平均值」视图,筛选出CPU平均低于2%、网络总流量(In+Out)平均低于5MB的实例
- 记录实例ID,打开EC2控制台,选中目标实例后点击「终止实例」
五、注意事项
- 终止实例前务必确认实例无业务负载,建议先创建磁盘快照备份数据
- 脚本会自动跳过运行不足30天的实例,可根据需求调整
START_TIME参数 - 跨账号批量操作需提前配置AWS Organizations跨账号权限
内容的提问来源于stack exchange,提问作者SriNivas
相关产品推荐
相关产品推荐

