官方文档:Istio / 流量转移

前提条件:

  • 微服务使用deployment+service部署到集群

1、配置命名空间自动注入sidecar

1
kubectl label namespace default istio-injection=enabled

我这里使用istio官方提供的bookinfo程序演示

2、部署bookinfo示例程序

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
cat > bookinfo.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: details
labels:
  app: details
  service: details
spec:
ports:
- port: 9080
  name: http
selector:
  app: details
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-details
labels:
  account: details
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: details-v1
labels:
  app: details
  version: v1
spec:
replicas: 1
selector:
  matchLabels:
    app: details
    version: v1
template:
  metadata:
    labels:
      app: details
      version: v1
  spec:
    serviceAccountName: bookinfo-details
    containers:
    - name: details
      image: docker.io/istio/examples-bookinfo-details-v1:1.18.0
      imagePullPolicy: IfNotPresent
      ports:
      - containerPort: 9080
---
apiVersion: v1
kind: Service
metadata:
name: ratings
labels:
  app: ratings
  service: ratings
spec:
ports:
- port: 9080
  name: http
selector:
  app: ratings
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-ratings
labels:
  account: ratings
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ratings-v1
labels:
  app: ratings
  version: v1
spec:
replicas: 1
selector:
  matchLabels:
    app: ratings
    version: v1
template:
  metadata:
    labels:
      app: ratings
      version: v1
  spec:
    serviceAccountName: bookinfo-ratings
    containers:
    - name: ratings
      image: docker.io/istio/examples-bookinfo-ratings-v1:1.18.0
      imagePullPolicy: IfNotPresent
      ports:
      - containerPort: 9080
---
apiVersion: v1
kind: Service
metadata:
name: reviews
labels:
  app: reviews
  service: reviews
spec:
ports:
- port: 9080
  name: http
selector:
  app: reviews
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-reviews
labels:
  account: reviews
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v1
labels:
  app: reviews
  version: v1
spec:
replicas: 1
selector:
  matchLabels:
    app: reviews
    version: v1
template:
  metadata:
    labels:
      app: reviews
      version: v1
  spec:
    serviceAccountName: bookinfo-reviews
    containers:
    - name: reviews
      image: docker.io/istio/examples-bookinfo-reviews-v1:1.18.0
      imagePullPolicy: IfNotPresent
      env:
      - name: LOG_DIR
        value: "/tmp/logs"
      ports:
      - containerPort: 9080
      volumeMounts:
      - name: tmp
        mountPath: /tmp
      - name: wlp-output
        mountPath: /opt/ibm/wlp/output
    volumes:
    - name: wlp-output
      emptyDir: {}
    - name: tmp
      emptyDir: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v2
labels:
  app: reviews
  version: v2
spec:
replicas: 1
selector:
  matchLabels:
    app: reviews
    version: v2
template:
  metadata:
    labels:
      app: reviews
      version: v2
  spec:
    serviceAccountName: bookinfo-reviews
    containers:
    - name: reviews
      image: docker.io/istio/examples-bookinfo-reviews-v2:1.18.0
      imagePullPolicy: IfNotPresent
      env:
      - name: LOG_DIR
        value: "/tmp/logs"
      ports:
      - containerPort: 9080
      volumeMounts:
      - name: tmp
        mountPath: /tmp
      - name: wlp-output
        mountPath: /opt/ibm/wlp/output
    volumes:
    - name: wlp-output
      emptyDir: {}
    - name: tmp
      emptyDir: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: reviews-v3
labels:
  app: reviews
  version: v3
spec:
replicas: 1
selector:
  matchLabels:
    app: reviews
    version: v3
template:
  metadata:
    labels:
      app: reviews
      version: v3
  spec:
    serviceAccountName: bookinfo-reviews
    containers:
    - name: reviews
      image: docker.io/istio/examples-bookinfo-reviews-v3:1.18.0
      imagePullPolicy: IfNotPresent
      env:
      - name: LOG_DIR
        value: "/tmp/logs"
      ports:
      - containerPort: 9080
      volumeMounts:
      - name: tmp
        mountPath: /tmp
      - name: wlp-output
        mountPath: /opt/ibm/wlp/output
    volumes:
    - name: wlp-output
      emptyDir: {}
    - name: tmp
      emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: productpage
labels:
  app: productpage
  service: productpage
spec:
ports:
- port: 9080
  name: http
selector:
  app: productpage
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: bookinfo-productpage
labels:
  account: productpage
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: productpage-v1
labels:
  app: productpage
  version: v1
spec:
replicas: 1
selector:
  matchLabels:
    app: productpage
    version: v1
