同主机不同路径Ingress配置问题:/path2/login访问404排查
Nginx Ingress路径重写导致的404问题分析
问题现象
dev.app.com/login:无论直接访问还是从根路径重定向过来,均能正常转发至path1svc并返回正确内容。dev.app.com/path2/login:仅从dev.app.com/path2重定向过来时可用;直接在浏览器输入该URL或跳转后刷新页面,会触发Nginx 404 Not Found错误。
当前Ingress配置
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-fe annotations: nginx.ingress.kubernetes.io/use-regex: 'true' nginx.ingress.kubernetes.io/rewrite-target: /$1 spec: tls: - hosts: - dev.app.com secretName: tls-secret-con rules: - host: dev.app.com http: paths: - path: /(.*) pathType: ImplementationSpecific backend: service: name: path1svc port: number: 80 - path: /path2(/|$)(.*) pathType: ImplementationSpecific backend: service: name: path2svc port: number: 80
问题原因分析
路径匹配顺序错误
Nginx Ingress的正则路径匹配是从上到下按定义顺序执行,第一个匹配的规则会被优先使用。配置中第一个路径/(.*)是贪婪匹配,会捕获所有以/开头的请求(包括/path2/login),导致第二个针对/path2的规则永远不会被触发。直接访问或刷新/path2/login时,请求会被转发到path1svc,而该服务没有对应资源,因此返回404。重定向场景的特殊逻辑
当访问/path2时,请求会被第二个路径规则匹配(符合/path2(/|$)(.*)的正则),转发到path2svc。path2svc返回重定向到/path2/login后,前端可能在客户端完成路由跳转(未发起新的后端请求),因此暂时可用;但刷新页面时会发起新的HTTP请求,此时又会被第一个路径规则捕获,触发404。Rewrite-Target捕获组错误
第二个路径规则的正则/path2(/|$)(.*)定义了两个捕获组:
- 第一个捕获组:
(/|$)(匹配斜杠或路径结束) - 第二个捕获组:
(.*)(匹配后续内容)
但全局配置的rewrite-target: /$1只会使用第一个捕获组,导致转发到path2svc的路径错误(比如/path2/login会被重写成/而非/login),即使规则被触发也无法正确访问后端资源。
解决方案
修正后的Ingress配置
调整路径顺序(将具体路径放在前面),并为/path2路径单独指定正确的rewrite规则:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-fe annotations: nginx.ingress.kubernetes.io/use-regex: 'true' # 全局rewrite-target保留给默认路径 nginx.ingress.kubernetes.io/rewrite-target: /$1 spec: tls: - hosts: - dev.app.com secretName: tls-secret-con rules: - host: dev.app.com http: paths: - path: /path2(/|$)(.*) pathType: ImplementationSpecific backend: service: name: path2svc port: number: 80 # 为该路径单独指定rewrite-target,使用第二个捕获组 annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 - path: /(.*) pathType: ImplementationSpecific backend: service: name: path1svc port: number: 80
简化替代方案
如果不需要匹配/path2和/path2/两种格式,可以拆分路径规则,避免复杂正则:
paths: - path: /path2/(.*) pathType: ImplementationSpecific backend: service: name: path2svc port: number: 80 - path: /path2 pathType: ImplementationSpecific backend: service: name: path2svc port: number: 80 - path: /(.*) pathType: ImplementationSpecific backend: service: name: path1svc port: number: 80
内容的提问来源于stack exchange,提问作者gospecomid12
相关产品推荐
相关产品推荐

