zl程序教程

您现在的位置是:首页 >  工具

当前栏目

Devops 发布策略 灰度发布

DevOps 发布 策略 灰度
2023-09-14 09:15:18 时间

灰度/滚动发布


灰度发布是金丝雀发布的延伸,是将发布分成不同的阶段/批次每个阶段/批次的用户数量逐级增加。如果新版本在当前阶段没有发现问题,就再增加用户数量进入下一个阶段,直至扩展到全部用户。

灰度发布可以减小发布风险,是一种零宕机时间的发布策略它通过切换线上并存版本之间的路由权重,逐步从一个版本切换为另一个版本。整个发布过程会持续比较长的时间, 在这段时间内,新旧代码共存,所以在开发过程中,需要考虑版本之间的兼容性,新旧代码共存不能影响功能可用性和用户体验。当新版本代码出现问题时,灰度发布能够比较快的回滚到老版本的代码上。

结合特性开关等技术,灰度发布可以实现更复杂灵活的发布策略。

图片

优势:

  1. 用户体验影响比较小, 不需要停机发布

  2. 能够控制发布风险

劣势:

  1. 发布时间会比较长

  2. 需要复杂的发布系统和负载均衡器

  3. 需要考虑新旧版本共存时的兼容性

适用场景:

  1. 适合可用性较高的生产环境发布

通过注解来实现流量的分发 

灰度也是有一个线上的环境,现在要发灰度的时候,要让一小部分用户去收到这个新版本,这一小部分用户可以通过cooki或者header,或者通过ingress权重的方式去分配。

image.png

  • V1 旧版本正常运行中, 用户请求流量都在V1
  • V2 新版本开始发布, ingress控制, 通过header/cookie/weight 将一部分流量引到V2   10%
  • 更新Ingress ,    流量扩大到30%
  • 更新Ingress ,    流量扩大到60%
  • 更新Ingress ,    流量扩大到90%
  • 更新Ingress ,    流量扩大到100%
  • 此时测试没问题, 用V2 helm chart 部署替换V1旧版本。
[root@master devops]# kubectl get svc -n devops
NAME       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
nginxapp   ClusterIP   10.233.34.137   <none>        80/TCP    46h
nginxnpm   ClusterIP   10.233.18.40    <none>        80/TCP    46h


[root@master devops]# kubectl get pod -n devops
NAME                                   READY   STATUS    RESTARTS   AGE
nginx-npm-blue-6c5ddc9ffd-jl25q        1/1     Running   1          46h
nginx-npm-blue-6c5ddc9ffd-qx2kw        1/1     Running   1          46h
nginx-npm-blue-6c5ddc9ffd-vhtnx        1/1     Running   1          46h
nginxapp-1.20-green-5668c79ff7-9l7kl   1/1     Running   1          46h
nginxapp-1.20-green-5668c79ff7-fckpc   1/1     Running   1          46h
nginxapp-1.20-green-5668c79ff7-vmvq9   1/1     Running   1          46h
[root@master ~]# curl 10.233.18.40  
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>vuedemo</title><link 

href=/static/css/app.30790115300ab27614ce176899523b62.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.2ae2e69a05c33dfc65f8.js></script><script type=text/javascript src=/static/js/vendor.0aad2172a75b8ed4f46c.js></script><script type=text/javascript src=/static/js/app.2f2e5edd9af2c59aa514.js></script></body></html>

[root@master ~]# curl 10.233.34.137
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

现在生产 

[root@master devops]# cat ingress.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginxnpm-ingress
  namespace: devops
spec:
  rules:
  - host: nginxnpm.devops.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginxapp
          servicePort: 80

基于权重的发布(nginx-ingress是支持金丝雀的)


Canary

In some cases, you may want to "canary" a new set of changes by sending a small number of requests to a different service than the production service. The canary annotation enables the Ingress spec to act as an alternative service for requests to route to depending on the rules applied. The following annotations to configure canary can be enabled after nginx.ingress.kubernetes.io/canary: "true" is set:

