【问题标题】:nginx ingress & rewrite-targetnginx 入口和重写目标
【发布时间】:2018-05-29 22:39:12
【问题描述】:

我有一个响应 /api/ 请求的 pod

我想重写对 /auth/api/ 的请求转到 /api/ 的位置。

使用 Ingress (nginx),我认为使用 ingress.kubernetes.io/rewrite-target: 注释我可以这样做:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: myapi-ing
  annotations:
    ingress.kubernetes.io/rewrite-target: /api
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: api.myapp.com
    http:
      paths:
      - path: /auth/api
        backend:
          serviceName: myapi
          servicePort: myapi-port

然而,正在发生的事情是 /auth/ 正在传递给服务/pod,并且正确地抛出了 404。我一定是误解了重写注释。

有没有办法通过 k8s & ingresses 做到这一点?

【问题讨论】:

    标签: nginx kubernetes nginx-ingress


    【解决方案1】:

    我不知道这是否仍然是一个问题,但从 0.22 版开始,您似乎需要使用捕获组将值传递给重写目标值 来自 nginx 示例可用here

    从 0.22.0 版本开始,使用注解 nginx.ingress.kubernetes.io/rewrite-target 的入口定义不向后兼容以前的版本。在 0.22.0 及更高版本中,请求 URI 中需要传递到重写路径的任何子字符串都必须在捕获组中明确定义。

    对于您的特定需求,这样的事情应该可以解决问题

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: myapi-ing
    annotations:
      ingress.kubernetes.io/rewrite-target: /api/$2
      kubernetes.io/ingress.class: "nginx"
    spec:
     rules:
     - host: api.myapp.com
       http:
        paths:
         - path: /auth/api(/|$)(.*)
           backend:
             serviceName: myapi
             servicePort: myapi-port
    

    【讨论】:

    • 谢谢,我不得不使用新的apiVersion: networking.k8s.io/v1beta1nginx.ingress.kubernetes.io/rewrite-target
    【解决方案2】:

    我创建了以下示例,我将对其进行解释。要运行这个最小示例,请运行以下命令:

    $ minikube start  
    $ minikube addons enable ingress # might take a while for ingress pod to bootstrap  
    $ kubectl apply -f kubernetes.yaml 
    $ curl https://$(minikube ip)/auth/api/ --insecure
    success - path: /api/
    $ curl https://$(minikube ip)/auth/api --insecure
    failure - path: /auth/api
    $ curl https://$(minikube ip)/auth/api/blah/whatever --insecure
    success - path: /api/blah/whatever
    

    您会注意到,入口重写注释似乎对尾部斜杠非常特别。如果不存在尾部斜杠,则不会重写请求。但是,如果提供了尾部斜杠,则请求 uri 将被重写,并且您的代理将按预期运行。

    从入口控制器内部检查生成的nginx.conf 文件后,负责此行为的代码行是:

    rewrite /auth/api/(.*) api/$1 break;
    

    这一行告诉我们只有匹配第一个参数的请求才会被第二个参数指定的路径重写。

    我相信这是值得的错误。

    kubernetes.yaml

    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: ingress-rewite-example
    spec:
      selector:
        app: ingress-rewite-example
      ports:
      - name: nginx
        port: 80
        protocol: TCP
        targetPort: 80
      type: NodePort
    
    ---
    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
      name: ingress-rewite-example
    spec:
      template:
        metadata:
          labels:
            app: ingress-rewite-example
        spec:
          containers:
          - name: ingress-rewite-example
            image: fbgrecojr/office-hours:so-47837087
            imagePullPolicy: Always
            ports:
            - containerPort: 80
    
    ---
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: ingress-rewite-example
      annotations:
        ingress.kubernetes.io/rewrite-target: /api
        kubernetes.io/ingress.class: "nginx"
    spec:
      rules:
      - http:
          paths:
          - path: /auth/api
            backend:
              serviceName: ingress-rewite-example
              servicePort: 80
    

    main.go

    package main
    
    import (
      "fmt"
      "strings"
      "net/http"
    )
    
    func httpHandler(w http.ResponseWriter, r *http.Request) {
      var response string
      if strings.HasPrefix(r.URL.Path, "/api") {
        response = "success"
      } else {
        response = "failure"
      }
      fmt.Fprintf(w, response + " - path: " + r.URL.Path + "\n")
    }
    
    func main() {
        http.HandleFunc("/", httpHandler)
        panic(http.ListenAndServe(":80", nil))
    }
    

    【讨论】:

    • 有趣 - 如果我添加到 url:curl https://$(minikube ip)/auth/api/blah/whatever 它也没有捕捉到它
    • @matt 您在评论中提供的示例工作正常(请参阅我更新的示例)。请注意,我正在运行 NGINX 入口控制器的 0.9.0-beta.15 版本和 Kubernetes 的 v1.8.0。
    • 您好,您在哪里找到文件 nginx.conf ?干杯
    • @GiovanniVigorelli k8s 入口控制器的工作方式是每次添加新入口资源时都会动态重新创建 nginx.conf。因此,要查看配置,请应用原始问题中的入口资源,然后执行到 nginx 入口控制器 pod 并找出当前 nginx.conf 的内容。
    • 在 nginx-ingress-1.4.0 版本上,您必须指定 nginx.ingress.kubernetes.io/rewrite-target: /api(注意前面的 nginx。)
    猜你喜欢
    • 2020-08-17
    • 2020-10-13
    • 2020-07-25
    • 2018-05-27
    • 2020-12-15
    • 1970-01-01
    • 2020-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多