NLB 目标组健康检查失控

Posted

技术标签:

【中文标题】NLB 目标组健康检查失控【英文标题】:NLB Target Group health checks are out of control 【发布时间】:2018-06-16 13:21:50 【问题描述】:

我有一个网络负载均衡器和一个关联的目标组,它们被配置为对 EC2 实例进行运行状况检查。问题是我看到大量的健康检查请求;每秒多次。

检查之间的default interval 应该是 30 秒,但它们出现的频率比应有的高出大约 100 倍。

我的堆栈是在 CloudFormation 中构建的,我尝试覆盖 HealthCheckIntervalSeconds,但没有效果。有趣的是,当我尝试在控制台中手动更改间隔时,我发现这些值是灰色的:

这是模板的相关部分,我尝试更改间隔已被注释掉:

NLB:
  Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
  Properties:
    Type: network
    Name: api-load-balancer
    Scheme: internal
    Subnets: 
      - Fn::ImportValue: PrivateSubnetA
      - Fn::ImportValue: PrivateSubnetB
      - Fn::ImportValue: PrivateSubnetC

NLBListener:
  Type : AWS::ElasticLoadBalancingV2::Listener
  Properties:
    DefaultActions:
      - Type: forward
        TargetGroupArn: !Ref NLBTargetGroup
    LoadBalancerArn: !Ref NLB
    Port: 80
    Protocol: TCP

NLBTargetGroup:
  Type: AWS::ElasticLoadBalancingV2::TargetGroup
  Properties:
    # HealthCheckIntervalSeconds: 30
    HealthCheckPath: /healthcheck
    HealthCheckProtocol: HTTP
    # HealthyThresholdCount: 2
    # UnhealthyThresholdCount: 5
    # Matcher:
    #   HttpCode: 200-399
    Name: api-nlb-http-target-group
    Port: 80
    Protocol: TCP 
    VpcId: !ImportValue PublicVPC

我的 EC2 实例位于私有子网中,外界无法访问。 NLB 是内部的,因此不通过 API 网关就无法访问它们。 API Gateway 没有配置 /healthcheck 端点,因此排除了来自 AWS 网络外部的任何活动,例如人们手动 ping 端点。

这是从 CloudWatch 获取的我的应用程序日志示例,而应用程序应该处于空闲状态:

07:45:33 "label":"Received request URL","value":"/healthcheck","type":"trace"
07:45:33 "label":"Received request URL","value":"/healthcheck","type":"trace"
07:45:33 "label":"Received request URL","value":"/healthcheck","type":"trace"
07:45:33 "label":"Received request URL","value":"/healthcheck","type":"trace"
07:45:34 "label":"Received request URL","value":"/healthcheck","type":"trace"
07:45:34 "label":"Received request URL","value":"/healthcheck","type":"trace"
07:45:34 "label":"Received request URL","value":"/healthcheck","type":"trace"
07:45:35 "label":"Received request URL","value":"/healthcheck","type":"trace"
07:45:35 "label":"Received request URL","value":"/healthcheck","type":"trace"
07:45:35 "label":"Received request URL","value":"/healthcheck","type":"trace"

我通常每秒收到 3 到 6 个请求,所以我想知道这是否正是网络负载均衡器的工作方式,而 AWS 仍然没有记录(或者我还没有找到),或以其他方式解决此问题。

【问题讨论】:

您有多少个 EC2 目标实例?他们是否将日志写入同一个 cloudwatch 流? 目前只有一个实例,但它们也被配置为写入由实例 ID 标识的日志。 您需要记录传入的健康检查请求的源IP地址。这向你展示了什么?平衡器是否检测到您的服务是健康的? 感谢@Michael-sqlbot,服务很健康。任何服务都无法在私有子网之外访问此端点。这是私有子网中的唯一实例,并且该实例没有公共 IP 地址。没有 Internet 网关,因此只能通过没有运行状况检查端点的 API Gateway VPC 链接进入。我所做的尝试是将目标组运行状况检查端点更改为无效的,然后实例立即停止将请求记录到 /healthcheck,证明它们都来自目标组检查,而不是其他任何东西。 我明白你的意思,但仍然建议你需要记录源IP。同时记录对等源端口。没有这些,您仍然在技术上推测它不可能是其他任何东西。 【参考方案1】:

更新:已在相关的aws forum post 上对此进行了回答,确认这是网络负载平衡器的正常行为,并引用了它们的分布式特性作为原因。无法配置自定义间隔。目前,文档仍然过时,另有说明。


这可能是 NLB 目标组中的错误,或者是 documentation 不正确的正常行为。我得出这个结论是因为:

我已验证运行状况检查来自 NLB 配置选项在控制台上显示为灰色 推断 AWS 知道或施加了此限制 others 观察到了相同的结果 该文档专门针对网络负载均衡器 AWS 文档通常会引导您进行疯狂追逐

在这种情况下,我认为这可能是记录不正确的正常行为,但除非来自 AWS 的人可以验证,否则无法验证这一点,而且几乎不可能在 aws 论坛上获得issue like this 的答案。

