使用 Elastic Load Balancing 和 EC2 Auto Scaling 选择正确的运行状况检查

作者: 迈克尔·哈肯 | 2023

客户经常使用 弹性负载平衡 (ELB) 负载均衡器和 亚马逊 EC2 Auto Scaling 组 (ASG) 来构建可扩 展、有弹性的工作负载。正确配置后,Amazon ELB 运行状况检查有助于使您的工作负载更能抵御负载均衡器背后的工作负载组件的故障。但是,您可能需要权衡处理不同的故障场景,具体取决于您实施运行状况检查的方式以及它们是否已添加到 ASG。

这篇文章就不同类型的健康检查的用例以及是否应将其添加到 ASG 中提供了规范性指导。它还描述了它们如何使您的工作负载更能适应特定的故障条件,以及您可能需要构建自己的弹性工具来缓解故障的其他场景。

健康检查策略

默认情况下,ASG 仅使用 EC2 实例状态检查 来确定实例运行状况。这些状态检查可识别故障情况,例如网络连接中断、系统电源中断、内存耗尽或内核不兼容。他们不监控实例内部发生的事情(例如软件、操作系统或文件系统的运行状况),也不监视其与外部依赖关系交互的能力。您还可以 将 ELB 运行状况检查添加到注册的 Auto Scaling 组 中。向 ASG 添加负载均衡器的运行状况检查允许 EC2 自动替换未通过 亚马逊弹性计算云 (Amazon EC2) 状态检查或亚马逊 ELB 运行状况检查的实例。

衡量实例运行状况的策略有三种:活跃度检查、本地运行状况检查和依赖关系运行状况检查。亚马逊建筑商图书馆关于 实施健康检查 的文章 提供了更多细节。活动检查的示例包括 EC2 实例状态检查和 网络负载均衡器 (NLB) 执行的 被动运行状况检查 。 但是,您通常想了解更多关于实例运行状况的信息,而不仅仅是它响应 ping 之类的能力。为了更好地了解实例的真实运行状况,您应该将活动的 ELB 运行状况检查配置为本地运行状况检查(在本文 中称为 shallo w )或依赖关系运行状况检查(在本文 中称为 深度 检查)。浅层运行状况检查只能进行 “机内” 检查,例如确保关键进程和代理正在运行、软件的正确行为或文件系统的运行状况等。深度运行状况检查包括浅层运行状况检查和与 “开箱即用” 依赖关系的测试交互,例如解析 DNS 记录、查询数据库或向下游服务发送数据。

以下部分评估了使用负载均衡器提供的浅层和深度运行状况检查的利弊、将其添加到您的 ASG 所产生的影响、确定每种组合的利弊,以及根据需求评估通过特定组合最适合解决的用例。

使用浅层运行状况检查

浅层运行状况检查可监控本地实例的运行状况,例如确保关键进程正在运行、文件系统运行状况以及已部署软件的正确行为。如果该实例的本地所有内容都显示正常,则该实例会向运行状况检查返回成功的 HTTP 响应。让我们来看看使用添加到 ASG 的浅层运行状况检查。

场景 1:使用添加到 ASG 的浅层运行状况检查

在此配置中,当发生本地故障时,ELB 和 EC2 Auto Scaling 都会检测到故障,停止将流量路由到实例,然后将其替换。向 ASG 添加浅层运行状况检查可让 EC2 Auto Scaling 更好地了解本地实例的运行状况。此外,在这种方法中,依赖关系的暂时失效不会导致实例终止。这两者都是好东西。 通常,没有理由不将负载均衡器中的浅层运行状况检查添加到 ASG。对于 EC2 Auto Scaling 来说,提高可观测性 几乎总是有益和安全 的。

但是,浅层健康检查也有缺点。它们不允许系统自动绕过外部依赖关系导致的故障,尤其是单可用区 (AZ) 灰色故障等情况。发生这些情况时,负载均衡器会将其所有目标视为运行状况良好,即使它们可能会向您的客户返回错误。这是您在浅层健康检查和深度运行状况检查之间做出的权衡,如下图所示(图 1)。

Registered instances passing health checks while a network impairment prevents database connections for one Availability Zone.

图 1 — 浅层运行状况检查不允许 ELB 绕过灰色故障或依赖故障

