mcpField
A
aws-cost-optimization

aws-cost-optimization

github.com/bagelhole云与 DevOps1.2k320 次安装23 周前更新
代码仓库

关于 aws-cost-optimization

面向 AWS 工作负载团队的 FinOps 技能,提供支出分析、资源规格调整、承诺折扣、告警和清理方面的实践流程,并附 AWS CLI 与 Terraform 示例。

主要功能

  1. 01按服务和标签分析支出
  2. 02调整计算与存储规格
  3. 03比较 Savings Plans 与 RIs
  4. 04配置预算和告警
  5. 05查找未使用资源

适用场景

  1. 01排查 AWS 账单意外增长
  2. 02负载测试后审查资源规格
  3. 03设置预算和成本异常告警
  4. 04清理未挂载卷和旧快照

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill aws-cost-optimization

安装后在 Claude Code 中输入/aws-cost-optimization确认已加载。

详细介绍

AWS 成本优化

应用实用的 FinOps 管控措施,在不牺牲可靠性或性能的前提下降低 AWS 支出。

适用场景

  • AWS 月度账单意外飙升或超出预算阈值
  • 与工程和财务团队准备成本评审
  • 负载测试后调整 EC2、RDS、EKS 或 Lambda 工作负载的规格
  • 在 Savings Plans、Reserved Instances 和按需定价之间进行选择
  • 设置自动预算提醒和异常检测
  • 清理未使用的资源(未挂载的 EBS、闲置的负载均衡器、旧快照)
  • 优化跨区域和可用区的数据传输成本

前置条件

  • 已安装并配置 AWS CLI v2(aws configure)
  • IAM 权限:ce:*、budgets:*、ec2:Describe*、cloudwatch:PutMetricAlarm、s3:PutLifecycleConfiguration
  • 已在 AWS 账单控制台启用 Cost Explorer(数据填充需要 24 小时)
  • 已在 Billing 控制台激活成本分配标签

成本评审工作流

  1. 为每个资源添加团队、服务、环境和成本中心标签。
  2. 启用 Cost Explorer,并激活将成本和使用情况报告(CUR)导出到 S3。
  3. 按服务、账户和标签找出支出最高的项目。
  4. 根据 CloudWatch 指标调整未充分利用的计算和存储资源规格。
  5. 为稳定的基准用量应用承诺折扣(Savings Plans 或 RIs)。
  6. 设置预算和异常提醒,并构建 KPI 控制面板。
  7. 每月评审并持续优化。

Cost Explorer CLI 命令

# Get cost and usage for the last 30 days grouped by service
aws ce get-cost-and-usage \
  --time-period Start=2026-02-01,End=2026-03-01 \
  --granularity MONTHLY \
  --metrics "BlendedCost" "UnblendedCost" "UsageQuantity" \
  --group-by Type=DIMENSION,Key=SERVICE

# Get cost forecast for the next 30 days
aws ce get-cost-forecast \
  --time-period Start=2026-03-24,End=2026-04-24 \
  --metric UNBLENDED_COST \
  --granularity MONTHLY

# Get cost grouped by a specific tag (e.g., team)
aws ce get-cost-and-usage \
  --time-period Start=2026-02-01,End=2026-03-01 \
  --granularity MONTHLY \
  --metrics "UnblendedCost" \
  --group-by Type=TAG,Key=team

# Get rightsizing recommendations for EC2
aws ce get-rightsizing-recommendation \
  --service "AmazonEC2" \
  --configuration '{"RecommendationTarget":"SAME_INSTANCE_FAMILY","BenefitsConsidered":true}'

# Get Savings Plans purchase recommendation
aws ce get-savings-plans-purchase-recommendation \
  --savings-plans-type COMPUTE_SP \
  --term-in-years ONE_YEAR \
  --payment-option NO_UPFRONT \
  --lookback-period-in-days SIXTY_DAYS

# Get Savings Plans utilization
aws ce get-savings-plans-utilization \
  --time-period Start=2026-02-01,End=2026-03-01 \
  --granularity MONTHLY

