Terraform AWS Auto Scaling 自动扩缩容完整详解

这是AWS云原生架构的核心组件,彻底解决了手动管理服务器的痛点。通过自动扩缩容,你的应用可以根据流量自动调整服务器数量:流量高峰时自动增加实例保证性能,流量低谷时自动减少实例节省成本。这是所有生产级Web应用的必备功能。

一、核心价值:为什么需要自动扩缩容?

手动管理服务器的痛点

  • 流量突增时,手动加机器来不及,导致服务宕机
  • 流量低谷时,大量服务器闲置,浪费成本
  • 服务器故障时,需要手动重启或重建,恢复时间长
  • 无法应对不可预测的流量波动

Auto Scaling 的核心能力

自动扩容:CPU/内存/网络使用率高时,自动增加实例
自动缩容:使用率低时,自动减少实例,节省成本
自动自愈:实例故障时,自动终止并创建新实例替换
多可用区部署:自动将实例分布在多个可用区,提高可用性
零人工干预:所有操作完全自动化,不需要SSH登录


二、整体架构与核心概念

核心组件关系图

CloudWatch 监控
    ↓
指标达到阈值 → 触发告警 → 执行扩缩容策略
                                  ↓
                            Auto Scaling Group (ASG)
                                  ↓
                            Launch Configuration
                                  ↓
                        自动创建/终止 EC2 实例

核心概念澄清

  1. Launch Configuration(启动配置)

    • 是创建EC2实例的模板
    • 定义了实例的所有属性:AMI、实例类型、SSH密钥、安全组、User Data等
    • 不可变:一旦创建就不能修改,修改后会创建新的启动配置
  2. Auto Scaling Group(自动扩展组)

    • 是Auto Scaling的核心
    • 定义了实例的数量范围、部署位置、健康检查方式等
    • 根据扩缩容策略自动调整实例数量
    • 自动将实例分布在多个可用区,实现高可用
  3. Auto Scaling Policy(扩缩容策略)

    • 定义了如何调整实例数量
    • 支持多种调整方式:增加固定数量、减少固定数量、调整到指定数量、按百分比调整
  4. CloudWatch Alarm(云监控告警)

    • 监控EC2实例的各种指标(CPU、内存、网络等)
    • 当指标达到阈值时,触发告警
    • 告警会执行对应的扩缩容策略

三、核心代码逐行解析

1. autoscaling.tf(启动配置 + 自动扩展组)

1.1 Launch Configuration(启动配置)
resource "aws_launch_configuration" "example-launchconfig" {
  name_prefix     = "example-launchconfig"  # 名称前缀,自动生成唯一名称
  image_id        = var.AMIS[var.AWS_REGION]  # AMI镜像
  instance_type   = "t2.micro"  # 实例规格
  key_name        = aws_key_pair.mykeypair.key_name  # SSH密钥
  security_groups = [aws_security_group.allow-ssh.id]  # 安全组
}

关键说明

  • name_prefix:强烈推荐使用name_prefix而不是name。因为Launch Configuration是不可变的,当你修改任何参数时,Terraform会创建一个新的Launch Configuration并删除旧的。使用name_prefix可以自动生成唯一的名称,避免命名冲突。
  • 这里可以添加user_data参数,结合上一章节的CloudInit,实现实例启动时自动部署应用。
1.2 Auto Scaling Group(自动扩展组)
resource "aws_autoscaling_group" "example-autoscaling" {
  name                      = "example-autoscaling"
  vpc_zone_identifier       = [aws_subnet.main-public-1.id, aws_subnet.main-public-2.id]
  launch_configuration      = aws_launch_configuration.example-launchconfig.name
  min_size                  = 1  # 最小实例数
  max_size                  = 2  # 最大实例数
  desired_capacity          = 1  # 期望实例数(可选,默认等于min_size)
  health_check_grace_period = 300  # 健康检查宽限期(秒)
  health_check_type         = "EC2"  # 健康检查类型
  force_delete              = true  # 强制删除(测试环境用,生产环境不要开)

  tag {
    key                 = "Name"
    value               = "ec2 instance"
    propagate_at_launch = true  # 自动将标签传播到新创建的实例
  }
}

关键参数详解

参数说明生产环境建议
vpc_zone_identifier实例部署的子网列表必须指定至少2个不同可用区的子网,实现高可用
min_size自动扩展组维护的最小实例数根据业务最低需求设置
max_size自动扩展组允许的最大实例数设置合理的上限,避免成本失控
desired_capacity期望实例数不指定时默认等于min_size
health_check_grace_period实例启动后,多久开始进行健康检查给应用足够的启动时间,一般设置为300-600秒
health_check_type健康检查类型生产环境建议使用ELB(负载均衡器健康检查),比EC2更准确
force_delete删除自动扩展组时,是否强制终止所有实例生产环境必须设为false,防止误删
propagate_at_launch是否将标签传播到新创建的实例设为true,方便管理和计费