在某些情况下,您可能希望通过向与生产服务不同的服务发送少量请求来“金丝雀”一组新的更改。canary 注释使 Ingress 规范能够充当请求路由的替代服务,具体取决于应用的规则。设置后可以启用以下配置金丝雀的注释nginx.ingress.kubernetes.io/canary: "true"

  • nginx.ingress.kubernetes.io/canary-weight: The integer based (0 - ) percent of random requests that should be routed to the service specified in the canary Ingress. A weight of 0 implies that no requests will be sent to the service in the Canary ingress by this canary rule. A weight of means implies all requests will be sent to the alternative service specified in the Ingress. <weight-total> defaults to 100, and can be increased via nginx.ingress.kubernetes.io/canary-weight-total.

基于整数 (0 - ) 应路由到金丝雀 Ingress 中指定的服务的随机请求的百分比。权重为 0 表示此金丝雀规则不会向金丝雀入口中的服务发送任何请求。一个重量表示所有请求都将发送到 Ingress 中指定的替代服务。<weight-total>默认为 100,可以通过 增加nginx.ingress.kubernetes.io/canary-weight-total。 

[root@master devops]# cat ingress-weight.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginxapp-canary
  namespace: devops
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "50"
spec:
  rules:
  - host: nginxnpm.devops.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginxnpm
          servicePort: 80

访问同一个页面两次,分别请求到了不同的版本。

 

Header报头流量分发


在访问的时候可以通过请求头进行区分的,比如来自于北京的,那么可以先让来自北京的用户先看到,那么就可以根据请求头里面的信息来匹配。

下面就是北京来的请求访问新版本。

[root@master devops]# cat ingress-header.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginxapp-canary
  namespace: devops
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "Region"
    nginx.ingress.kubernetes.io/canary-by-header-value: "bj"
spec:
  rules:
  - host: nginxnpm.devops.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginxnpm
          servicePort: 80

杭州来的用户访问,流量用的还是老版本

[root@master devops]# for i in {1..2};do curl -H "region: hz" nginxnpm.devops.com && sleep 5s;done
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>


<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

 北京来的用户访问,用的流量是新版本

[root@master devops]# for i in {1..2};do curl -H "region: bj" nginxnpm.devops.com && sleep 5s;done
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>vuedemo</title><link href=/static/css/app.30790115300ab27614ce176899523b62.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.2ae2e69a05c33dfc65f8.js></script><script type=text/javascript src=/static/js/vendor.0aad2172a75b8ed4f46c.js></script><script type=text/javascript src=/static/js/app.2f2e5edd9af2c59aa514.js></script></body></html>

<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>vuedemo</title><link href=/static/css/app.30790115300ab27614ce176899523b62.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.2ae2e69a05c33dfc65f8.js></script><script type=text/javascript src=/static/js/vendor.0aad2172a75b8ed4f46c.js></script><script type=text/javascript src=/static/js/app.2f2e5edd9af2c59aa514.js></script></body></html>[root@master devops]# 

根据cookie流量分发


cookie只有两个值,一个是always(新版本),还有一个是never

[root@master devops]# cat ingress-cookie.yaml 
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginxapp-canary
  namespace: devops
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-cookie: "from"
spec:
  rules:
  - host: nginxnpm.devops.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginxnpm
          servicePort: 80
[root@master devops]#  curl  nginxnpm.devops.com --cookie "from=always"
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>vuedemo</title><link href=/static/css/app.30790115300ab27614ce176899523b62.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.2ae2e69a05c33dfc65f8.js></script><script type=text/javascript src=/static/js/vendor.0aad2172a75b8ed4f46c.js></script><script type=text/javascript src=/static/js/app.2f2e5edd9af2c59aa514.js></script></body></html>[root@master devops]# 
[root@master devops]# 
[root@master devops]# 
[root@master devops]# 
[root@master devops]#  curl  nginxnpm.devops.com --cookie "from=a"
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>