# Get Reserved Instance utilization
aws ce get-reservation-utilization \
  --time-period Start=2026-02-01,End=2026-03-01 \
  --granularity MONTHLY

预算提醒

# Create a monthly cost budget with email alert at 80% and 100%
aws budgets create-budget \
  --account-id 123456789012 \
  --budget '{
    "BudgetName": "monthly-total",
    "BudgetLimit": {"Amount": "5000", "Unit": "USD"},
    "TimeUnit": "MONTHLY",
    "BudgetType": "COST",
    "CostFilters": {},
    "CostTypes": {
      "IncludeTax": true,
      "IncludeSubscription": true,
      "UseBlended": false
    }
  }' \
  --notifications-with-subscribers '[
    {
      "Notification": {
        "NotificationType": "ACTUAL",
        "ComparisonOperator": "GREATER_THAN",
        "Threshold": 80,
        "ThresholdType": "PERCENTAGE"
      },
      "Subscribers": [{"SubscriptionType": "EMAIL", "Address": "[email protected]"}]
    },
    {
      "Notification": {
        "NotificationType": "ACTUAL",
        "ComparisonOperator": "GREATER_THAN",
        "Threshold": 100,
        "ThresholdType": "PERCENTAGE"
      },
      "Subscribers": [{"SubscriptionType": "EMAIL", "Address": "[email protected]"}]
    }
  ]'

# List all budgets
aws budgets describe-budgets --account-id 123456789012

# Enable Cost Anomaly Detection monitor for all services
aws ce create-anomaly-monitor \
  --anomaly-monitor '{
    "MonitorName": "all-services",
    "MonitorType": "DIMENSIONAL",
    "MonitorDimension": "SERVICE"
  }'

# Create anomaly subscription (alert when impact > $50)
aws ce create-anomaly-subscription \
  --anomaly-subscription '{
    "SubscriptionName": "cost-alerts",
    "MonitorArnList": ["arn:aws:ce::123456789012:anomalymonitor/monitor-id"],
    "Subscribers": [{"Type": "EMAIL", "Address": "[email protected]"}],
    "Threshold": 50,
    "Frequency": "DAILY"
  }'

CloudWatch 成本告警

# Create alarm for estimated charges exceeding $4000
aws cloudwatch put-metric-alarm \
  --alarm-name "billing-alarm-4000" \
  --alarm-description "Alert when estimated charges exceed $4000" \
  --metric-name EstimatedCharges \
  --namespace AWS/Billing \
  --statistic Maximum \
  --period 21600 \
  --threshold 4000 \
  --comparison-operator GreaterThanThreshold \
  --evaluation-periods 1 \
  --dimensions Name=Currency,Value=USD \
  --alarm-actions "arn:aws:sns:us-east-1:123456789012:billing-alerts" \
  --treat-missing-data notBreaching

查找并清理未使用的资源

# List unattached EBS volumes (wasted storage spend)
aws ec2 describe-volumes \
  --filters Name=status,Values=available \
  --query "Volumes[].{ID:VolumeId,Size:Size,Created:CreateTime}" \
  --output table

# Find old EBS snapshots (older than 90 days)
aws ec2 describe-snapshots \
  --owner-ids self \
  --query "Snapshots[?StartTime<='2025-12-24'].{ID:SnapshotId,Size:VolumeSize,Date:StartTime}" \
  --output table

# List unused Elastic IPs (charged when not associated)
aws ec2 describe-addresses \
  --query "Addresses[?AssociationId==null].{IP:PublicIp,AllocId:AllocationId}" \
  --output table

# Find idle load balancers (zero healthy targets)
aws elbv2 describe-target-health \
  --target-group-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/my-tg/abc123

# List RDS instances and their utilization
aws cloudwatch get-metric-statistics \
  --namespace AWS/RDS \
  --metric-name CPUUtilization \
  --dimensions Name=DBInstanceIdentifier,Value=mydb \
  --start-time 2026-03-17T00:00:00Z \
  --end-time 2026-03-24T00:00:00Z \
  --period 86400 \
  --statistics Average