能够配置设置或至少更新文档会很有用。

【讨论】:

您是如何克服这个问题的?将私有服务移动到公共子网并通过安全组保护它? 似乎您添加到 NLB 的侦听器越多,运行状况检查就越受到重视。如果您只使用 1 个侦听器,您将不会有这种 ddos​​ 行为 Fwiw 我只有 1 个侦听器并且仍然得到这种行为 对于其他像我一样困惑的登陆这里的人,这就是答案。我有 3 个监听器指向一个 Fargate 容器,每个监听器在 30 秒时进行健康检查。我每分钟看到 1k 次健康检查,其中 170 次来自单个 nlb 源 ip。我已将它们从我的应用程序代码中删除以更好地管理它们。【参考方案2】:

编辑:现在只是想在 2021 年 9 月分享这方面的更新。如果您使用的是 NLB,您可能会收到类似于以下内容的电子邮件:

我们正在就您的网络即将发生的变化与您联系 负载均衡器。从 2021 年 9 月 9 日开始,我们将升级 NLB 的 目标健康检查系统。升级后的系统提供更快 故障识别,提高目标健康状态的准确性,以及 允许 ELB 在部分期间对受影响的可用区进行加权 失败场景。

作为本次更新的一部分,您可能会注意到生命值降低了 检查到后端目标的流量,减少目标 NetworkIn/Out 指标,因为我们删除了多余的运行状况检查。

我希望这应该可以解决目标在使用 NLB 时收到许多健康检查的问题。

上一个答案:

AWS 员工在这里。为了详细说明已接受的答案,您可能会看到大量的健康检查请求的原因是 NLB 使用多个分布式健康检查器来评估目标健康状况。这些健康检查器中的每一个都会以您指定的时间间隔向目标发出请求,但它们都会在该时间间隔内向目标发出请求,因此您将看到来自每个分布式探测器的一个请求。然后根据成功的探测次数评估目标运行状况。

您可以在“查看 Route 53 健康检查”下阅读另一位 AWS 员工在此处撰写的非常详细的说明:https://medium.com/@adhorn/patterns-for-resilient-architecture-part-3-16e8601c488e

我对运行状况检查的建议是将运行状况检查编码得非常轻松。很多人都犯了一个错误,即超载他们的健康检查来检查后端数据库或运行其他检查。理想情况下,您的负载均衡器的健康检查除了返回一个短字符串(如“OK”)之外什么都不做。在这种情况下,您的代码应该花费不到一毫秒的时间来处理运行状况检查请求。如果您遵循这种模式,那么偶尔会爆发 6 到 8 次运行状况检查请求不应使您的流程过载。

【讨论】:

一个非常简单的运行状况检查虽然没那么有用,但我不确定包含的不仅仅是检查进程是否正在运行和接受连接是一个“错误”。除了数据库连接之外,磁盘空间检查也是另一个有用的方法。 “偶尔爆发 6-8 个健康检查请求”-> 似乎变得更糟了,每秒连续 6-8 个请求,定期爆发接近 20 个请求/秒。即使是轻微的运行状况检查也会以如此不必要的高速率显着影响较小实例类型的 CPU 消耗。 我遇到的问题是我尝试进行负载平衡的服务具有非常详细的日志记录,无法减少它。持续的治疗检查(大约每秒 5 次)很快就填满了我的日志。这非常令人沮丧,并且让我试图找到一些 hacky 替代方案来避免使用 NLB。为什么需要这样工作???它不需要像这样向我的服务发送垃圾邮件来确定它是否健康。 “犯错误 [...] 做检查后端数据库之类的事情” ...这正是健康检查的重点。这不是一个错误。您应该做的是将运行状况检查结果缓存约 30 秒或 w/e。这样你就可以获得真正的健康检查,但可能会受到打击,这没关系。 我认为这是对我的实例的一种 DDOS 或负载测试 :(【参考方案3】:

这件事有点晚了。但是对我有用的是让我的(C++)服务启动一个专门用于来自 ELB 的健康检查的线程。线程等待套接字连接,然后等待从套接字读取;或遇到错误。然后它关闭套接字并返回等待下一个健康检查 ping。这比让 ELB 一直占用我的流量端口要便宜得多。它不仅让我的代码认为它受到了攻击,而且还启动了为真正的客户提供服务所需的所有后勤工作。

【讨论】:

请详细说明如何操作。

以上是关于NLB 目标组健康检查失控的主要内容,如果未能解决你的问题,请参考以下文章

使用 UDP ECS 服务对 NetworkLoadBalancer 进行健康检查

目标组在端口 80 上的健康检查不断失败,并在使用动态端口映射时启动新实例

如何使用 elasticbeanstalk 设置自动缩放组健康检查类型

AWS Application Load Balancer 向不健康的目标组/实例发送请求

如何将健康检查请求 ip 添加到负载均衡器安全组?

健康风险评估的步骤包括