为什么 Elastic Beanstalk 流量拆分部署策略会忽略 HTTP 错误?

问题描述

我正在使用 AWS Elastic Beanstalk。在那里,我选择了 100% 拆分的流量拆分部署策略(以便 100% 的新实例将拥有新版本并对其运行状况进行评估)。

这是(根据他们的文档)应该如何工作:

在流量拆分部署期间,Elastic Beanstalk 在单独的临时 Auto Scaling 组中创建一组新实例。然后,Elastic Beanstalk 指示负载均衡器将环境传入流量的一定百分比定向到新实例。然后,在配置的时间内,Elastic Beanstalk 会跟踪新实例集的运行状况。如果一切顺利,Elastic Beanstalk 会将剩余流量转移到新实例,并将它们附加到环境的原始 Auto Scaling 组,替换旧实例。然后 Elastic Beanstalk 进行清理——终止旧实例并移除临时 Auto Scaling 组。

更具体地说:

将部署回滚到以前的应用程序版本很快,并且不会影响对客户端流量的服务。如果新实例未通过运行状况检查,或者您选择中止部署,Elastic Beanstalk 会将流量移回旧实例并终止新实例。

但是,它查看我的内部 /health 运行状况检查,而不是从 HTTP 状态代码中查看环境的整体运行状况,这似乎很愚蠢,因为它已经具有信息。

我尝试了以下场景:

  1. 部署新版本。
  2. “健康评估期”一开始,服务器就会出现错误 500s(来自我专门为此目的制作的端点)。
  3. 然后,AWS 将我所有的实例移至“降级”状态和“不健康”状态,但随后似乎忽略了它,并继续进行。

请参阅以下两个日志转储屏幕截图(它们是最旧的)。

有什么方法可以让 AWS 在流量拆分期间尊重它已经执行的基于 HTTP 状态的健康检查?还是我必须完全依赖定制开发的健康检查?

更新 1:更奇怪的是,我尝试让自己的健康检查也总是失败,但它仍然决定部署健康检查失败的新版本!

更新 2: 我注意到它在评估健康状况时创建的临时 Auto Scaling 组只有“EC2”类型的健康检查,而不是“ELB”。我认为这可能是根本原因。如果我只能让它改用“ELB”就好了。

enter image description here

enter image description here

解决方法

这很有趣!我不知道将健康检查类型设置为“ELB”是否可以完成这项工作,因为我们使用的是 CodeDeploy,它比 AWS Elastic Beanstalk 具有更好的回滚功能。

但是,文档 [1] 中有一种完善的文档方式来应用您正在寻找的设置:

[...] 默认情况下,为您的环境创建的 Auto Scaling 组使用 Amazon EC2 状态检查。如果您环境中的实例未通过 Amazon EC2 状态检查,Auto Scaling 会将其关闭并替换。
Amazon EC2 状态检查仅涵盖实例的健康状况,而不涵盖您的应用程序、服务器或在该实例上运行的任何 Docker 容器的健康状况。如果您的应用程序崩溃,但它运行的实例仍然健康,它可能会被踢出负载均衡器,但 Auto Scaling 不会自动替换它。 [...]
如果您希望 Auto Scaling 替换应用程序停止响应的实例,您可以使用配置文件将 Auto Scaling 组配置为使用 Elastic Load Balancing 运行状况检查。以下示例将组设置为使用负载均衡器的运行状况检查以及 Amazon EC2 状态检查来确定实例的运行状况。

示例 .ebextensions/autoscaling.config

Resources:
 AWSEBAutoScalingGroup:
   Type: "AWS::AutoScaling::AutoScalingGroup"
   Properties:
     HealthCheckType: ELB
     HealthCheckGracePeriod: 300

不过,它没有提到新的流量拆分部署功能。 因此,我无法确认这是实际的解决方案,但至少您可以试一试。

[1] https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environmentconfig-autoscaling-healthchecktype.html

,

曾几何时,我认为 Elastic Beanstalk 中的不可变部署选项是灵丹妙药——但它仅在部署不涉及更改应用程序的数据库架构时才有效。

我们现在采用了蓝绿部署。但是,这仅在您控制 DNS 时才有效。如果您是 SaaS 解决方案并且您允许客户创建 CNAME,那么 B/G 通常是一个巨大的失败,因为企业:a) 设置非常高的 TTL,和/或 b) 他们的内部 DNS 或防火墙缓存底层 IP 地址ALB(这是动态的,当然,当您交换蓝色和绿色环境的 URL 时会被替换)。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...