You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Terraform更新AWS ASG实例类型触发服务downtime如何解决

问题根因

你当前配置出现服务downtime的核心原因有两个:

  1. 给aws_autoscaling_group配置create_before_destroy = true会触发Terraform层面的全量资源重建:Terraform会先创建一个全新的ASG,再触发旧ASG销毁,旧ASG销毁时会立即把绑定的实例从Target Group摘流,完全不管新ASG的实例有没有通过健康检查;你设置的360秒deregistration_delay只会等旧实例存量请求处理完,不会等待新实例就绪。
  2. 没有启用ASG原生的滚动更新/实例刷新能力,Terraform的资源生命周期逻辑和AWS的ASG流量调度逻辑完全脱节,无法控制新老实例的替换节奏。

核心配置调整方案

1. 修正ASG配置,用原生实例刷新替代Terraform层面的资源重建

移除ASG资源上错误配置的create_before_destroy规则,开启ASG原生滚动更新,保证替换过程中始终有足额健康实例承接流量:

resource "aws_autoscaling_group" "app_asg" {
  # 保留原有基础配置:vpc可用区、min_size、max_size、target_group_arns等
  min_size                  = 2
  max_size                  = 4
  vpc_zone_identifier       = var.subnet_ids
  target_group_arns         = [aws_lb_target_group.app_tg.arn]

  launch_template {
    id      = aws_launch_template.app_lt.id
    version = "$Latest" # 不写死版本,启动模板更新后自动触发版本迭代
  }

  # 健康检查宽限期,需大于应用启动+通过ALB健康检查的总时长,留足冗余
  health_check_grace_period = 300
  # 终止策略优先淘汰最旧实例,避免误杀刚上线的新实例
  termination_policies      = ["OldestInstance"]
  # 对接ALB健康检查,不用EC2默认的虚拟机状态检查
  health_check_type         = "ELB"

  # 开启原生滚动实例刷新
  instance_refresh {
    strategy = "Rolling"
    preferences {
      # 滚动过程中始终保持100%期望容量的健康实例,不会提前终止旧实例
      min_healthy_percentage = 100
      # 新实例启动后的预热等待时长,和grace period保持一致
      instance_warmup        = 300
      # 已经匹配最新配置的实例不重复替换
      skip_matching          = true
    }
    # 启动模板变更时自动触发实例刷新
    triggers = ["launch_template"]
  }

  lifecycle {
    # 原有配置保留,避免伸缩活动调整的实例数被Terraform覆盖
    ignore_changes = [desired_capacity]
    # 必须删除此处原有的create_before_destroy = true配置
  }
}

2. 优化Target Group健康检查与流量调度规则

保留原有360秒注销延迟配置,补充健康检查阈值、慢启动配置,避免新实例刚启动就被打满流量、或者未就绪就被切入流量:

resource "aws_lb_target_group" "app_tg" {
  # 保留原有基础配置:端口、协议、VPC等
  port                 = 80
  protocol             = "HTTP"
  vpc_id               = var.vpc_id
  # 原有360秒注销延迟保留,足够等待旧实例存量请求处理完成
  deregistration_delay = 360
  # 开启慢启动,新实例注册后180秒内线性增长流量,避免突发流量打垮未预热完成的实例
  slow_start           = 180

  health_check {
    protocol            = "HTTP"
    # 注意:该接口必须等应用完成初始化、依赖连接全部建立、可正常处理业务请求时才返回200,不能用虚拟机存活类接口
    path                = "/health"
    matcher             = "200"
    interval            = 30
    timeout             = 5
    # 连续2次检查成功才判定为健康,连续2次失败才判定为异常,避免偶发抖动误判
    healthy_threshold   = 2
    unhealthy_threshold = 2
  }
}

3. 调整启动模板生命周期规则

仅在启动模板层面保留create_before_destroy,保证新模板版本创建完成后再触发ASG滚动更新,不会出现模板版本空窗:

resource "aws_launch_template" "app_lt" {
  name_prefix   = "app-lt-"
  image_id      = var.app_ami_id
  instance_type = var.instance_type
  # 保留原有配置:安全组、IAM角色、用户数据、存储配置等

  lifecycle {
    create_before_destroy = true
  }
}

验证步骤
  1. 配置修改完成后先执行terraform plan,确认输出中不会触发ASG资源的删除重建,仅会更新ASG的实例刷新配置、新增/修改启动模板版本
  2. 首次apply完成基础配置更新后,尝试修改instance_type参数再次执行apply,到AWS控制台ASG的「实例刷新」页面观察进度:整个流程会先启动新实例,等新实例通过ALB健康检查、完成预热后,再逐台终止旧实例,Target Group中始终存在足额健康实例
  3. 滚动更新过程中持续发起业务请求,验证无5xx错误、无连接中断。

常见踩坑说明
  • 禁止给aws_autoscaling_group资源配置create_before_destroy,该规则会绕开ASG原生滚动逻辑,触发新旧ASG全量替换,必然出现流量空窗
  • min_healthy_percentage不能设置为低于100,否则ASG会在更新时先终止旧实例再启动新实例,导致容量不足
  • 健康检查接口必须真实反映应用就绪状态,禁止用TCP检查、根路径默认200这类无法判断业务可用性的检查规则,否则新实例未就绪就会被切入流量。

内容的提问来源于stack exchange,提问作者Daniele

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 12:27:08