nginx - Kubernetes 多路径重写

标签 nginx kubernetes

好吧,这个问题的各种排列已经被问到了,我觉得问这个问题很糟糕;我正在扔毛巾,很好奇是否有人能指出我正确的方向(或指出我错在哪里)。我继续尝试了一些examples来自文档,但无济于事(见下文)。

我正在尝试使用 Ingress Controller 将流量路由到 Kubernetes 下的适当位置。

服务器设置

我有一个服务器 myserver.com 和三个服务运行在:

myserver.com/services/

myserver.com/services/service_1/

myserver.com/services/service_2/

请注意,我没有(有目的地)对 myserver.com/ 做任何事情。

在这三个位置中的每一个位置,都有一个正在运行的 Web 应用程序。例如,myserver.com/services/service_2需要加载myserver.com/services/service_2/static/css处的css文件,等等...

Kubernetes 入口

为了管理网络,我使用了 Kubernetes Ingress Controller ,我在下面定义了该 Controller 。 CORS 注释并不是 super 相关的,但我将它们包含在内是为了消除任何困惑。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myServices
  namespace: myServices
  annotations:
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, OPTIONS"
    nginx.ingress.kubernetes.io/cors-allow-origin: '$http_origin'
    nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/use-regex: "true"

spec:
  ingressClassName: nginx
  tls:
  - hosts:
      - myserver.com
  rules:
  - host: myserver.com
    http:
      paths:
      - path: /services
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
      - path: /services/service_1(/|$)
        pathType: Prefix
        backend:
          service:
            name: web-service-1
            port:
              number: 80
      - path: /services/service_2(/|$)
        pathType: Prefix
        backend:
          service:
            name: web-service-2
            port:
              number: 80

目标

我注意到一件有用的事情就是给出一些路径示例。从下面的示例来看,路径看起来并没有那么复杂。。我认为这就是我所追求的。请注意,我希望每个服务都能够解析其 css 和图像文件。

myserver.com/services -> myserver.com/services
myserver.com/services/xxx/xxx -> myserver.com/services/xxx/xxx
myserver.com/services/service_1 -> myserver.com/services/service_1
myserver.com/services/service_1/xxx/xxx -> myserver.com/services/service_1/xxx/xxx
myserver.com/services/service_2/xxx/xxx -> myserver.com/services/service_2/xxx/xxx


尝试

我知道这个问题与 nginx.ingress.kubernetes.io/rewrite-target 规则及其与我定义的路径的交互有很大关系。

知道我不想要 nginx.ingress.kubernetes.io/rewrite-target: $1 因为访问 myserver 时会给出 500。 com/services

知道我不想要 nginx.ingress.kubernetes.io/rewrite-target: $1/$2 因为当我访问 myserver.com 时/services/service_1 我实际上获得了在页面上呈现的 myserver.com/services 的部分内容。

SO 尝试 1

我还尝试复制 this 中接受的解决方案问题。

在这次尝试中我设置了

nginx.ingress.kubernetes.io/rewrite-target: "/$1" 以及服务路径之一

- 路径:/(services/service_1(?:/|$).*)

当我访问 myserver.com/services/service_1/xyz 时,会呈现来自 myserver.com/services/service_1 的 HTML。

结论性想法

路径重写和路径规则不太正确。有什么建议吗?

最佳答案

您在最近的评论中报告的问题已通过查看 rewrite example 得到解决。在 nginx-ingress 文档中。

rewrite-target 注释配置入口,以便匹配的路径将被重写为该值。由于您已指定静态值 /,任何与您的入口规则匹配的内容都将被重写为 /,这正是您所看到的行为。

解决方案是捕获我们关心的路径部分,然后在 rewrite-target 注释中使用它。例如:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myservices
  annotations:
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, OPTIONS"
    nginx.ingress.kubernetes.io/cors-allow-origin: '$http_origin'
    nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "false"

spec:
  ingressClassName: nginx
  rules:
  - host: myserver.com
    http:
      paths:
      - path: /services/service_1(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: webservice-service1
            port:
              number: 80
      - path: /services/service_2(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: webservice-service2
            port:
              number: 80
      - path: /services(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: webservice
            port:
              number: 80

在这里,我们修改了匹配表达式,使它们看起来像:

      - path: /services/service_1(/|$)(.*)

第二个捕获组(.*)捕获路径之后的所有内容 字面匹配的部分。然后我们使用该捕获组 ($2, 因为它是第二组)在 rewrite-target 注释中:

    nginx.ingress.kubernetes.io/rewrite-target: /$2

完成此配置后,将请求 /services/service_2 结果:

This is service2.

但是对 /services/service_2/foo/bar 的请求会导致:

<html><head><title>404 Not Found</title></head><body>
<h1>Not Found</h1>
The URL you requested (/foo/bar) was not found.
<hr>
</body></html>

查看后端服务器日志,我们看到:

10.42.0.32 - - [21/Jan/2022:20:33:23 +0000] "GET / HTTP/1.1" 200 211 "" "curl/7.79.1"
10.42.0.32 - - [21/Jan/2022:20:33:45 +0000] "GET /foo/bar HTTP/1.1" 404 311 "" "curl/7.79.1"

我已更新my example repository以匹配此配置。

关于nginx - Kubernetes 多路径重写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70795048/

相关文章:

对 Coindesk 的 Python API 调用返回 403 或 405。如何排除故障?

ssl - Google Cloud Load Balancer - 502 - 非托管实例组未通过健康检查

ruby - 如何使用 nginx proxy_pass 保留请求 url

php - 如何在 Debian 上为 php5-fpm 设置 umask?

typescript - Pulumi 在运行时获取 kubernetes 上下文

kubernetes - 部署重启和终止 Pod 之间的区别

kubernetes - 将多个 Persistent Volume Claim 绑定(bind)到一个挂载路径

php - apache + Varnish + nginx + ssl + wordpress将所有http流量重定向到https

bash - 如何仅使用 bash(无编辑器)创建 Kubernetes YAML 部署对象?

kubernetes:通过 kops 部署时的 CA 文件