istio模拟灰度发布
istio功能简介
Istio是一个开源的服务网格平台,用于管理和连接容器化应用程序的微服务。它提供了一系列功能,包括:
-
流量管理:Istio可以控制和路由应用程序的流量,实现灰度发布、A/B测试、故障恢复等功能。
-
安全性:Istio提供了强大的安全功能,包括身份认证、授权、访问控制和加密通信,以保护应用程序的安全性。
-
观察性:Istio可以收集和展示应用程序的运行时数据,如请求流量、延迟、错误率等,帮助开发人员进行故障排查和性能优化。
-
策略和配额:Istio允许定义和实施各种策略和配额,如限制每秒请求数、设置访问控制规则等。
-
故障注入和测试:Istio提供了故障注入的功能,可以模拟网络延迟、错误响应等情况,以测试应用程序的容错能力。
总之,Istio可以帮助开发人员更好地管理和监控微服务架构,提供更好的安全性、可观察性和流量控制能力。
下面使用官方文档的例子做验证,所有资源文件部署在default
namespace下
模拟部分流量管理功能
- 给命名空间添加标签
# 指示 Istio 在部署应用的时候,自动注入 Envoy 边车代理
$ kubectl label namespace default istio-injection=enabled
- 部署istio gateway,作为流量入口,一个k8s集群只需要一个网关
bookinfo-gateway.yaml
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: 80
name: http
protocol: HTTP
#如果配置具体域名,需要通过域名访问,域名可在本机hosts配置,如果配置*则可用ip或域名访问
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
$ kubectl apply -f bookinfo-gateway.yaml
- 部署bookinfo应用
bookinfo.yaml
# Copyright Istio Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##################################################################################################
# This file defines the services, service accounts, and deployments for the Bookinfo sample.
#
# To apply all 4 Bookinfo services, their corresponding service accounts, and deployments:
#
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
#
# Alternatively, you can deploy any resource separately:
#
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l service=reviews # reviews Service
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l account=reviews # reviews ServiceAccount
# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l app=reviews,version=v3 # reviews-v3 Deployment
##################################################################################################
##################################################################################################
# Details service
##################################################################################################
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
---
##################################################################################################
# Ratings service
##################################################################################################
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
---
##################################################################################################
# Reviews service
##################################################################################################
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: {}
---
##################################################################################################
# Productpage services
##################################################################################################
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: {}
---
$ kubectl apply -f bookinfo.yaml
$ kubectl get pods

一个productpage
前端和details
、ratings
、reviews
后端接口服务,reviews
部署了3个版本
我们现在没有创建任何目标规则,一个请求从gateway-->k8s service-->POD,reviews三个版本labels.app
相同,
默认每次请求productpage
服务会轮训调用三个版本的reviews
# 设置 EXTERNAL-IP 的值之后, 您的环境就有了一个外部的负载均衡器,
# 可以将其用作入站网关。 但如果 EXTERNAL-IP 的值为 <none> (或者一直是 <pending> 状态),
# 则您的环境则没有提供可作为入站流量网关的外部负载均衡器。
# 在这个情况下,您还可以用服务(Service)的节点端口访问网关。
$ kubectl get svc istio-ingressgateway -n istio-system
# 查看Service IP和应用端口
$ kubectl get svc
我这里有EXTERNAL-IP
我就用http://${EXTERNAL-IP}/productpage
在浏览器访问,
否则就用http://${CLUSTER-IP}:9080/productpage
(需要再集群任意一台机器上访问)

红色框显示当前提供服务的是哪个版本的reviews
,多次刷新发现会在 v1 v2 v3之间变化
- 设置每个版本的子集
subsets
,可以为不同版本指定不同的负载均衡算法
distination-rule-reviews.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
trafficPolicy:
loadBalancer:
simple: RANDOM
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
# trafficPolicy:
# loadBalancer:
# simple: ROUND_ROBIN
- name: v3
labels:
version: v3
$ kubectl apply -f distination-rule-reviews.yaml
- 测试-reviews v2和v3版本各50%权重
virtual-service-reviews-v2-v3.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v2
weight: 50
- destination:
host: reviews
subset: v3
weight: 50
$ kubectl apply -f virtual-service-reviews-v2-v3.yaml
浏览器多次刷新,发现右下角reviews
版本在v2 v3之间切换,总体上权重维持1:1
- 测试-reviews v1和v2版本各权重90:10权重
virtual-service-reviews-90-10.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
weight: 90
- destination:
host: reviews
subset: v2
weight: 10
$ kubectl apply -f virtual-service-reviews-90-10.yaml
浏览器多次刷新,发现右下角reviews
版本在v1 v2之间切换,总体上权重维持9:1
- 测试-把权重全部给到v3
virtual-service-reviews-v3.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v3
$ kubectl apply -f virtual-service-reviews-v3.yaml
浏览器多次刷新,发现右下角reviews
版本保持v3;经过上面5、6、7三个步骤我们就明白了如何控制灰度发布
- 测试-带有特征的流量转发
有时为了验证新版本需要把带有指定特征的流量导入到新版本,无特征的流量继续访问老版本
virtual-service-reviews-jason-v2-v3.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v3
$ kubectl apply -f virtual-service-reviews-jason-v2-v3.yaml
如果请求头带有end-user:jason
,就把流量转到v2版本,否则流量转到v3,这里的exact
代表全匹配模式,
还可以指定prefix、正则表达式等支持的匹配模式;此时我们多次刷新页面发现都是v3版本,我们在右上角登录
jason
用户(密码可不填),再次刷新页面发现都是v2版本;通过查看productpage
服务日志发现请求reviews
接口带了end-user:jason
请求头

Istio中的"match"用于定义流量管理规则,以便对特定的请求进行匹配和操作。以下是一些常见的匹配模式:
-
URI匹配:可以基于请求的URI路径进行匹配,例如
/api/v1/users/*
。 -
方法匹配:可以基于HTTP方法(GET、POST等)进行匹配。
-
主机匹配:可以基于请求的主机名进行匹配,例如
example.com
。 -
标头匹配:可以基于请求的标头进行匹配,例如
x-request-id=123456
。 -
标签匹配:可以基于Kubernetes标签进行匹配,例如
version=v1
。 -
端口匹配:可以基于请求的端口号进行匹配。
这些匹配模式可以组合使用,以创建更复杂的匹配规则。例如,可以使用URI匹配和方法匹配来仅匹配特定路径和HTTP方法的请求。Istio的匹配规则非常灵活,可以根据具体的需求进行定制。
应用部署方案

