蓝绿部署

分享到:

蓝绿部署

[TOC]

蓝绿部署

什么是蓝绿部署

蓝绿(blue/green):新版本与旧版本一起存在,然后切换流量

蓝绿部署流程图

K8S中如何实现蓝绿部署

  • 通过k8s service label标签来实现蓝绿发布
  • 通过Ingress 控制器来实现蓝绿发布
  • 通过Istio来实现蓝绿发布,或者像Istio类似的服务

k8s 蓝绿 yaml 配置

service.yaml 文件

 1
 2apiVersion: v1
 3kind: Service
 4metadata:
 5  name: demo
 6  namespace: default
 7  labels:
 8    app: demo
 9spec:
10  ports:
11    - port: 80
12      targetPort: http
13      protocol: TCP
14      name: http
15  # 注意这里我们匹配 app 和 version 标签,当要切换流量的时候,我们更新 version 标签的值,比如:v2
16  selector:
17    app: demo
18    version: v1

蓝 v1-deploy.yaml 文件

 1apiVersion: apps/v1
 2kind: Deployment
 3metadata:
 4  name: demo1-deployment
 5  namespace: default
 6  labels:
 7    app: demo
 8    version: v1
 9spec:
10  replicas: 1
11  revisionHistoryLimit: 3
12  strategy:
13    rollingUpdate:
14      maxSurge: 30%
15      maxUnavailable: 30%
16  selector:
17    matchLabels:
18      app: demo
19      version: v1
20  template:
21    metadata:
22      labels:
23        app: demo
24        version: v1
25    spec:
26      containers:
27      - name: demo1
28        image: mritd/demo
29        livenessProbe:
30          httpGet:
31            path: /
32            port: 80
33            scheme: HTTP
34          initialDelaySeconds: 30
35          timeoutSeconds: 5
36          periodSeconds: 30
37          successThreshold: 1
38          failureThreshold: 5
39        readinessProbe:
40          httpGet:
41            path: /
42            port: 80
43            scheme: HTTP
44          initialDelaySeconds: 30
45          timeoutSeconds: 5
46          periodSeconds: 10
47          successThreshold: 1
48          failureThreshold: 5
49        ports:
50          - name: http
51            containerPort: 80
52            protocol: TCP

绿 v2-deploy.yaml

 1
 2apiVersion: apps/v1
 3kind: Deployment
 4metadata:
 5  name: demo2-deployment
 6  namespace: default
 7  labels:
 8    app: demo
 9    version: v2
10spec:
11  replicas: 1
12  revisionHistoryLimit: 3
13  strategy:
14    rollingUpdate:
15      maxSurge: 30%
16      maxUnavailable: 30%
17  selector:
18    matchLabels:
19      app: demo
20      version: v2
21  template:
22    metadata:
23      labels:
24        app: demo
25        version: v2
26    spec:
27      containers:
28      - name: demo2
29        image: mritd/demo
30        livenessProbe:
31          httpGet:
32            path: /
33            port: 80
34            scheme: HTTP
35          initialDelaySeconds: 30
36          timeoutSeconds: 5
37          periodSeconds: 30
38          successThreshold: 1
39          failureThreshold: 5
40        readinessProbe:
41          httpGet:
42            path: /
43            port: 80
44            scheme: HTTP
45          initialDelaySeconds: 30
46          timeoutSeconds: 5
47          periodSeconds: 10
48          successThreshold: 1
49          failureThreshold: 5
50        ports:
51          - name: http
52            containerPort: 80
53            protocol: TCP

上面定义的资源对象中,最重要的就是Service 中 label selector的定义:

1  selector:
2    app: demo
3    version: v1

部署与测试

部署v1 v2 deploy服务 和 service服务

1$ kubectl  apply -f service.yaml -f v1-deploy.yaml -f v2-deploy.yaml

测试流量是否到v1版本

1# 登陆任意一个pod,向 demo service 发起请求
2$ while sleep 0.3; do curl http://demo; done
3
4# 输出日志
5Host: demo1-deployment-b5bd596d8-dw27b, Version: v1
6Host: demo1-deployment-b5bd596d8-dw27b, Version: v1

切换入口流量从v1 到 v2

1$ kubectl patch service demo -p '{"spec":{"selector":{"version":"v2"}}}'

测试流量是否到v2版本

1# 登陆任意一个pod,向 demo service 发起请求
2$ while sleep 0.3; do curl http://demo; done
3
4# 输出日志
5Host: demo2-deployment-b5bd596d8-dw27b, Version: v2
6Host: demo2-deployment-b5bd596d8-dw27b, Version: v2

金丝雀

什么是金丝雀发布?

金丝雀发布(Canary):也是一种发布策略,和国内常说的灰度发布是同一类策略。蓝绿部署是准备两套系统,在两套系统之间进行切换,金丝雀策略是只有一套系统,逐渐替换这套系统。

Istio 金丝雀部署

定义 service 服务

 1apiVersion: v1
 2kind: Service
 3metadata:
 4  name: demo4
 5  namespace: test1
 6  labels:
 7    app: demo4
 8spec:
 9  ports:
