如何配置ASG待EC2、ELB健康检查均通过后再向CloudFormation上报成功
实际触发原因
CloudFormation对ASG的创建完成判定,从设计上就不等待ELB健康检查的最终结果:
- 默认判定规则只有两个硬条件:ASG的实例数达到
MinSize要求、所有实例处于InService状态,满足就直接把资源标记为CREATE_COMPLETE - 结合ASG的默认健康规则:所有实例启动后初始状态直接算健康,只要没收到来自EC2或ELB的不健康通知,就一直保持健康状态。所以哪怕ELB的健康检查还没跑、从来没判定过实例合格,只要还没发不健康通知,实例就会被算成
InService,触发CF提前结束创建流程 - 你配置的
HealthCheckType: ELB只影响ASG后续的实例替换、扩缩容逻辑,完全不会改动CF的创建完成判定阈值,这是AWS的原生设计,不属于配置错误。
实现目标的配置方法
要让CF等所有实例都实际通过双维度健康检查再判定成功,需要用CF的原生创建信号机制替换默认的宽松判定逻辑,不需要额外加第三方工具:
1. 给ASG资源增加CreationPolicy块
直接在原有ASG定义下追加创建策略,要求必须收到指定数量的实例成功上报信号,才允许把ASG标记为创建完成:
MyAppScalingGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: # 保留你原来的全部配置项即可,不需要改动原有逻辑 AutoScalingGroupName: !Ref InstanceName CapacityRebalance: true HealthCheckGracePeriod: 300 HealthCheckType: ELB LaunchTemplate: LaunchTemplateId: !Ref MyAppLaunchTemplate Version: !GetAtt MyAppLaunchTemplate.DefaultVersionNumber MaxSize: !Ref MaxInstances MinSize: !Ref MinInstances TargetGroupARNs: [ !Ref MyAppTargetGroup ] VPCZoneIdentifier: !Split [ ",", !Ref Subnets ] # 新增创建策略 CreationPolicy: ResourceSignal: # 要求收到的成功上报数完全等于ASG的最小实例数 Count: !Ref MinInstances # 超时时间要比健康检查宽限期长,预留足够的健康检查判定窗口 Timeout: PT10M
2. 调整启动模板的用户数据逻辑
要让实例发出来的信号真的代表“已经通过ELB健康检查”,必须把发信号的时机放在两个条件都满足之后:一是本地应用已经能正常响应健康检查请求,二是预留了足够的时间让ELB完成首次健康检查判定。以Linux系统为例,在user data最后追加对应逻辑:
# 等待本地应用就绪,可根据实际的健康检查接口地址调整 until curl -f http://localhost/health; do sleep 5; done # 等待和HealthCheckGracePeriod匹配的时长,确保ELB已经完成至少一次健康检查判定 sleep 300 # 向CloudFormation上报创建成功信号 /opt/aws/bin/cfn-signal -e $? \ --stack ${AWS::StackName} \ --resource MyAppScalingGroup \ --region ${AWS::Region}
实际配置时需要避开的坑
ResourceSignal.Count必须和ASG的MinSize值完全一致,要是信号数量和要求不匹配,CF会一直卡在CREATE_IN_PROGRESS状态,直到超时判定栈创建失败- 千万不要在实例刚启动、应用还没就绪的时候就发CF信号,不然等于回到原来的问题:CF提前判定创建完成,ASG后续才发现ELB检查不通过,开始循环替换实例
- 你现在设置的
HealthCheckType: ELB已经满足双维度健康检查的要求:这个模式下ASG会同时接收EC2的实例状态、ELB的健康结果来判定实例健康度,不需要额外叠加EC2的健康检查类型 - 别指望靠ASG本身的健康状态等CF完成判定:ASG的健康状态是持续异步更新的,CF不会等健康检查达到稳态才返回结果,必须靠实例主动上报信号来同步状态
内容的提问来源于stack exchange,提问作者chaserb
相关产品推荐
相关产品推荐