要绕过遇到单可用区灰色故障的实例,您可以使用 区域 转移等服务撤离该可用区。 有关构建检测和缓解单可用区灰色故障所需的可观测性和缓解模式的详细信息,请参阅 高级多可用区弹性模式 白皮书。在短暂的依赖关系失败期间,你可以实现诸如 优雅降级 或 退 避之类的模式,然后重试 以减轻其影响。或者,您可以实施深度健康检查,以帮助规避依赖障碍。让我们来看看这些可以如何提供帮助,以及你必须做出的权衡。

使用深度健康检查

深度运行状况检查既可以检查本地实例的运行状况,也可以检查与您定义的外部依赖关系(例如数据库或外部 API)交互的运行状况。当您使用深度运行状况检查时,外部依赖关系的短暂损害可能会使负载均衡器目标显得不正常。这对于绕过受依赖项暂时性故障影响的实例非常有用。但是,无论您是否将健康检查添加到ASG,都可能导致不同的结果,因此让我们来看看这两种情况。

场景 2:使用未添加到 ASG 的深度运行状况检查

在此示例中,让我们假设网络降级灰色故障会导致从 AZ 1 中的实例到 AZ 2 中的数据库的 20% 的查询超时。下图(图 2)显示了运行状况检查的流程。

The workflow for an ELB health check that tests local instance health and an external dependency

图 2 — 使用深度运行状况检查来避开 AZ 灰色故障

  1. ELB 向实例 Web 应用程序的 /health 路径发送 HTTP GET 请求。
  2. EC2 实例接收请求并执行其本地运行状况检查逻辑。
  3. EC2 实例向数据库发送查询以确保它可以连接和检索数据。灰色故障导致此查询超时。
  4. 由于数据库查询失败,实例使用 HTTP 500 响应响应运行状况检查,但运行状况检查失败。

一旦实例连续运行状况检查失败,负载均衡器就会发现 EC2 实例运行状况不佳并停止向其路由请求。深度健康检查有助于迅速从受影响的亚利桑那州撤离,并减轻客户因减值而受到的任何影响。这是一个不错的结果。

现在让我们假设 AZ 1 中的实例遇到了本地问题,例如,由于配置文件损坏, httpd 进程不断崩溃。深度运行状况检查也成功绕过了此故障。但是,此类问题不太可能自行解决,实例可以永久保持这种失败状态。如果有系统因素导致本地故障,例如引发损坏的毒丸请求,则这种情况可能会在多个情况下发生。从 EC2 Auto Scaling 的角度来看,这些实例永远不会被标记为运行状况不佳,因为它仅使用 EC2 实例状态检查。因此,它们不会被替换。在最坏的情况下,这可能导致无法为客户请求提供服务的健康实例。

场景 3:向 ASG 添加深度运行状况检查

为了缓解前面描述的情况,您可以考虑将负载均衡器运行状况检查添加到 ASG。但是, 这种方法有一个明显的缺点 。如果依赖关系出现暂时性错误,则可能导致每个注册目标同时失败 ELB 运行状况检查。尽管负载均衡器会 失效打开 并将流量发送到所有注册目标,但 EC2 Auto Scaling 将所有实例视为运行状况不佳并开始替换它们,如下图所示(图 3)。

An external dependency failure causes all registered instances to appear unhealthy.

图 3 — 深度运行状况检查不必要地导致 EC2 Auto Scaling 终止本地运行状况良好的实例

发生这种情况时,您必须等待 EC2 Auto Scaling 替换所有运行状况不佳的实例,然后等待它们启动并通过运行状况检查,然后才能恢复服务。这可能需要比等待暂时性问题缓解要长得多。 最佳做法是,不要在您的 ASG 中添加 “深度” ELB 运行状况检查。这将防止在依赖关系失败期间大规模终止您的 EC2 实例队列。 这也意味着需要权衡取舍:ELB 的深度运行状况检查有助于快速解决故障,但是 EC2 Auto Scaling 无法确定本地实例的运行状况,也无法在实例运行状况不佳时替换实例。

使用深度运行状况检查时确定本地实例运行状况。

