警告
本文最后更新于 2021-10-21 00:27,文中内容可能已过时。
背景
当我们有两个virtualservice并且路由匹配都是使用match.uri.prefix,第一个路由r1是匹配/it前缀,第二个路由r2匹配/item前缀。
这时你会发现无论是访问/it、/it/、/it/xxx,/item,/item/,/item/xx都会匹配到r1对应的服务。
由于vs不支持priority,可以通过下面几种方法解决
- 合并virtualservice(推荐)
- 使用regex匹配路由
- 写一个prefix: /it/ 一个exact: /it
下面使用regex的方式来解决这个问题。
一、部署测试服务
部署两个nginx服务用于测试路由
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
| apiVersion: apps/v1
kind: Deployment
metadata:
name: n1
namespace: istio-demo
spec:
replicas: 1
selector:
matchLabels:
app: nginx
version: v1
template:
metadata:
labels:
app: nginx
version: v1
spec:
containers:
- name: nginx
image: nginx:1.14-alpine
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: n1-svc
namespace: istio-demo
spec:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
selector:
app: nginx
version: v1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: n2
namespace: istio-demo
spec:
replicas: 1
selector:
matchLabels:
app: nginx
version: v2
template:
metadata:
labels:
app: nginx
version: v2
spec:
containers:
- name: nginx
image: nginx:1.14-alpine
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: n2-svc
namespace: istio-demo
spec:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
selector:
app: nginx
version: v2
|
上面只是单纯的创建了两个nginx应用和两个service,后面通过浏览器访问,观察nginx日志来确认流量进入了哪个应用
二、配置有问题的路由规则
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: r1
namespace: istio-demo
spec:
gateways:
- istio-system/public-gateway
hosts:
- 'n1-svc'
- 'headers.t.cn'
http:
- route:
- destination:
host: n1-svc
match:
- uri:
prefix: '/it'
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: r2
namespace: istio-demo
spec:
gateways:
- istio-system/public-gateway
hosts:
- 'n2-svc'
- 'headers.t.cn'
http:
- route:
- destination:
host: n2-svc
match:
- uri:
prefix: /item
|
测试访问情况:
- 首先打开两个控制台观察pod的日志
- 在浏览器访问/it、/it/、/it/xxx、/item、/item/、/item/xxx均访问到n1服务上(n2服务的规则失效)
- 删除n1的路由匹配规则,此时/item、/item/、/item/xxx均访问到n2服务上
解决方法
修改prefix为regex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: r1
namespace: istio-demo
spec:
gateways:
- istio-system/public-gateway
hosts:
- 'n1-svc'
- 'headers.t.cn'
http:
- route:
- destination:
host: n1-svc
match:
- uri:
# 匹配/it/开头或/it的uri
regex: '(\/it\/.*)|(\/it\/?)'
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: r2
namespace: istio-demo
spec:
gateways:
- istio-system/public-gateway
hosts:
- 'n2-svc'
- 'headers.t.cn'
http:
- route:
- destination:
host: n2-svc
match:
- uri:
# 匹配/item/开头或/item的uri,这里其实不改也可以,因为r1路由已经不会影响到r2路由了
regex: '(\/item\/.*)|(\/item\/?)'
|
经测试
访问/it、/it/、/it/xxx会路由到n1应用
访问/item、/item/、/item/xxx会路由到n2应用