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



场景-

我有两个部署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

代码文件可以在这里找到

问题-

当我尝试访问上的此入口网关IP时http://ingress-gateway-ip/v1/favicon.ico,我在控制台中遇到一个404错误,说http://ingress-gateway-ip/favicon.ico找不到(因为这已经被重写为"/"(而且样式和js在这条路径上也不存在。但是当我想去拜访的时候http://ingress-gateway-ip/v1/favicon.ico我可以看到favicon图标以及所有的js和样式

请在这里找到问题的屏幕截图

预期-

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

第1版:

  1. 添加了原始代码中的代码片段
  2. 添加了代码文件链接

第2版:

  1. 添加了问题的屏幕截图
  2. 修改了问题陈述,以便清晰理解

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

我认为你的问题是你的DestinationRule,在v2名称中,你的标签是version: v1,应该是version: v2,这就是为什么你从/v1和/v2发出的请求只发送到pod的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

当我尝试访问这个入口网关IP时,我在控制台中遇到一个404错误,上面写着http://ingress-gateway-ip/favicon.ico

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

如果你想访问,那么你必须为/添加另一个匹配项

- match:
- uri:
prefix: /
route:
- destination:
host: test-1

有一个2个nginx吊舱的工作示例,请看一下。

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

编辑

问题是所有的样式和js都不能被浏览器在"当它们被重新写入时

@Rinor在这里已经解释过了

我想在这里添加这个Istio实践教程,它很好地解释了处理这个问题的一种方法,即为您的依赖项(js、css等(添加更多路径。

让我们分解一下应该路由到Frontend:的请求

精确路径/应该路由到前端以获得Index.html

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

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

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

如果你还有什么问题,请告诉我。

最新更新