S3 生命周期成本优化

# Apply tiered lifecycle policy to reduce storage costs
aws s3api put-bucket-lifecycle-configuration \
  --bucket my-data-bucket \
  --lifecycle-configuration '{
    "Rules": [
      {
        "ID": "TierDownOldData",
        "Status": "Enabled",
        "Filter": {"Prefix": ""},
        "Transitions": [
          {"Days": 30, "StorageClass": "STANDARD_IA"},
          {"Days": 90, "StorageClass": "GLACIER"},
          {"Days": 365, "StorageClass": "DEEP_ARCHIVE"}
        ],
        "NoncurrentVersionTransitions": [
          {"NoncurrentDays": 30, "StorageClass": "GLACIER"}
        ],
        "NoncurrentVersionExpiration": {"NoncurrentDays": 90}
      },
      {
        "ID": "CleanupIncompleteUploads",
        "Status": "Enabled",
        "Filter": {"Prefix": ""},
        "AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 7}
      }
    ]
  }'

Terraform 预算和告警示例

resource "aws_budgets_budget" "monthly" {
  name         = "monthly-total"
  budget_type  = "COST"
  limit_amount = "5000"
  limit_unit   = "USD"
  time_unit    = "MONTHLY"

  notification {
    comparison_operator        = "GREATER_THAN"
    threshold                  = 80
    threshold_type             = "PERCENTAGE"
    notification_type          = "ACTUAL"
    subscriber_email_addresses = ["[email protected]"]
  }

  notification {
    comparison_operator        = "GREATER_THAN"
    threshold                  = 100
    threshold_type             = "PERCENTAGE"
    notification_type          = "ACTUAL"
    subscriber_email_addresses = ["[email protected]"]
  }
}

resource "aws_cloudwatch_metric_alarm" "billing" {
  alarm_name          = "billing-alarm-4000"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 1
  metric_name         = "EstimatedCharges"
  namespace           = "AWS/Billing"
  period              = 21600
  statistic           = "Maximum"
  threshold           = 4000
  alarm_description   = "Billing exceeds $4000"
  alarm_actions       = [aws_sns_topic.billing_alerts.arn]

  dimensions = {
    Currency = "USD"
  }
}

安排非生产环境关机

# Stop all dev instances tagged Environment=dev (run via EventBridge + Lambda)
aws ec2 describe-instances \
  --filters "Name=tag:Environment,Values=dev" "Name=instance-state-name,Values=running" \
  --query "Reservations[].Instances[].InstanceId" \
  --output text | xargs -n1 aws ec2 stop-instances --instance-ids

# Scale down dev ECS services to zero at night
aws ecs update-service \
  --cluster dev-cluster \
  --service dev-api \
  --desired-count 0

故障排除

问题原因解决方法
Cost Explorer 返回空数据尚未启用 CE,或启用时间不足 24 小时在 Billing 控制台启用,并等待 24 小时
预算提醒未触发SNS 订阅尚未确认检查电子邮件并确认订阅
规格调整没有建议使用数据不足等待 14 天以收集足够的指标
Savings Plans 利用率低购买过多或工作负载已改变检查并调整 SP 覆盖范围
未挂载的 EBS 未显示查询了错误的区域遍历所有活动区域
账单告警始终未触发账单指标仅在 us-east-1 中提供在 us-east-1 区域创建告警
S3 中缺少 CUR 数据报告未配置或存储桶策略有误在 Billing 控制台验证 CUR 设置
基于标签的成本分配数据为空尚未激活标签在 Billing 中激活成本分配标签

相关技能

  • aws-ec2 - EC2 运维、规格选择和 Spot 实例
  • aws-s3 - S3 存储类别和生命周期管控
  • aws-rds - RDS 实例规格选择和预留实例
  • aws-lambda - Lambda 定价和并发调优
  • terraform-aws - 在 IaC 中将成本防护措施编码

评论

支持 Markdown