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

问题描述

场景-

我有2个部署deployment-1label- version:v1deployment-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 访问此Ingress Gateway IP时,我在控制台中遇到404错误提示 http:// {找不到{1}} / favicon.ico (因为已将其重写为“ /”),在此路由中也没有样式和js。但是当我尝试参观 http:// ingress-gateway-ip / ingress-gateway-ip /favicon.ico 我可以看到favicon图标以及所有的js和样式。

请找到问题here

的屏幕截图

期望-

如何使用url中的前缀路由访问这两个服务,这意味着当我导航到/ v1时,只有V1版本不带404,而当我导航到/ v2时,只有V2版本才可以。上吗?

EDIT-1:

  1. 从原始代码添加代码
  2. 添加代码file link

EDIT-2:

  1. 添加了问题的screenshot
  2. 修改后的问题陈述,以便清楚理解

解决方法

如何使用url中的前缀路由访问这两个服务,这意味着当我导航到/ v1时,只有V1版本不带404,而当我导航到/ v2时,只有V2版本才可以。上

我认为您的问题是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

当我尝试访问此Ingress Gateway IP时,我在控制台中遇到404错误,提示http://ingress-gateway-ip/favicon.ico

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

如果要访问,则必须为- match: - uri: prefix: / route: - destination: host: test-1 添加另一个匹配项

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","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

有一个带有2个nginx容器的工作示例,看看吧。

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

卷曲的结果:

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

编辑

问题在于,当重新编​​写样式和js时,浏览器无法在“ /”处读取所有样式和js

@Rinor here

已经对此进行了解释

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

让我们分解应该路由到前端的请求:

确切路径 /应该路由到Frontend以获得Index.html

前缀路径 / static / *应该路由到Frontend以获得前端所需的任何静态文件,例如级联样式表 JavaScript文件

与正则表达式^。*。(ico | png | jpg)$匹配的路径应路由到Frontend,因为它是页面需要显示的图像。

const browser = await pie.connect(app,puppeteer);
const page = await pie.getPage(browser,win);  

让我知道您是否还有其他问题。