Terraform更新AWS ASG实例类型触发服务downtime如何解决
问题根因
你当前配置出现服务downtime的核心原因有两个:
- 给
aws_autoscaling_group配置create_before_destroy = true会触发Terraform层面的全量资源重建:Terraform会先创建一个全新的ASG,再触发旧ASG销毁,旧ASG销毁时会立即把绑定的实例从Target Group摘流,完全不管新ASG的实例有没有通过健康检查;你设置的360秒deregistration_delay只会等旧实例存量请求处理完,不会等待新实例就绪。 - 没有启用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 } }
验证步骤
- 配置修改完成后先执行
terraform plan,确认输出中不会触发ASG资源的删除重建,仅会更新ASG的实例刷新配置、新增/修改启动模板版本 - 首次apply完成基础配置更新后,尝试修改
instance_type参数再次执行apply,到AWS控制台ASG的「实例刷新」页面观察进度:整个流程会先启动新实例,等新实例通过ALB健康检查、完成预热后,再逐台终止旧实例,Target Group中始终存在足额健康实例 - 滚动更新过程中持续发起业务请求,验证无5xx错误、无连接中断。
常见踩坑说明
- 禁止给
aws_autoscaling_group资源配置create_before_destroy,该规则会绕开ASG原生滚动逻辑,触发新旧ASG全量替换,必然出现流量空窗 min_healthy_percentage不能设置为低于100,否则ASG会在更新时先终止旧实例再启动新实例,导致容量不足- 健康检查接口必须真实反映应用就绪状态,禁止用TCP检查、根路径默认200这类无法判断业务可用性的检查规则,否则新实例未就绪就会被切入流量。
内容的提问来源于stack exchange,提问作者Daniele
相关产品推荐
相关产品推荐

