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

Posted

技术标签:

【中文标题】为啥 Elastic Beanstalk 流量拆分部署策略忽略 HTTP 错误?【英文标题】:Why is Elastic Beanstalk Traffic Splitting deploy strategy ignoring HTTP errors?为什么 Elastic Beanstalk 流量拆分部署策略忽略 HTTP 错误? 【发布时间】:2021-06-15 16:03:09 【问题描述】:

我正在使用 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 状态代码来看,它已经有信息,这似乎很愚蠢.

我尝试了以下场景:

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

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

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

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

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

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

【参考方案2】:

这很有趣!我不知道将运行状况检查类型设置为“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

【讨论】:

是的,我试过那个配置。它确实适用于永久 Auto Scaling 组,但不适用于用于评估运行状况的临时组。 嗯,这很有趣!由弹性豆茎管理的云形成模板中的临时asg是否可见? 您能否尝试使用上面的 .ebextensions 文件通过将“AWSEBAutoScalingGroup”更改为该“临时”ASG 的逻辑 ID 来修改它? 那很不幸。我不知道如何解决这个问题。由于这是一个我自己没有使用的相对较新的功能,所以我不完全了解 AWS 在幕后所做的事情。无法修改临时 ASG 对我来说似乎是一个糟糕的设计决定。但是,如果临时 asg 具有可预测的 id 或标签,您可以通过 cli 调用(由 CloudWatch 事件触发)以编程方式更改每个部署的运行状况检查类型 我刚刚意识到另一种解决方法可能是通过 EventBridge 和 lambda 函数对弹性 beanstalk 事件做出反应:docs.aws.amazon.com/elasticbeanstalk/latest/dg/…

以上是关于为啥 Elastic Beanstalk 流量拆分部署策略忽略 HTTP 错误?的主要内容,如果未能解决你的问题,请参考以下文章

我应该如何限制我的 Elastic Beanstalk 环境的负载平衡 Web 流量?

在 AWS Elastic Beanstalk 和 EKS 上部署了一个 laravel 应用程序 相同的数据库 RDS 为啥在 Elastic Beanstalk 中获得快速响应

为啥我的 ec2-instance 被 elastic-beanstalk 终止?

Python3 + Nginx:将 HTTP 流量重定向到 AWS Elastic Beanstalk 上的 HTTPS

为啥 https 在 AWS Elastic Beanstalk 上被阻止?

为啥 AWS 将停用具有多容器支持的 Elastic Beanstalk?