nginx ingress&重写目标

时间:2017-12-15 17:22:37

标签: nginx kubernetes

我有一个响应对/ api /

的请求的pod

我想重写/ auth / api /请求/ api /.

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

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&入节点?

2 个答案:

答案 0 :(得分:10)

我创建了以下示例,该示例有效,我将解释。要运行此最小示例,请运行以下命令:

$ 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))
}

答案 1 :(得分: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