Istio 实现灰度发布
一、部署bookinfo微服务示例
Bookinfo 应用分为四个单独的微服务: - productpage : productpage 微服务会调用 details 和 reviews 两个微服务,用来生成页面。 - details :这个微服务包含了书籍的信息。 - reviews :这个微服务包含了书籍相关的评论。它还会调用ratings 微服务。 - ratings : ratings 微服务中包含了由书籍评价组成的评级信息。
reviews 微服务有 3 个版本: - v1 版本不会调用 ratings 服务。 - v2 版本会调用 ratings 服务,并使用 5个黑色五角星来显示评分信息。 - v3 版本会调用 ratings 服务,并使用5个红色五角星 来显示评分信息。
1.1、部署
kubectl create ns bookinfo
kubectl label namespace bookinfo istio-injection=enabled # 针对命名空间注入
cd istio-1.4.2/samples/bookinfo
kubectl apply -f platform/kube/bookinfo.yaml -n bookinfo
kubectl get pod -n bookinfo # 等待正常启动后会有2个pod(一个服务,一个sidecar的注入)
kubectl apply -f networking/bookinfo-gateway.yaml -n bookinfo # 两个服务Gateway和VirtualService
访问地址: http://192.168.171.12:32217/productpage
一旦部署完毕,刷新前端就可以看到3个版本是一直在轮训被展示的!
为了模拟现实工作的场景,我这边nginx的虚机IP是:192.168.171.10
nginx.conf
upstream ingressgateway {
server 192.168.171.12:32217;
server 192.168.171.13:32217;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://ingressgateway;
proxy_set_header Host $Host; # 使用请求头来分流
proxy_http_version 1.1; # nginx默认是1.0
}
如上这种方式虽然是都可以访问,但是不是我们最终的目的,必须要实现不同的域名访问不同的后端;
更改httbin这个服务的http-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- "httpbin.zhdya.cn" # * 修改为域名
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "bookinfo.zhdya.cn"
kubectl apply -f bookinfo-gateway.yaml -n bookinfo
kubectl apply -f http-gateway.yaml
再次访问就实现了httpbin访问的就是httpbin应用,bookinfo同理;
二、发布方案
主流发布方案: - 蓝绿发布 - 滚动发布 - 灰度发布(金丝雀发布) - A/B Test
2.1、蓝绿发布(早期用的比较广泛)
项目逻辑上分为AB组,在项目升级时,首先把A组从负载均衡中摘除,进行新版本的部署。 B组仍然继续提供服务。 A组升级完成上线, B组从负载均衡中摘除。
特点: - 策略简单 - 升级/回滚速度快 - 用户无感知,平滑过渡
缺点: - 需要 两倍以上服务器资源 - 短时间内浪费一定资源成本 - 故障影响范围大
2.2、滚动发布(K8S默认更新策略)
每次只升级一个或多个服务,升级完成后加入生产环境,不断执行这个过程,直到集群中的全部旧版升级新版本。 Kubernetes的默认发布策略。
特点: - 用户无感知,平滑过渡
缺点: - 部署周期长 - 发布策略较复杂 - 不易回滚
2.3、灰度发布(金丝雀发布)<当前主流方式>
只升级部分服务,即让一部分用户继续用老版本,一部分用户开始用新版本,如果用户对新版本没有什么意见,那么逐步扩大范围,把所有用户都迁移到新版本上面来。
特点: - 保证整体系统稳定性 - 用户无感知,平滑过渡
缺点: - 自动化要求高
2.4、A/B Test(灰度发布的一种)
灰度发布的一种方式,主要对特定用户采样后,对收集到的反馈数据做相关对比,然后根据比对结果作出决策。用来测试应用功能表现的方法,侧重应用的可用性,受欢迎程度等, 最后决定是否升级。
三、Istio实现灰度发布
3.1、基于权重的路由(灰度发布)
需求:
1、流量全部发送到reviews v1版本(不带五角星); # virtual-service-all-v1.yaml
cat networking/virtual-service-all-v1.yaml
···省略
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews # 后端的svc
http:
- route:
- destination: # 流量的转发
host: reviews
subset: v1
···省略
kubectl apply -f networking/virtual-service-all-v1.yaml -n bookinfo
------------
cat networking/destination-rule-all.yaml
···省略
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1 # 选择的标签是v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
···省略
kubectl apply -f networking/destination-rule-all.yaml -n bookinfo
再来看下,刚刚我们线上部署了3套不同版本的应用:
cat platform/kube/bookinfo.yaml
···省略
---
##################################################################################################
# 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.15.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
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.15.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
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.15.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
---
···省略
再次刷新前端页面就会发现,所有的流量一直停留在V1版本!
-----------------
2、将90%的流量发送到reviewsv1版本,另外10%的流量发送到reviewsv2版本(5个黑色五角星),最后完全切换到v2版本。
# cat networking/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 # 90%权重
- destination:
host: reviews
subset: v2
weight: 10
kubectl apply -f networking/virtual-service-reviews-90-10.yaml -n bookinfo
3、将50%的流量发送到v2版本,另外50%的流量发送到v3版本(5个红色五角星)。
# cat networking/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 networking/virtual-service-reviews-v2-v3.yaml -n bookinfo
假如测试没有任何问题,这样我们就可以通过权重调整全部切为V3版本
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v2
weight: 0
- destination:
host: reviews
subset: v3
weight: 100
或者一旦有任何异常,我们可以通过权重直接修改,apply即可!
3.2、基于请求内容的路由(A/B Test)
需求: 1. 将特定用户的请求发送到reviews v2版本(5个黑色五角星),其他用户则不受影响(v3)
# cat networking/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 # 只要是jason这个用户登录就会显示V2版本,其余均是V3版本
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v3
# kubectl apply -f networking/virtual-service-reviews-jason-v2-v3.yaml -n bookinfo
四、总结
实现灰度发布: - 引入服务版本标签(version:v3); - 使用deployment部署,pod标签加上version; - 创建istio资源; - 创建一个灰度版本,version; - 创建DestinationRule规则,关联所有版本(在用版本和灰度版本); - 创建VirtualService规则,路由策略(请求内容,百分比?)
之所以没有被大量应用的主要原因,就是人工修改量太大,误操作概率高,如果把如上全部自动化后,我相信这简直就是和K8S的珠联璧合!!
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!