如何让 Nginx 入口控制器使用远程地址

问题描述

我在 Kubernetes 集群中使用 Nginx 入口控制器。我在集群中有一个应用程序,可以通过 Internet 访问。现在我使用 Ingress Controller 访问应用程序,目的是显示一些自定义错误

如果我访问该应用程序(该应用程序不是我自己编写的,因此我无法更改那里的内容),它会收到 nginx-ingress-controller-pod 的 IP 地址。 nginx-ingress-controller-pod 的日志表明远程地址是不同的。

我已经尝试过 use-proxy-protocol 之类的东西,然后我就可以使用 $remote_addr 并获得正确的 IP。但正如我所提到的,我无法更改我的应用程序,因此我必须“欺骗”入口控制器以将 $remote_addr 用作他自己的。 我如何配置入口,以便应用程序从远程 IP 而不是从 nginx-ingress-controller-pod IP 获取请求?有没有办法做到这一点?

编辑:我正在使用带有 kubernetes v1.19.2 和 Nginx 图表 ingress-Nginx-3.29.0 的裸机安装。

解决方法

使用第 7 层入口控制器无法实现。

如果 Ingress 保留源 IP,那么响应将直接从应用程序 pod 获得到客户端,因此客户端将从与他连接的 IP:port 不同的 IP:port 获得响应。甚至更糟 - 客户端的 NAT 完全丢弃响应,因为它与现有连接不匹配。

您可以在 stackoverflow 上查看此 similar question 并提供已接受的答案:

因为入口是 4 层以上的代理。您无法在第 3 层 IP 协议中保留 SRC IP。最好的是,我认为 Nginx Ingress 已经默认设置为将“X-Forwarded-For”标头放在任何 HTTP 转发中。 您的应用应该记录 X-Forwarded-For 标头

您可以按照 this article 尝试解决方法。它可以帮助您保护您的 IP。

我还推荐有关负载平衡和代理的very good article。您还将了解 L7 上的负载平衡:

L7 负载均衡和 OSI 模型 正如我在上面关于 L4 负载均衡的部分所说的,使用 OSI 模型来描述负载均衡特性是有问题的。原因是 L7,至少如 OSI 模型所描述的那样,本身包含多个离散的负载平衡抽象层。例如,对于 HTTP 流量,请考虑以下子层:

  • 可选的传输层安全性 (TLS)。请注意,网络人员争论 TLS 属于哪个 OSI 层。为便于讨论,我们将考虑 TLS L7。
  • 物理 HTTP 协议(​​HTTP/1 或 HTTP/2)。
  • 逻辑 HTTP 协议(​​标头、正文数据和尾部)。
  • 消息传递协议(gRPC、REST 等)。