三个数量参数的区别

  • min_size:底线,无论如何都不能低于这个数量
  • max_size:上限,无论如何都不能高于这个数量
  • desired_capacity:当前期望的数量,扩缩容就是调整这个值

2. autoscalingpolicy.tf(扩缩容策略 + CloudWatch告警)

2.1 扩容策略与告警
# 扩容策略:增加1个实例
resource "aws_autoscaling_policy" "example-cpu-policy" {
  name                   = "example-cpu-policy"
  autoscaling_group_name = aws_autoscaling_group.example-autoscaling.name
  adjustment_type        = "ChangeInCapacity"  # 调整类型:增加/减少固定数量
  scaling_adjustment     = "1"  # 增加1个实例
  cooldown               = "300"  # 冷却期:300秒(5分钟)
  policy_type            = "SimpleScaling"  # 策略类型:简单扩展策略
}

# CloudWatch告警:CPU使用率>=30%持续4分钟,触发扩容
resource "aws_cloudwatch_metric_alarm" "example-cpu-alarm" {
  alarm_name          = "example-cpu-alarm"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  evaluation_periods  = "2"  # 连续2个周期
  metric_name         = "CPUUtilization"  # 监控指标:CPU使用率
  namespace           = "AWS/EC2"  # 指标命名空间
  period              = "120"  # 每个周期120秒(2分钟)
  statistic           = "Average"  # 统计方式:平均值
  threshold           = "30"  # 阈值:30%

  # 监控哪个自动扩展组的指标
  dimensions = {
    "AutoScalingGroupName" = aws_autoscaling_group.example-autoscaling.name
  }

  actions_enabled = true
  alarm_actions   = [aws_autoscaling_policy.example-cpu-policy.arn]  # 触发时执行的策略
}
2.2 缩容策略与告警
# 缩容策略:减少1个实例
resource "aws_autoscaling_policy" "example-cpu-policy-scaledown" {
  name                   = "example-cpu-policy-scaledown"
  autoscaling_group_name = aws_autoscaling_group.example-autoscaling.name
  adjustment_type        = "ChangeInCapacity"
  scaling_adjustment     = "-1"  # 减少1个实例
  cooldown               = "300"  # 冷却期:5分钟
  policy_type            = "SimpleScaling"
}

# CloudWatch告警:CPU使用率<=5%持续4分钟,触发缩容
resource "aws_cloudwatch_metric_alarm" "example-cpu-alarm-scaledown" {
  alarm_name          = "example-cpu-alarm-scaledown"
  comparison_operator = "LessThanOrEqualToThreshold"
  evaluation_periods  = "2"
  metric_name         = "CPUUtilization"
  namespace           = "AWS/EC2"
  period              = "120"
  statistic           = "Average"
  threshold           = "5"  # 阈值:5%

  dimensions = {
    "AutoScalingGroupName" = aws_autoscaling_group.example-autoscaling.name
  }

  actions_enabled = true
  alarm_actions   = [aws_autoscaling_policy.example-cpu-policy-scaledown.arn]
}

关键参数详解

  • adjustment_type:调整类型,支持三种:
    • ChangeInCapacity:增加/减少固定数量的实例
    • ExactCapacity:调整到指定数量的实例
    • PercentChangeInCapacity:按百分比增加/减少实例
  • cooldown:冷却期。扩缩容操作完成后,在冷却期内不会再执行任何扩缩容操作。作用是避免频繁扩缩容,给系统足够的时间稳定下来。
  • period:每个数据点的时间间隔,单位秒。
  • evaluation_periods:连续多少个周期达到阈值才触发告警。
  • Demo中阈值设置得很低(30%扩容,5%缩容)是为了方便测试,生产环境建议设置为:
    • 扩容阈值:CPU使用率>=70-80%
    • 缩容阈值:CPU使用率<=20-30%

四、完整工作流程

Auto Scaling Group 启动
    ↓
创建 min_size 个实例,分布在多个可用区
    ↓
CloudWatch 持续监控所有实例的平均 CPU 使用率
    ↓
┌─────────────────────────────────────────────────┐
│ CPU >= 30% 持续 4 分钟                          │
│   ↓                                             │
│ 触发扩容告警                                    │
│   ↓                                             │
│ 执行扩容策略,增加 1 个实例                     │
│   ↓                                             │
│ 进入 5 分钟冷却期,期间不执行任何扩缩容操作     │
└─────────────────────────────────────────────────┘
    ↓
┌─────────────────────────────────────────────────┐
│ CPU <= 5% 持续 4 分钟                           │
│   ↓                                             │
│ 触发缩容告警                                    │
│   ↓                                             │
│ 执行缩容策略,减少 1 个实例                     │
│   ↓                                             │
│ 进入 5 分钟冷却期,期间不执行任何扩缩容操作     │
└─────────────────────────────────────────────────┘
    ↓
循环监控

自动自愈流程

  • Auto Scaling 会定期检查所有实例的健康状态
  • 如果发现某个实例不健康(如系统崩溃、网络不通)
  • 会自动终止该实例,并创建一个新的实例替换它
  • 整个过程完全自动,不需要人工干预

