ECS蓝绿部署用ECSAllAtOnce忽略健康检查问题求解
问题
我有一个采用FARGATE启动类型的ECS服务,使用CodeDeploy执行蓝绿部署。当前遇到的问题:
- 使用
CodeDeployDefault.ECSAllAtOnce部署配置时,新的绿色目标健康状态不会被校验,即便新实例无响应,部署仍会继续并将流量路由至该实例,导致服务异常。 - 使用
CodeDeployDefault.ECSLinear10PercentEvery1Minutes时,健康状态会正常校验,一旦新实例不健康,部署会停止,这符合预期。
需求:实现一次性切换所有实例(类似ECSAllAtOnce的全量切换),同时确保仅在新目标健康时才执行流量切换。
解决方案
要实现全量切换+健康校验,核心是利用蓝绿部署的健康校验机制,配合目标组和CodeDeploy的配置调整,具体步骤如下:
- 保留蓝绿部署模式:你的模板已使用
BLUE_GREEN部署类型和WITH_TRAFFIC_CONTROL选项,这是实现健康校验的基础,无需修改。 - 替换为全量部署配置:直接将
DeploymentConfigName改为CodeDeployDefault.ECSAllAtOnce。 - 确保目标组健康检查配置有效:确认
TargetGroup1和TargetGroup2配置了合理的健康检查规则(如检查路径、响应码、超时时间等),这是CodeDeploy判断目标健康的核心依据。 - 调整部署就绪等待时间:根据服务启动初始化时长,合理设置
DeploymentReadyOption中的WaitTimeInMinutes,确保有足够时间让实例完成健康检查。
修改后的CloudFormation代码片段
EcsService: Type: AWS::ECS::Service DependsOn: - TargetGroup1 - TargetGroup2 Properties: Cluster: !Ref EnvironmentName DeploymentController: Type: CODE_DEPLOY DesiredCount: 1 HealthCheckGracePeriodSeconds: !Ref HealthCheckGracePeriod LaunchType: FARGATE LoadBalancers: - TargetGroupArn: !Ref TargetGroup1 ContainerName: !Ref EnvironmentName ContainerPort: 8080 NetworkConfiguration: AwsvpcConfiguration: Subnets: [ !Ref PrivateSubnet1, !Ref PrivateSubnet2 ] SecurityGroups: [ !Ref ECSHostSecurityGroup ] AssignPublicIp: ENABLED PlatformVersion: LATEST SchedulingStrategy: REPLICA ServiceName: !Ref EnvironmentName TaskDefinition: !Ref TaskDefinition CodeDeployDeploymentGroup: Type: AWS::CodeDeploy::DeploymentGroup DependsOn: EcsService Properties: ApplicationName: !Ref EnvironmentName DeploymentGroupName: !Ref EnvironmentName # 替换为全量部署配置 DeploymentConfigName: CodeDeployDefault.ECSAllAtOnce ServiceRoleArn: !GetAtt EcsRoleForCodeDeploy.Arn DeploymentStyle: DeploymentType: BLUE_GREEN DeploymentOption: WITH_TRAFFIC_CONTROL BlueGreenDeploymentConfiguration: TerminateBlueInstancesOnDeploymentSuccess: Action: TERMINATE TerminationWaitTimeInMinutes: 0 DeploymentReadyOption: ActionOnTimeout: STOP_DEPLOYMENT # 根据服务启动时长调整等待时间,确保健康检查能完成 WaitTimeInMinutes: 10 LoadBalancerInfo: TargetGroupPairInfoList: - TargetGroups: - Name: !Sub ${EnvironmentName}-1 - Name: !Sub ${EnvironmentName}-2 ProdTrafficRoute: ListenerArns: [ !Ref ALBListenerHTTPS ] ECSServices: - ServiceName: !Ref EnvironmentName ClusterName: !Ref EnvironmentName
关键说明
- 之前ECSAllAtOnce不校验健康的原因:蓝绿部署模式下,ECSAllAtOnce配置本身不会主动触发健康校验,需要依赖目标组健康检查和CodeDeploy的
DeploymentReadyOption配合。线性部署配置会在每批实例启动后等待健康校验,而全量配置需要明确让CodeDeploy等待目标健康后再切换流量。 - 目标组健康检查的作用:CodeDeploy会监听目标组状态,只有当绿色目标组内所有实例都健康时,才会执行流量切换;如果等待超时仍未健康,部署会按
ActionOnTimeout设置停止,避免流量路由到异常实例。 - 健康检查宽限期:ECS服务的
HealthCheckGracePeriodSeconds需设置合理值,避免服务启动初期就被标记为不健康,确保有足够时间完成初始化。
内容的提问来源于stack exchange,提问作者Alex Harris
相关产品推荐
相关产品推荐