template:
  metadata:
    annotations:
      prometheus.io/scrape: "true"
      prometheus.io/port: "9080"
      prometheus.io/path: "/metrics"
    labels:
      app: productpage
      version: v1
  spec:
    serviceAccountName: bookinfo-productpage
    containers:
    - name: productpage
      image: docker.io/istio/examples-bookinfo-productpage-v1:1.18.0
      imagePullPolicy: IfNotPresent
      ports:
      - containerPort: 9080
      volumeMounts:
      - name: tmp
        mountPath: /tmp
    volumes:
    - name: tmp
      emptyDir: {}
EOF
1
kubectl apply -f bookinfo.yaml

所有pod运行时2/2即为部署成功,sidecar也以容器形式注入到pod内。

3、部署网关

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cat > bookinfo-gateway.yaml << EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
spec:
# The selector matches the ingress gateway pod labels.
# If you installed Istio using Helm following the standard documentation, this would be "istio=ingress"
selector:
  istio: ingressgateway # use istio default controller
servers:
- port:
    number: 8080
    name: http
    protocol: HTTP
  hosts:
  # 允许所有域名通过gateway
  - "*"
EOF
1
kubectl apply -f bookinfo-gateway.yaml

4、部署前端virtual service

这里的前端指的时发送请求的服务,可以是中间件也可以是后端的接口,我这里使用productpage服务

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
cat > virtual-service-productpage.yaml << EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
# 访问时服务使用的域名,*表示允许所有访问
- "*"
# 外部访问时需要指定gateways,选择入口网关
gateways:
- bookinfo-gateway
http:
# 匹配规则
- match:
  - uri:
      # uri 完全 匹配时走下面路由
      exact: /productpage
  - uri:
      # uri 前缀 匹配时走下面路由
      prefix: /static
  - uri:
      exact: /login
  - uri:
      exact: /logout
  - uri:
      prefix: /api/v1/products
  route:
  # 目标路由
  - destination:
      # service名称
      host: productpage
      # service端口
      port:
        number: 9080
EOF
1
kubectl apply -f virtual-service-productpage.yaml

5、访问

通过istio-ingress服务的外部IP访问http://10.20.12.190/productpage,如果没有部署MetalLB可以使用nodeIP+30271(istio-ingress服务80端口的映射端口)访问http://10.20.12.10:30271/productpage

访问后刷新页面,发现reviews服务时每次刷新都会请求不同的版本,这是因为后端服务还没有被纳管,此时的请求是通过productpage请求reviews服务的service返回的

6、创建目标规则

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
cat > destination-rule-all.yaml << EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: productpage
spec:
host: productpage
subsets:
- name: v1
  labels:
    version: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
  labels:
    version: v1
- name: v2
  labels:
    version: v2
- name: v3
  labels:
    version: v3
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: ratings
spec:
host: ratings
subsets:
- name: v1
  labels:
    version: v1
- name: v2
  labels:
    version: v2
- name: v2-mysql
  labels:
    version: v2-mysql
- name: v2-mysql-vm
  labels:
    version: v2-mysql-vm
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: details
spec:
host: details
subsets:
- name: v1
  labels:
    version: v1
- name: v2
  labels:
    version: v2
EOF
1
kubectl apply -f destination-rule-all.yaml

此时将所有服务都设置了规则,按照pod label为version 的识别出来,这一步并不会对请求发生变化,这是为了方便后面调整变化时使用的。

7、创建后端virtual service

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
cat > virtual-service-all-v1.yaml <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: productpage
spec:
hosts:
- productpage
http:
- route:
  - destination:
      host: productpage
      subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
  - destination:
      host: reviews
      subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings
spec:
hosts:
- ratings
http:
- route:
  - destination:
      host: ratings
      subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: details
spec:
hosts:
- details
http:
- route:
  - destination:
      host: details
      subset: v1
EOF
1
kubectl apply -f virtual-service-all-v1.yaml

此时后端服务都被istio纳管,并将路由目标指向v1版本,现在不管怎么请求,reviews服务都是v1版本

8、灰度发布

之前的操作都是为了能模拟一个正常使用的业务,并将服务通过istio的virtual service管理,接下来才是灰度发布的操作

要升级Review服务从v1到v2版本,首先部署这个deployment,这个demo中已经部署了,并且之前访问时也看到了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cat > virtual-service-reviews.yaml << EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
  - reviews
http:
- route:
  - destination:
      host: reviews
      subset: v1
    weight: 80
  - destination:
      host: reviews
      subset: v2
    weight: 20
EOF
1
kubectl apply -f virtual-service-reviews.yaml

再次刷新页面模拟请求,发现80%的流量在v1,20%流量分配到v2

在kiali中也可以看到流量分配情况

运行一段时间再次调整v2流量的比例直到100%流量到v2,这时可以下线v1版本。