关注分享主机优惠活动
国内外VPS云服务器

K8S Ingress 环境中 Http Redirect 端口丢失问题

摘要:最近发现了一个问题,应用程序在恢复时会丢失其最初访问的端口。 所以我觉得问题出在这些。 正如描述中提到的,返回的应该是: 更改后的端口是可靠的。 这种方法比较可靠。 更改端口就没有问题。 使用提供的内容并将值替换为文本。

github

最近发现了一个问题。 返回 HTTP 重定向时,应用程序丢失了最初访问的端口。 例如,如果您按如下方式访问 http://IP-A:Port-A/app/delete,则该 URL 将响应 302,但响应标头 位置 b> 没有港口。 正确结果为:http://IP-A:Port-A/app/index 但返回结果为: http://IP-A/ app/index,端口丢失。

基本情况

部署情况如下。

部署Nginx Ingress,并使用NodePort公开Nginx Ingress服务。

应用中配置的入口

服务器信息:

服务器名称

NAT服务器

K8S节点

Nginx Ingress服务

Nginx Ingress Pod

应用服务

应用Pod

IP

IP-A

IP-B

IP-C(集群IP/VIP)

IP-D(集群IP)

IP-E(集群IP/VIP)

IP-F(集群IP)

端口

端口-A

端口-B(Nginx Ingress Svc的节点端口)

港口-C

80(集装箱港口)

港口-E

端口-F

其实,以上并不都是服务器。 其中两个 K8S 服务不是服务器。 有关详细信息,请参阅 K8S - 访问 http://IP-A:Port-A/app/delete 时使用源 IP 请求。

顺便说一下,上面的NAT服务器是用来让Nginx Ingress能够从外网访问的。

观察

使用上面提到的。Echo Server 通过 Ingress 访问 Echo Server 时会监控传递给 Echo Server 的请求头:http://IP-A:Port-A/echo-server 并获取这些有趣的信息。 请求头:

host=IP-A:Port-Ax-original-uri=/echo-serverx-forwarded-for= IP[k4 ] ]Bx-转发-主机=IP-A:端口-Ax-转发-端口=80x-转发-proto=http

如果您随后直接访问 Echo Server Svc,您会发现上面的 x-*Request header 丢失了。 所以我认为问题可能出在这些标题上。

术语解释

解释每个头的含义。

x-forwarded-,客户端访问代理时的客户端IP。
这里使用 K8S 节点 IP 的原因是 Nginx Ingress 认为请求来自 K8S 节点(仔细看上面的文章,使用 K8S - 源 IP)。 在此之前,我不知道是否是NAT。

x-forwarded-host,客户端访问代理的主机。

x-forwarded-proto,客户端访问代理时访问的原始http方案。

x-forwarded-port,客户端访问代理时访问的端口。

x-原始-uri,没有找到可靠的信息。

前三个是事实上的标准,MDN 上列出了 x-forwarded-portx-original-。它被包括在内。 uri看起来像一个私有扩展。

实验

找到一个有用的Http请求工具(我使用Postman),并记住在使用Nginx请求方法之前取消选中“跟随重定向”(即使用上面的x-* headers(包括/removed/modified值))直接请求App Svc。

您可以看到x-forwarded-port是响应标头Location的键。 因此,如果 x -forwarded[ k4]port=port-Alocation 将获得正确的端口。

分析如何构造重定向URL

我猜应用程序正在使用hostx[可以。 k4]forwarded-*这些标头用于构造重定向 URL。

Java Servlet API 规定,在编写 HttpServletResponse#sendRedirect 时,返回的 URL 必须是绝对 URL。

Tomcat 的 org.apache.catalina.connector.Response 的 toAbsolute 方法负责构造绝对 URL。

那么如何决定选择哪个端口呢?这与RemoteIPValve有关。 如果您有兴趣,请查看相关材料。

上面只描述了Tomcat如何构建redir。等URL,但这种方法不是标准的。 不同的容器有自己的实现。 毕竟,Java Servlet API 没有指定如何构造绝对 URL。

我之前还写过一篇相关主题的文章,名为反向代理使用 https 协议、后台 Tomcat 使用 http、重定向时使用错误协议的解决方案。 参见: 。

为什么 x-forwarded-port 是 80

问题显然是访问 IP-A:Port-A ,为什么我在Nginx中得到的值是80?

这是因为它在整个请求链路的开始处:NAT服务器>K8S节点>Nginx Ingress Svc都是第4层有效的。 它们的作用是 NAT,您可以将它们视为 Nginx Ingress Pod。 由于我们不知道这些服务器/网络节点的端口,所以我们只能给 x-forwarded-port 自己的端口 80(容器内部的端口)。

对于这个逻辑,可以检查Nginx Ingress配置文件,看到如下内容:

kubectl -n kube-system exec -it  -- cat /etc /nginx/nginx.conf

解决方案 根据请求带 x - ]forwarded-端口(不可靠)

如果您检查 Nginx Ingress配置文件并在第一个请求中包含 x-forwarded-port ,您可以更改传回的值,但有两个问题: .

通过浏览器访问时无法添加此标头。

此标头通常由反向代理添加。 ,换句话说,Nginx Ingress 前面需要有反向代理。

因此,这种方法不适合。

更改Tomcat代码(不可靠)

将Tomcat代码更改为x-forward-host/host您也可以将其从标头。 您需要获得一个端口,这是不切实际的。

将NAT服务器端口更改为80(可靠)。

这种方法比较可靠。 将NAT服务器端口改为80就没有问题了。

实际上,如果想直接访问K8S节点(NodePort方法),还需要将NodePort设置为80。 还记得我之前说过的吗?Nginx Ingress 无法看到上层 NAT 上的端口。

这意味着最初请求的 URL 不能是 80 以外的端口,但必须是 http://some-ip/app

使用 Nginx Ingress 注释(可靠性)

使用 Nginx Ingress 提供的代理重定向注释将 location 值设置为 text 替换为

未经允许不得转载:主机频道 » K8S Ingress 环境中 Http Redirect 端口丢失问题

评论 抢沙发

评论前必须登录!