nginx ingress & rewrite-target

前端 未结 2 1443
情歌与酒
情歌与酒 2020-12-14 03:02

I have a pod that responds to requests to /api/

I want to do a rewrite where requests to /auth/api/ go to /api/.

Using an Ingress (nginx), I thought that wit

相关标签:
2条回答
  • 2020-12-14 03:32

    I have created the following example that works and which I will explain. To run this minimal example, run these commands:

    $ 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
    

    As you'll notice, the ingress rewrite annotation appears to be very particular about trailing slashes. If a trailing slash is not present, the request will not be rewritten. However, if a trailing slash is provided, the request uri will be rewritten and your proxy will function as expected.

    After inspecting the generated nginx.conf file from inside the ingress controller, the line of code responsible for this behavior is:

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

    This line tells us that only requests matching the first argument will be rewritten with the path specified by the second argument.

    I believe this is bug worthy.

    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))
    }
    
    0 讨论(0)
  • 2020-12-14 03:47

    I don't know if this is still an issue, but since version 0.22 it seems you need to use capture groups to pass values to the rewrite-target value From the nginx example available here

    Starting in Version 0.22.0, ingress definitions using the annotation nginx.ingress.kubernetes.io/rewrite-target are not backwards compatible with previous versions. In Version 0.22.0 and beyond, any substrings within the request URI that need to be passed to the rewritten path must explicitly be defined in a capture group.

    For your specific needs, something like this should do the trick

    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
    
    0 讨论(0)
提交回复
热议问题