当从实例 X 的 NLB DNS 卷曲时,内部网络负载平衡器不会路由到实例 X

Ski*_*kip 2 nlb amazon-web-services

  • 我有一个网络负载平衡器 (NLB) 的内部(解析为私有 ip)
  • 端口 80 上的 NLB 侦听器指向目标组。目标组中的实例 10.141.80.140 是唯一一个。

问题:
当我在实例 10.141.80.140 上卷曲 NLB 的 DNS 时, 我没有收到任何响应。
希望 NLB 重定向到 10.141.80.140,但它没有发生。
当我在 10.141.80.140 上时,NLB DNS 仅不会重定向 - 重定向可以从同一子网中的其他实例进行

细节:

  • EC2 10.141.80.140 周围的安全组是全球开放的,入站和出站
  • 当我从另一个实例 10.141.80 卷曲 NLB DNS 时。122在具有相同安全组和其他设置的同一子网中 - NLB 正确解析为 10.141.80.140
  • 当我从实例卷曲 NLB DNS 时,NLB 应将 10.141.80 解析到该 DNS。140 - NLB解析为 10.141.80.140
  • 当我从实例 10.141.80 卷曲实例 ip 10.141.80.140 时。140 - 我得到回应
  • 当我从实例 10.141.80 卷曲实例 ip 10.141.80.140 时。122 - 我得到回应

问题:
在 NLB 侦听器目标组中,有什么会阻止 NLB 解析实例的请求,该请求将路由回实例?

在此处输入图片说明

Ski*_*kip 5

这是一个众所周知的行为,我很乐意解释。网络负载均衡器引入了源地址保留功能 - 传入连接的原始 IP 地址和源端口保持不变。当目标响应请求时,VPC 内部会捕获此数据包并将其转发到 NLB,后者将其转发到其目的地。

这种行为有一个副作用:当操作系统内核检测到出口数据包的目标地址是本地地址之一时,它会直接将此数据包转发给应用程序。

例如,给定以下组件:

  • 我们有一个内部 NLB 和一个后端实例。两者都部署在子网 10.0.0.0/24 中。
  • NLB 具有 IP 10.0.0.10 和端口 80 上的侦听器,用于将请求转发到端口 8080。
  • 后端实例的地址为 10.0.0.55,有一个 Web 服务器侦听端口 8080。它有一个安全组,允许所有传入的本地流量。

  • 如果实例尝试与 NLB 建立通信;通信流程如下:

    • 实例想要 telnet NLB:它请求在端口 80 上针对 NLB DNS 名称建立 TCP 连接。
      • 由于它是传出通信,因此它从一个临时端口开始;实例发送一个 SYN 数据包 (1):
        • 来源:10.0.0.55:40000
        • 目的地:10.0.0.10:80
      • NLB 接收数据包并将其转发到后端实例 (10.0.0.55:80)。
      • 由于地址保留功能,后端实例会收到一个包含以下信息的 SYN 数据包:
        • 来源:10.0.0.55:40000
        • 目的地:10.0.0.55:80
      • 操作系统在内部路由数据包(因为它的目的地是自己的机器),这是问题发生的时间:
        • 发起套接字期待来自 10.0.0.10:80(NLB)的 SYN_ACK。
        • 但是,它从 10.0.0.55:40000(实例本身)接收 SYN_ACK。
        • 操作系统将发送几个 TCP_RETRANSMISSION 直到超时。

公共 NLB 不会发生这种情况,因为实例需要在 VPC 中执行 NAT 以使用其公共 IP 地址将请求发送到 NLB。内核不会在内部转发数据包。

最后,一种可能的解决方法是根据后端的 IP 地址而不是它们的实例 ID 来注册后端;使用这种方法,NLB 转发的流量将包含 NLB 内部 IP 作为源 IP,禁用“源地址保留”功能。不幸的是,如果您使用 AutoScaling Group 启动实例,则它只能通过其 ID 注册启动的实例。对于 ECS 任务,将网络配置为“awsvpc”会强制 NLB 通过其 IP 注册每个目标。