五、完整部署与测试步骤

1. 准备工作

# 生成SSH密钥对
ssh-keygen -t rsa -b 2048 -f mykey -N ""

2. 部署所有资源

cd demo-12-autoscaling
terraform init
terraform plan
terraform apply

3. 查看自动扩展组和实例

# 查看自动扩展组详情
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names example-autoscaling

# 查看当前运行的实例
aws ec2 describe-instances --filters "Name=tag:Name,Values=ec2 instance"

4. 测试自动扩容

# SSH登录到其中一个实例
ssh -i mykey ubuntu@<实例公网IP>

# 安装stress工具,压测CPU
sudo apt update && sudo apt install -y stress

# 启动4个进程,每个进程占用100%CPU
stress -c 4

现在等待4-5分钟,CloudWatch会检测到CPU使用率超过30%,触发扩容,自动创建第二个实例。

5. 测试自动缩容

# 在实例中按Ctrl+C停止stress工具

等待4-5分钟,CPU使用率会降到5%以下,触发缩容,自动终止一个实例,回到1个实例的状态。

6. 查看扩缩容活动历史

aws autoscaling describe-scaling-activities --auto-scaling-group-name example-autoscaling

六、生产环境最佳实践

1. 使用 Launch Template 代替 Launch Configuration

Launch Configuration 已经被 AWS 标记为**遗留(legacy)**功能,推荐使用 Launch Template 代替:

  • 支持版本管理,可以回滚到之前的版本
  • 支持更多高级功能:混合实例类型、竞价实例、专用主机等
  • 可以在不替换整个自动扩展组的情况下更新启动模板

2. 高可用改进

  • 跨至少3个可用区部署:提高容错能力
  • 使用 ELB 健康检查:比 EC2 健康检查更准确,可以检测应用层的健康状态
  • 启用实例保护:防止重要的实例被缩容终止

3. 扩缩容策略改进

  • 使用目标跟踪扩展策略(Target Tracking Scaling) 代替简单扩展策略:
    • 更智能,自动调整实例数量,将指标维持在目标值附近
    • 不需要手动配置扩容和缩容两个策略
    • 示例:将平均CPU使用率维持在70%
  • 配置计划扩展:应对已知的流量高峰(如促销活动)
  • 配置预测扩展:AWS会根据历史流量预测未来的需求,提前扩容

4. 成本优化

  • 使用混合实例策略:结合按需实例和竞价实例,大幅降低成本
  • 合理设置缩容阈值:不要过于激进,避免频繁缩容
  • 使用合适的实例规格:根据应用的CPU/内存需求选择合适的实例类型

5. 安全改进

  • 不要给实例公网IP:将实例放在私网子网,通过NAT网关上网
  • 使用最小权限原则:给实例分配具有最小权限的IAM角色
  • 配置安全组:只开放必要的端口

6. 运维改进

  • 配置通知:扩缩容时发送邮件或短信通知
  • 启用 CloudWatch 详细监控:收集1分钟粒度的指标数据
  • 配置生命周期钩子:在实例启动和终止时执行自定义操作(如注册到服务发现、注销负载均衡器)

七、常见坑点与排错

  1. 实例创建失败但Auto Scaling不报错

    • 查看自动扩展组的活动历史:aws autoscaling describe-scaling-activities
    • 常见原因:AMI不存在、实例规格不足、安全组不存在、子网没有足够的IP地址
  2. 健康检查太严格导致实例频繁被终止

    • 调大health_check_grace_period,给应用足够的启动时间
    • 使用ELB健康检查代替EC2健康检查
  3. 冷却期设置不合理导致频繁扩缩容

    • 冷却期太短:会导致频繁扩缩容,系统不稳定
    • 冷却期太长:无法及时响应流量变化
    • 一般设置为300-600秒比较合适
  4. CloudWatch告警不触发

    • 检查dimensions是否正确,特别是AutoScalingGroupName
    • 检查指标是否有数据:aws cloudwatch get-metric-statistics
    • 检查periodevaluation_periods的设置
  5. 缩容时终止了错误的实例

    • 配置终止策略:默认是先终止最旧的实例
    • 可以配置为终止最接近下一个计费小时的实例,节省成本
    • 对重要实例启用实例保护

八、下一步进阶方向

掌握了基础的Auto Scaling后,你可以继续学习以下内容,组成完整的高可用Web应用架构:

  1. ALB应用负载均衡器:将流量分发到多个实例,实现负载均衡和HTTPS
  2. 目标跟踪扩展策略:更智能的扩缩容方式
  3. 计划扩展和预测扩展:应对已知和未知的流量高峰
  4. 混合实例策略:结合按需实例和竞价实例,大幅降低成本
  5. 生命周期钩子:在实例启动和终止时执行自定义操作
  6. 蓝绿部署和滚动更新:实现应用的无停机更新

更多推荐