web-dev-qa-db-ja.com

nginxイングレスと書き換えターゲット

/ api /へのリクエストに応答するポッドがあります

/ 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 /がservice/podに渡され、404が正しくスローされています。書き換えアノテーションを誤解しているに違いありません。

K8とイングレスでこれを行う方法はありますか?

8
matt

動作する次の例を作成しました。これについて説明します。この最小限の例を実行するには、次のコマンドを実行します。

$ 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;

この行は、最初の引数に一致するリクエストのみが、2番目の引数で指定されたパスで書き換えられることを示しています。

これはバグに値すると信じています。

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))
}
16
frankgreco

これがまだ問題かどうかはわかりませんが、バージョン0.22以降、キャプチャグループを使用して値をrewrite-target値に渡す必要があるようです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
9
Kerruba