弹性计算 · EC2

弹性不是「加机器」,是让容量跟着业务曲线走

我们把伸缩策略拆成基线容量、弹性容量与应急容量三层,配合 Spot 混部把单位算力成本压下来。

  • 扩容响应90 秒内新实例进入服务
  • Spot 占比无状态层可达 60%-80%
  • 容量冗余按 p99 峰值 × 1.25 设计

三层容量模型

基线容量

覆盖日常最低负载,用 Savings Plans 或预留实例锁定 1-3 年价格,单价最低。

弹性容量

按目标追踪策略随流量伸缩,优先使用 Spot 实例池,跨 3 个以上实例类型分散中断风险。

应急容量

预置容量储备(Capacity Reservation)或 On-Demand 兜底,只在大促、故障切换时启用。

容量规划四步法

  1. 01

    采集与建模

    拉取 90 天的 RPS、CPU、内存与响应时间数据,识别日内峰谷、周周期和活动尖峰。

    交付物:负载曲线图、峰谷比与增长率、单实例承载能力基线

    3-5 天

  2. 02

    压测定标

    在预生产环境阶梯加压,找到单实例的拐点(p99 开始劣化的并发数),而不是拿 CPU 70% 当上限。

    交付物:单实例容量卡、拐点前的安全水位、扩容阈值建议

    5-8 天

  3. 03

    策略落地

    配置目标追踪 + 预测性伸缩双策略,设置合理的预热时间与冷却窗口,避免抖动。

    交付物:ASG 启动模板、伸缩策略 IaC 代码、混合实例分配策略

    3-5 天

  4. 04

    演练与调优

    做一次 Spot 中断演练和一次流量翻倍演练,验证扩容速度与服务降级链路。

    交付物:演练报告、调优后的阈值、容量应急手册

    2-3 天

混合实例策略示例(Terraform)

hcl asg-mixed-instances.tf
resource "aws_autoscaling_group" "web" {
  name                = "web-asg"
  vpc_zone_identifier = var.private_subnet_ids
  min_size            = 4     # 基线容量,由 Savings Plans 覆盖
  max_size            = 40
  desired_capacity    = 6

  health_check_type         = "ELB"
  health_check_grace_period = 90
  default_instance_warmup   = 60

  mixed_instances_policy {
    instances_distribution {
      # 基线 4 台走按需,超出部分 75% 用 Spot
      on_demand_base_capacity                  = 4
      on_demand_percentage_above_base_capacity = 25
      spot_allocation_strategy                 = "price-capacity-optimized"
      spot_max_price                           = "  # 留空表示不超过按需价
    }

    launch_template {
      launch_template_specification {
        launch_template_id = aws_launch_template.web.id
        version            = "$Latest"
      }
      # 多类型分散中断风险,注意保持相近的 vCPU/内存比
      override { instance_type = "m7i.large" }
      override { instance_type = "m7a.large" }
      override { instance_type = "m6i.large" }
      override { instance_type = "m6a.large" }
      override { instance_type = "m5.large"  }
    }
  }

  # 优雅退出:Spot 中断通知触发连接排空
  capacity_rebalance = true

  tag {
    key                 = "CostCenter"
    value               = "web-frontend"
    propagate_at_launch = true
  }
}

resource "aws_autoscaling_policy" "target_tracking" {
  name                   = "web-req-per-target"
  autoscaling_group_name = aws_autoscaling_group.web.name
  policy_type            = "TargetTrackingScaling"

  target_tracking_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ALBRequestCountPerTarget"
      resource_label         = "${var.alb_arn_suffix}/${var.tg_arn_suffix}"
    }
    target_value = 800   # 由压测拐点反推,而非拍脑袋
  }
}

capacity_rebalance 打开后,AWS 会在 Spot 中断前主动补容量,配合 90 秒预热基本无感。

常见踩坑对照

容易出问题的做法

  • 用 CPU 60% 作为唯一扩容指标,忽略了 IO 或下游数据库瓶颈
  • 冷却时间设成默认 300 秒,尖峰流量还没扩完就已经超时
  • Spot 只挑一种实例类型,容量池枯竭时集体中断
  • 健康检查用 EC2 类型,应用挂了但实例还在,流量继续打进来
  • 缩容不做连接排空,用户请求被硬切断

推荐做法

  • 以 ALBRequestCountPerTarget 或队列深度为主指标,CPU 作为辅助
  • 启动模板内置预热镜像,配合 default_instance_warmup 缩短生效时间
  • 至少 4-5 种同规格实例类型,跨 3 个可用区分散
  • 健康检查用 ELB 类型 + 应用级 /healthz 探针
  • 配置 deregistration_delay 与优雅停机钩子,先摘流量再关机

下一步

把云的复杂度交给我们,你只管做业务

留下需求,沐杉云的解决方案架构师会在一个工作日内联系你,提供免费的现状评估、迁移方案草案与 TCO 测算表。