云成本优化

在不影响 SLO 的前提下识别浪费:右-sizing、自动伸缩、冷数据分层与网络出口;本页提供 AWS Cost Explorer API、Spot 中断处理、Lambda 定时关停与 S3 生命周期策略的可运行代码示例。

SKILL 应要求按资源类型拆解(计算、存储、网络、托管服务),并关联业务标签(团队、环境、产品),避免「一刀切关机器」影响生产。

常见抓手包括:闲置卷与快照、过度预配的 K8s requests、未使用弹性 IP、跨区域复制流量、日志与指标保留期;每项给出验证方法与预期节省区间。

Agent 输出时应区分一次性优化与持续治理(预算告警、异常检测、新资源命名与标签规范),并提醒预留实例 / Savings Plan 的现金流与承诺风险。

成本审查主流程(skill-flow-block)

  [ 按账户 / 标签 / 服务聚合账单与 Top N ]
        │
        ▼
  ┌─────────────┐     闲置:未挂载卷、空集群节点池、僵尸快照
  │  浪费扫描    │──── 过度预配:CPU/内存 P95、K8s request vs 实际
  └─────────────┘
        │
        ▼
  ┌─────────────┐     下一档实例族 / 存储层 / 出口路径;对照 SLO 历史
  │  右-sizing   │──── 变更窗口、回滚与观测对照(P99 延迟、错误率)
  └─────────────┘
        │
        ▼
  ┌─────────────┐     可中断负载 → Spot / 抢占式;混部与容量缓冲
  │ Spot 与弹性 │──── 固定基线 → On-Demand / 包年包月;长期稳定 → RI / SP
  └─────────────┘
        │
        ▼
  ┌─────────────┐     预算、异常、标签规范;工单owner 与合规例外
  │  治理闭环    │──── 一次性节省 vs 持续 FinOps 节奏
  └─────────────┘

右-sizing 与利用率证据

任何降配前须对照 P99 延迟与错误率 历史曲线;SKILL 应写明度量窗口(如 14d/30d)与是否含峰值活动(大促、批处理)。

计算与编排

  • 云主机:平均 / P95 CPU、内存、磁盘吞吐;是否可换 ARM 或更小规格。
  • Kubernetes:request 显著高于实际用量时下调 limit/request 并观察 HPA。
  • 无状态服务优先配合自动伸缩;有状态须评估迁移与复制成本。

存储与网络

  • 对象/块存储:热温冷分层、生命周期规则、重复快照合并。
  • 网络:跨区域/公网出口、NAT、CDN 与直连路径对比账单项。
  • 托管服务:只读副本、Serverless 层、日志与指标保留天数。

云成本分析:AWS Cost Explorer API 示例(Python boto3):

import boto3
import json
from datetime import datetime, timedelta

ce = boto3.client('ce', region_name='us-east-1')

# 按服务聚合最近 30 天费用,找出 Top 开销
def get_cost_by_service(days=30):
    end = datetime.today().strftime('%Y-%m-%d')
    start = (datetime.today() - timedelta(days=days)).strftime('%Y-%m-%d')

    resp = ce.get_cost_and_usage(
        TimePeriod={'Start': start, 'End': end},
        Granularity='MONTHLY',
        Filter={
            'Dimensions': {
                'Key': 'RECORD_TYPE',
                'Values': ['Usage'],
            }
        },
        GroupBy=[{'Type': 'DIMENSION', 'Key': 'SERVICE'}],
        Metrics=['UnblendedCost'],
    )

    results = []
    for group in resp['ResultsByTime'][0]['Groups']:
        service = group['Keys'][0]
        cost = float(group['Metrics']['UnblendedCost']['Amount'])
        results.append({'service': service, 'cost_usd': round(cost, 2)})

    return sorted(results, key=lambda x: x['cost_usd'], reverse=True)

# 按 Tag 分账(按团队/环境分析)
def get_cost_by_tag(tag_key='team', days=30):
    end = datetime.today().strftime('%Y-%m-%d')
    start = (datetime.today() - timedelta(days=days)).strftime('%Y-%m-%d')

    resp = ce.get_cost_and_usage(
        TimePeriod={'Start': start, 'End': end},
        Granularity='MONTHLY',
        GroupBy=[{'Type': 'TAG', 'Key': tag_key}],
        Metrics=['UnblendedCost'],
    )
    return resp['ResultsByTime'][0]['Groups']

