如何以正确的方式在 Istio 中重写并避免 404 错误?

How to rewrite in Istio the right way and avoid 404 error?

场景-

我有 2 个部署 deployment-1label- version:v1 以及 deployment-2label- version:v2 都托管在 nodeport service- test-1 下。我已经创建了一个具有两个匹配条件的虚拟服务,如下所示

  - match:
    - uri:
        exact: /v1
    rewrite:
      uri: /
    route:
      - destination:
          host: test-1
          port:
            number: 80
          subset: v1
  - match:
    - uri:
        exact: /v2
    rewrite:
      uri: /
    route:
      - destination:
          host: test-1
          port:
            number: 80
          subset: v2

可以找到代码文件here

问题-

当我尝试在 http://ingress-gateway-ip/v1/favicon.ico 访问此入口网关 IP 时,我在控制台中遇到 404 错误,显示 http://ingress-gateway-ip/favicon.ico 未找到 (因为已将其重写为“/”) 此路由中也没有样式和 js .但是当我尝试访问时 http://ingress-gateway-ip/v1/favicon.ico 我可以看到 favicon 图标以及所有 js 和样式。

求问题截图here

期望-

如何使用 url 中的前缀路由访问这两个服务,这意味着当我导航到 /v1 时,只有 V1 版本应该出现而没有 404,当我导航到 /v2 时,应该只有 V2 版本?

EDIT-1:

  1. 从原始代码中添加了代码片段
  2. 添加代码 file link

EDIT-2:

  1. 添加了screenshot个问题
  2. 为了清楚理解修改了问题陈述

How can I access these two services using a prefix routing in the url, meaning when I navigate to /v1, only the V1 version should come up without 404, and when I navigate to /v2, only the V2 version should come up

我假设你的问题是你的 DestinationRule,在 v2 名称中你的标签是 version: v1,它应该是 version: v2,这就是为什么你来自 /v1 和 /v2 的请求只转到 v1 版本你的豆荚。

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: test-destinationrule
spec:
  host: test-1
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v1 <--- 

应该是

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: test-destinationrule
spec:
  host: test-1
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

When I try to visit this Ingress Gateway IP, I encounter a 404 error in the console saying http://ingress-gateway-ip/favicon.ico

它按设计工作,您没有为 / 指定路径,只是为 /v1/v2

如果您希望能够访问,则必须为 /

添加另一个匹配项
- match:
  - uri:
      prefix: /
  route:
    - destination:
        host: test-1

有2个nginx的工作示例pods,看看。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v1
spec:
  selector:
    matchLabels:
      version: v1
  replicas: 1
  template:
    metadata:
      labels:
        app: frontend
        version: v1
    spec:
      containers:
      - name: nginx1
        image: nginx
        ports:
        - containerPort: 80
        lifecycle:
          postStart:
            exec:
              command: ["/bin/sh", "-c", "echo Hello nginx1 > /usr/share/nginx/html/index.html"]

---


apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v2
spec:
  selector:
    matchLabels:
      version: v2
  replicas: 1
  template:
    metadata:
      labels:
        app: frontend
        version: v2
    spec:
      containers:
      - name: nginx2
        image: nginx
        ports:
        - containerPort: 80
        lifecycle:
          postStart:
            exec:
              command: ["/bin/sh", "-c", "echo Hello nginx2 > /usr/share/nginx/html/index.html"]

---

apiVersion: v1
kind: Service
metadata:
  name: test-1
  labels:
    app: frontend
spec:
  ports:
  - name: http-front
    port: 80
    protocol: TCP
  selector:
    app: frontend

---

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: simpleexample
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - '*'
    port:
      name: http
      number: 80
      protocol: HTTP

---

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: test-virtualservice
spec:
  gateways:
  - simpleexample
  hosts:
  - '*' 
  http:
  - match:
    - uri:
        prefix: /v1
    rewrite:
      uri: /
    route:
      - destination:
          host: test-1
          port:
            number: 80
          subset: v1
  - match:
    - uri:
        prefix: /v2
    rewrite:
      uri: /
    route:
      - destination:
          host: test-1
          port:
            number: 80
          subset: v2

  
---

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: test-destinationrule
spec:
  host: test-1
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

curl 结果:

curl -v ingress-gateway-ip/  
404 Not Found 
there is no path specified for that in virtual service 

curl -v ingress-gateway-ip/v1  
HTTP/1.1 200 OK 
Hello nginx1

curl -v ingress-gateway-ip/v2 
HTTP/1.1 200 OK 
Hello nginx2

编辑

the problem is that all the stylings and js are not readable by the browser at "/" when they are being re-written

@Rinor 已经解释过了

我会在此处添加此 Istio in practise 教程,它很好地解释了处理该问题的方法,即为您的依赖项(js、css 等)添加更多路径。

Let’s break down the requests that should be routed to Frontend:

Exact path / should be routed to Frontend to get the Index.html

Prefix path /static/* should be routed to Frontend to get any static files needed by the frontend, like Cascading Style Sheets and JavaScript files.

Paths matching the regex ^.*.(ico|png|jpg)$ should be routed to Frontend as it is an image, that the page needs to show.

http:
  - match:
    - uri:
        exact: /
    - uri:
        exact: /callback
    - uri:
        prefix: /static
    - uri:
        regex: '^.*\.(ico|png|jpg)$'
    route:
    - destination:
        host: frontend             
        port:
          number: 80

如果您还有其他问题,请告诉我。