10    - port: 80
11      targetPort: http
12      protocol: TCP
13      name: http
14  selector:
15    app: demo4

定义两个版本的 deploy 文件,两个版本都包含服务选择标签 app:demo4

 1apiVersion: apps/v1beta1
 2kind: Deployment
 3metadata:
 4  name: demo4-deployment-v1
 5  namespace: test1
 6spec:
 7  replicas: 1
 8  template:
 9    metadata:
10      annotations:
11        # 允许注入 sidecar
12        sidecar.istio.io/inject: "true"
13      labels:
14        app: demo4
15        version: v1
16    spec:
17      containers:
18      - name: demo4-v1
19        image: mritd/demo
20        livenessProbe:
21          httpGet:
22            path: /
23            port: 80
24            scheme: HTTP
25          initialDelaySeconds: 30
26          timeoutSeconds: 5
27          periodSeconds: 10
28          successThreshold: 1
29          failureThreshold: 5
30        readinessProbe:
31          httpGet:
32            path: /
33            port: 80
34            scheme: HTTP
35          initialDelaySeconds: 30
36          timeoutSeconds: 5
37          periodSeconds: 10
38          successThreshold: 1
39          failureThreshold: 5
40        ports:
41          - name: http
42            containerPort: 80
43            protocol: TCP
44
45---
46
47apiVersion: apps/v1beta1
48kind: Deployment
49metadata:
50  name: demo4-deployment-v2
51  namespace: test1
52spec:
53  replicas: 1
54  template:
55    metadata:
56      labels:
57        app: demo4
58        version: v2
59      annotations:
60        sidecar.istio.io/inject: "true"
61    spec:
62      containers:
63      - name: demo4-v2
64        image: mritd/demo
65        livenessProbe:
66          httpGet:
67            path: /
68            port: 80
69            scheme: HTTP
70          initialDelaySeconds: 30
71          timeoutSeconds: 5
72          periodSeconds: 10
73          successThreshold: 1
74          failureThreshold: 5
75        readinessProbe:
76          httpGet:
77            path: /
78            port: 80
79            scheme: HTTP
80          initialDelaySeconds: 30
81          timeoutSeconds: 5
82          periodSeconds: 10
83          successThreshold: 1
84          failureThreshold: 5
85        ports:
86          - name: http
87            containerPort: 80
88            protocol: TCP

上面定义和普通k8s定义蓝绿部署是一样的

设置路由规则来控制流量分配。如将 10% 的流量发送到金丝雀版本(v2)。后面可以渐渐的把所有流量都切到金丝雀版本(v2),只需要修改weight: 10参数,注意v1和v2版本和一定要等于100

 1apiVersion: networking.istio.io/v1alpha3
 2kind: VirtualService
 3metadata:
 4  name: demo4-vs
 5  namespace: test1
 6spec:
 7  hosts:
 8  - demo4.a.com
 9  gateways:
10  - demo4-gateway
11  http:
12  - route:
13    - destination:
14        host: demo4.test1.svc.cluster.local
15        subset: v1
16      weight: 90
17    - destination:
18        host: demo4.test1.svc.cluster.local
19        subset: v2
20      weight: 10
21
22---
23
24apiVersion: networking.istio.io/v1alpha3
25kind: DestinationRule
26metadata:
27  name: demo4
28  namespace: test1
29spec:
30  host: demo4.test1.svc.cluster.local
31  subsets:
32  - name: v1
33    labels:
34      version: v1
35  - name: v2
36    labels:
37      version: v2

当规则设置生效后,Istio 将确保只有 10% 的请求发送到金丝雀版本,无论每个版本的运行副本数量是多少。

高层次的金丝雀部署

只允许特定网站上50%的用户流量路由到金丝雀(v2)版本,而其他用户则不受影响

 1
 2apiVersion: networking.istio.io/v1alpha3
 3kind: VirtualService
 4metadata:
 5  name: demo4-vs
 6  namespace: test1
 7spec:
 8  hosts:
 9  - demo4.a.com
10  gateways:
11  - demo4-gateway
12  http:
13  - match:
14    - headers:
15        cookie:
16          regex: "^(.*?;)?(email=[^;]*@some-company-name.com)(;.*)?$"
17    route:
18    - destination:
19        host: demo4.test1.svc.cluster.local
20        subset: v1
21        weight: 50
22    - destination:
23        host: demo4.test1.svc.cluster.local
24        subset: v2
25        weight: 50
26  - route:
27    - destination:
28        host: demo4.test1.svc.cluster.local
29        subset: v1

VirtualService 与 DestinationRule 解释

  • Istio Virtual Service,用于控制当前deployment和金丝雀deployment流量分配的权重
  • Istio Destination Rule,包含当前deployment和金丝雀deployment的子集(subset)
  • Istio Gateway(可选),如果服务需要从容器集群外被访问则需要搭建gateway

参考

https://archive.istio.io/v1.2/zh/docs/tasks/traffic-management/request-routing/ https://archive.istio.io/v1.2/zh/blog/2017/0.1-canary/