if __name__ == '__main__':
    top_services = get_cost_by_service()
    print("Top 5 服务开销:")
    for s in top_services[:5]:
        print(f"  {s['service']}: ${s['cost_usd']}")

Spot / 抢占式与中断容忍

Spot(或各云「抢占式」)适合可重启、可排队、可 checkpoint 的工作负载;SKILL 须要求写明中断时的数据一致性与 SLA 降级策略。

  • 与 On-Demand / RI 混部:基线容量固定,burst 用 Spot 吸收波动。
  • 批处理、渲染、CI 弹性 worker、无本地状态的弹性组为典型候选。
  • 中断通知与优雅退出: draining、作业重试、队列可见性超时对齐。

Spot 实例中断处理代码(Node.js,监听 EC2 元数据服务的中断通知):

// spot-interrupt-handler.js — 监听 EC2 Spot 中断通知并优雅退出
const http = require('http');
const { execSync } = require('child_process');

const METADATA_URL = 'http://169.254.169.254/latest/meta-data/spot/interruption-action';
const CHECK_INTERVAL_MS = 5000;   // 每 5 秒轮询一次

let isShuttingDown = false;

async function checkSpotInterruption() {
  return new Promise((resolve) => {
    const req = http.get(
      { hostname: '169.254.169.254', path: '/latest/meta-data/spot/interruption-action',
        timeout: 2000 },
      (res) => {
        if (res.statusCode === 200) {
          resolve(true);   // 收到中断通知
        } else {
          resolve(false);
        }
      }
    );
    req.on('error', () => resolve(false));
    req.on('timeout', () => { req.destroy(); resolve(false); });
  });
}

async function gracefulShutdown() {
  if (isShuttingDown) return;
  isShuttingDown = true;

  console.log('Spot interruption detected! Starting graceful shutdown...');

  // 1. 停止接收新请求
  server.close();

  // 2. 将当前任务状态保存到 SQS / DynamoDB(checkpoint)
  await saveCheckpoint();

  // 3. 等待正在处理的请求完成(最多 25 秒,中断通知提前 2 分钟)
  await new Promise(resolve => setTimeout(resolve, 25000));

  process.exit(0);
}

// 轮询中断通知
setInterval(async () => {
  if (!isShuttingDown && await checkSpotInterruption()) {
    gracefulShutdown();
  }
}, CHECK_INTERVAL_MS);

// 同时监听 SIGTERM(来自 ECS/K8s draining)
process.on('SIGTERM', gracefulShutdown);

Lambda 定时关停非生产环境(Terraform 配置):

# Lambda 定时关停非生产 RDS / ECS 实例
# terraform/modules/cost-scheduler/main.tf

resource "aws_lambda_function" "stop_nonprod" {
  function_name = "stop-nonprod-resources"
  runtime       = "python3.12"
  handler       = "index.handler"
  role          = aws_iam_role.lambda_exec.arn
  filename      = "${path.module}/stop_nonprod.zip"

  environment {
    variables = {
      RDS_INSTANCES  = "dev-db,staging-db"
      ECS_CLUSTERS   = "dev-cluster,staging-cluster"
      TARGET_ENV_TAG = "non-production"
    }
  }
}

# 工作日晚上 10 点停止(UTC 14:00)
resource "aws_cloudwatch_event_rule" "stop_schedule" {
  name                = "stop-nonprod-nightly"
  schedule_expression = "cron(0 14 ? * MON-FRI *)"  # 周一至周五 UTC 14:00
}

# 工作日早上 8 点启动(UTC 0:00)
resource "aws_cloudwatch_event_rule" "start_schedule" {
  name                = "start-nonprod-morning"
  schedule_expression = "cron(0 0 ? * MON-FRI *)"
}

resource "aws_cloudwatch_event_target" "stop_target" {
  rule = aws_cloudwatch_event_rule.stop_schedule.name
  arn  = aws_lambda_function.stop_nonprod.arn
  input = jsonencode({ action = "stop" })
}

# 预计节省:非生产环境周末 + 工作日 14 小时 ≈ 节省约 65% 的计算成本

