当前位置: 首页 > 知识库问答 >
问题:

kubernetes ingress nginx重写部分工作——有时是错误的上下文路径

越狐若
2023-03-14

我正在使用GKE建立简单的Kubernetes集群。我已经将Java Spring boot应用程序设置为Kubernetes部署和服务(使用类型负载平衡器,在端口80上公开)。当直接使用外部IP访问该服务时,该应用程序运行良好。

我还为GKE安装了nginx ingress,并提供了以下ingress资源:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/enable-rewrite-log: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
  name: rewrite
  namespace: default
spec:
  rules:
  - host: "myhost.ddns.net"
    http:
      paths:
      - backend:
          serviceName: app-java
          servicePort: 80
        path: /app-java/?(.*)

从现在起,有趣的事情发生了:

问题1:如果我访问网站在http://myhost.ddns.net/app-java-我只得到超文本标记语言文件,所有其他资源有404(下载尝试从http://myhost.ddns.net/foo.js而不是http://myhost.ddns.net/app-java/foo.js

问题2:如果我访问http://myhost.ddns.net/app-java/-我得到了HTML文件以及所有脚本和图像。然而,当我深入挖掘时,通过POST发送表单内容失败了。它的HTML代码是:

<form action="/select" method="post">

试图访问http://myhost.ddns.net/select而不是http://myhost.ddns.net/app-java/select

我发现这可能与这个问题有很大关系:反向代理背后的Thymeleaf模板(在Spring boot应用程序中)没有正确地形成url。提供的解决方案是编写以下nginx反向代理配置:

location /app-java {
    proxy_pass http://10.0.0.0:80;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $host:$server_port;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Prefix /app-java;
}

然而,我不知道如何将其翻译为入口资源yaml。

如何使用入口修复url重写问题?

编辑:在@HelloWorld的提示之后,我重新组织了应用程序,在/app java上下文路径上提供内容(使用Spring Boot 2属性server.servlet.context path=/app java)。之后,我将重写目标更改为:

nginx.ingress.kubernetes.io/rewrite-target: /app-java/$1

现在它工作得很好。

共有1个答案

何志业
2023-03-14

我看到你正试图让你的浏览器为飞行中的所有路径添加前缀。

我相信你一定误解了X-Forwarded-Prefix的概念,以及反向代理背后的Thymeleaf模板(在Spring boot应用程序中)中描述的任何内容,没有正确形成url,社区成员描述了如何将此头传递给你的应用程序。如果您想尝试一下,看看它是如何工作的,只需将此注释添加到ingress对象即可实现:

nginx.ingress.kubernetes.io/x-forwarded-prefix: "/app-java"

但请注意,这并不能解决你的问题。

当然,您也可以将这些头添加到应用程序的响应中,以便将它们发送到您的浏览器(我相信您希望实现这一点),但浏览器并不关心这些头,所以这样做没有意义。

如果您仍想亲自尝试并证明这一点,可以将此注释添加到ingress对象中:

nginx.ingress.kubernetes.io/configuration-snippet: |
    more_set_headers "X-Forwarded-Prefix: /app-java";

据我所知,解决这个问题的唯一方法是修改应用程序代码,使其以正确的路径响应。

您可以发现,许多应用程序使用可自定义的基本路径,可以通过env变量、配置文件或cli参数进行配置。

 类似资料:
  • 我正在尝试使用sping-boot-starter-webflow和reactive Netty创建sping-boot-2 REST api。我正在尝试根据要在Spring-Boot-2中定义的application.yml中定义的新属性设置上下文路径。 然而,它看起来像网络流量,Netty不使用/识别application.yml.中定义的这个属性 如果我使用spring boot start

  • 如果我从application.properties中删除server.context-path=/api/v1。然后,对http://localhost:8080/test的HEAD请求按预期工作。 谢谢你的帮助,马丁

  • 我有以下GitHub操作的文件(删除了一些代码,以便更容易理解这个问题): 我经历了以下步骤: 在分支上进行一些提交,并推动这些更改 我期望GitHub Actions在第2项之后运行测试和部署阶段作业。但是相反,它只是再次运行,而没有运行。 如上所述,即使在推送到之后,它仍然在分支上运行,而不是在分支上运行。我有点假设这可能是由于一些奇怪的行为与快进合并。但是GitHub显然意识到我推动了,因为

  • 我刚刚在我的Android应用程序中安装了Firebase,以启用推送通知。我通过从Firebase控制台向所有运行该应用程序的设备发送推送通知来确认它正在工作。现在,我正在尝试获取FCM令牌(应用程序实例的唯一标识符),以便可以向特定设备发送消息。然而,当我在扩展FirebaseMessagingService的类中重写onNewToken()函数时,该方法不会被重写。根据文件,它应该可以工作。

  • 我试图做一个重写,如果页面不存在,它重写到一个类别页面。它与普通的ReWriteCond%{REQUEST_FILENAME}-f有点不同,因为页面名称是基于URL动态的。 如果有人访问动态路径名称,如“/联系人” 我首先希望它检查以下文件夹/文件是否存在基于路径名称: 例如: 如果不存在,重写到以下页面 例如: 我已经尝试了下面的方法,但是当文件存在并直接进入类别重写时,第一个重写规则触发失败。

  • 问题内容: 给定此目录树: 编译file.cpp与VS一起使用,在gcc中失败。 标准怎么说? 如果路径区分大小写,这为什么明智? 最佳实践是什么,将所有文件/文件夹名都小写,并在包含时做同样的事情? 谢谢。 问题答案: 区分大小写取决于操作系统。Windows不区分大小写。Linux是。 编辑: 实际上,正如MartinYork的评论所观察到的,区分大小写取决于文件系统。默认情况下,Window