问题描述
我在 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 等)。