持续治理与承诺类采购

  • 与安全和合规冲突时(如必须保留审计日志),优先遵守合规。
  • 预留实例 / Savings Plan:覆盖度、可转让性、现金流与承诺期风险写进输出。
  • 建议附「责任团队 + 预计工单」而非仅数字列表;预算告警与成本异常订阅纳入例行节奏。

S3 生命周期策略配置(热/温/冷分层)与资源标签强制 IAM Policy:

# S3 生命周期策略(Terraform aws_s3_bucket_lifecycle_configuration)
resource "aws_s3_bucket_lifecycle_configuration" "app_logs" {
  bucket = aws_s3_bucket.app_logs.id

  rule {
    id     = "log-tiering"
    status = "Enabled"

    filter {
      prefix = "logs/"
    }

    transition {
      days          = 30
      storage_class = "STANDARD_IA"   # 30 天后转为低频访问(约节省 46%)
    }

    transition {
      days          = 90
      storage_class = "GLACIER_IR"    # 90 天后转为 Glacier Instant(约节省 68%)
    }

    transition {
      days          = 365
      storage_class = "DEEP_ARCHIVE"  # 1 年后转为深层归档(约节省 95%)
    }

    expiration {
      days = 2555   # 7 年后删除(合规要求)
    }

    noncurrent_version_expiration {
      noncurrent_days = 30   # 旧版本 30 天后删除
    }
  }
}

# IAM Policy:强制所有新资源必须有 team 和 environment 标签
resource "aws_iam_policy" "require_tags" {
  name = "RequireResourceTags"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Deny"
      Action = [
        "ec2:RunInstances",
        "rds:CreateDBInstance",
        "elasticloadbalancing:CreateLoadBalancer",
      ]
      Resource = "*"
      Condition = {
        "Null" = {
          "aws:RequestedRegion"              = "false"
          "aws:RequestTag/team"              = "true"   # 必须有 team 标签
          "aws:RequestTag/environment"       = "true"   # 必须有 environment 标签
          "aws:RequestTag/cost-center"       = "true"   # 必须有 cost-center 标签
        }
      }
    }]
  })
}

审查焦点清单生成

勾选本轮审查要覆盖的维度,生成为可粘贴进工单或 SKILL 附录的 Markdown 列表;与上方主流程、右-sizing 与 Spot 章节对齐。

审查维度

未勾选项不会出现在清单中;复制后可在 PR / FinOps 看板中补充具体账号、资源 ID 与负责人。

---
name: cost-optimization
description: 云资源成本分析、Spot 策略、自动调度与存储分层
tags: [finops, aws, cost, cloud]
---
# 成本分析
1. AWS Cost Explorer API:按服务/标签聚合,定位 Top 开销项
2. 分账原则:team + environment + cost-center 三个必填标签
3. 度量窗口:14d/30d,含峰值活动(大促、批处理)再做右-sizing 决策

# 计算优化
4. 右-sizing:对照 P95/P99 CPU/内存利用率,降配前验证 SLO 历史
5. ARM 迁移(Graviton):通常有 20-40% 价格优势,确认依赖兼容性
6. Spot 适用场景:批处理、CI worker、无本地状态的无状态服务
7. Spot 中断处理:监听 EC2 元数据通知(2分钟预警)+ SIGTERM 优雅退出
8. 混部策略:基线 On-Demand/RI,弹性 burst 用 Spot

# 存储优化
9. S3 生命周期:30d→STANDARD_IA,90d→GLACIER_IR,365d→DEEP_ARCHIVE
10. 旧版本 30 天后删除;日志保留 7 年满足合规,年满后删除
11. 闲置扫描:未挂载 EBS 卷、过期快照、未绑定弹性 IP

# 治理与自动化
12. Lambda 定时关停:工作日晚 10 点停非生产,早 8 点启动(节省 65%+)
13. IAM Policy 强制标签:Deny 无 team/environment/cost-center 的资源创建
14. 预算告警:AWS Budgets 按账户/标签设阈值,超 80% 告警
15. RI/Savings Plan:覆盖度 60-70%(稳定基线),不全覆盖保留弹性
16. 与合规冲突时优先合规(审计日志不可随意删除/缩短保留期)

返回技能库 更多技能入口