解决这种权衡并识别和响应实例上的本地运行状况问题的一种方法是使用心跳表模式。每当收到来自负载均衡器的运行状况检查时,该实例都会确定本地实例的运行状况,并将包含实例状态和时间戳的条目写入到 Amazon DynamoDB 表中。 然后,观察器进程(例如每分钟运行一次 亚马逊云科技 Lambda 函数)查询表,寻找状态不佳或在特定时间段(例如五分钟)内未更新状态的条目。 每当找到符合这两个条件之一的条目时,它就会使用 setInstanceHealt h API 手动设置实例运行状况。

下图(图 4)显示了向 DynamoDB 表报告其运行状况的三个实例。AZ 3 中的实例已经超过五分钟没有报告其状态了。 当 Lambda 函数在 2023-04-02 T 12:01:00 执行时,它会观察到报告失误,假设该实例在本地出现了问题,然后发出 setInstanceHealth API 调用,例如 i-5432106789cbafed2 将其设置为不健康。

The heartbeat table pattern where a Lambda function evaluates health check records inserted into a DynamoDB table and manually sets the instance health when they fail.

图 4 — 向心跳表报告本地运行状况的实例,以及观察程序服务终止五分钟内未报告的实例

确保使用此类模式实现速度控制,以防止配置错误、错误或意想不到的情况导致观察者服务无意中终止过多的实例。例如,你可能只允许观察者服务每分钟终止一个实例,如果它尝试终止更多实例,它就会发送警报让人类参与。

摘要

本节总结了使用负载均衡器进行深度和浅层运行状况检查的权衡和建议,以及您是否将其添加到 ASG。

深度健康检查

请勿将此类健康检查添加到您的 ASG 中。这可以防止您的实例队列无意中被大规模终止。

无需替换实例即可快速解决问题,例如灰色故障。

这需要额外的工具,例如心跳表,来识别运行状况不佳的实例,以便您可以将其替换。

浅层健康检查

请务必将它们添加到您的 ASG 中以替换运行状况不佳的实例。

防止在出现短暂依赖关系时更换实例,并快速绕过受该故障影响的实例。

需要构建其他机制来解决由外部依赖关系引起的问题,例如单可用区灰色故障或网络障碍。

无论是深层还是浅层的健康检查都不是对错。但是,每个都有它不直接支持的用例。您应该考虑与构建替代机制的成本和精力相比,哪个用例更有可能发生。

例如,假设您认为本地主机故障比单可用区灰色故障更有可能发生。在这种情况下,你需要选择与 ASG 集成的浅层运行状况检查。你可以得出结论,单个可用区灰色故障带来的风险不足以保证开发工具来应对这种故障,如果确实发生影响,你可以承受得起等待。但是您可能还会确定,构建心跳表解决方案的成本相对较低,工作量也较低。这只需稍加投资即可解决这两个用例,并决定使用深度运行状况检查选项。最后,你可能会认为,使用深度运行状况检查来规避灰色故障并不是一个足够全面的解决方案,你希望完全控制这种缓解措施。因此,您选择使用浅层健康检查并构建自己的亚利桑那州疏散工具。

结论

这篇文章描述了您可以使用负载均衡器实施的浅层运行状况检查和深度运行状况检查之间的区别、将其添加到您的 ASG 所产生的影响,以及为缓解某些情况而必须创建的其余解决方案。您应该仔细考虑选择使用 ELB 和 EC2 Auto Scaling 实施哪种模式,并了解其中的利弊。有关本文中描述的折衷方案和解决方案的更多详细信息 ,请参阅 NL B 运行状况检查 、ALB 运行状况检查、 分区转移 、 此架构完善的运行状况检查研讨会 高级多可用区弹性模式

Michael Haken

迈克尔·哈肯

Michael 是 亚马逊云科技 战略账户团队的首席解决方案架构师,他帮助客户创新、实现业务差异化并转变客户体验。他在支持金融服务、公共部门和数字原生客户方面拥有超过15年的经验。Michael 拥有弗吉尼亚大学的学士学位和约翰·霍普金斯大学的计算机科学硕士学位。工作之余,你会发现他在农场里和家人和狗一起玩耍。


*前述特定亚马逊云科技生成式人工智能相关的服务仅在亚马逊云科技海外区域可用,亚马逊云科技中国仅为帮助您发展海外业务和/或了解行业前沿技术选择推荐该服务。