Kubernetes

背景介绍

某些情况下,在使用Kubernetes作为业务应用的云平台,想要实现应用的蓝绿部署用来迭代应用版本,用lstio太重太复杂,而且它本身定位于流控和网格治理;Ingress-Nginx在0.21版本引入了Canary功能,可以为网关入口配置多个版本的应用程序,使用annotation来控制多个后端服务的流量分配。

Ingress-Nginx-Annotation Canary 功能介绍

如果想启用Canary功能,要先设置<font style="color:rgb(255, 93, 108);">nginx.ingress.kubernetes.io/canary: "true"</font>,然后可以启用以下注释来配置Canary

<font style="color:rgb(255, 93, 108);">nginx.ingress.kubernetes.io/canary-weight</font> 请求到Canary ingress中指定的服务的请求百分比,值为0-100的整数,根据设置的值来决定大概有百分之多少的流量会分配Canary Ingress中指定的后端s服务

<font style="color:rgb(255, 93, 108);">nginx.ingress.kubernetes.io/canary-by-header</font> 基于request header 的流量切分,适用于灰度发布或者A/B测试,当设定的hearder值为always是,请求流量会被一直分配到Canary入口,当hearder值被设置为never时,请求流量不会分配到Canary入口,对于其他hearder值,将忽略,并通过优先级将请求流量分配到其他规则

<font style="color:rgb(255, 93, 108);">nginx.ingress.kubernetes.io/canary-by-header-value</font> 这个配置要和<font style="color:rgb(255, 93, 108);">nginx.ingress.kubernetes.io/canary-by-header</font> 一起使用,当请求中的hearder keyvalue<font style="color:rgb(255, 93, 108);">nginx.ingress.kubernetes.io/canary-by-header</font> <font style="color:rgb(255, 93, 108);">nginx.ingress.kubernetes.io/canary-by-header-value</font>匹配时,请求流量会被分配到Canary Ingress入口,对于其他任何hearder值,将忽略,并通过优先级将请求流量分配到其他规则

<font style="color:rgb(255, 93, 108);">nginx.ingress.kubernetes.io/canary-by-cookie</font> 这个配置是基于cookie的流量切分,也适用于灰度发布或者A/B测试,当cookie值设置为always时,请求流量将被路由到Canary Ingress入口,当cookie值设置为never时,请求流量将不会路由到Canary入口,对于其他值,将忽略,并通过优先级将请求流量分配到其他规则

金丝雀规则按优先顺序进行如下排序:canary-by-header - > canary-by-cookie - > canary-weight

基于权重的小规模版本测试

v1版本编排文件

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. annotations:
  5. kubernetes.io/ingress.class: nginx
  6. labels:
  7. app: echoserverv1
  8. name: echoserverv1
  9. namespace: echoserver
  10. spec:
  11. rules:
  12. - host: echo.chulinx.com
  13. http:
  14. paths:
  15. - backend:
  16. serviceName: echoserverv1
  17. servicePort: 8080
  18. path: /
  19. ---
  20. kind: Service
  21. apiVersion: v1
  22. metadata:
  23. name: echoserverv1
  24. namespace: echoserver
  25. spec:
  26. selector:
  27. name: echoserverv1
  28. type: ClusterIP
  29. ports:
  30. - name: echoserverv1
  31. port: 8080
  32. targetPort: 8080
  33. ---
  34. apiVersion: extensions/v1beta1
  35. kind: Deployment
  36. metadata:
  37. name: echoserverv1
  38. namespace: echoserver
  39. labels:
  40. name: echoserverv1
  41. spec:
  42. template:
  43. metadata:
  44. labels:
  45. name: echoserverv1
  46. spec:
  47. containers:
  48. - image: mirrorgooglecontainers/echoserver:1.10
  49. name: echoserverv1
  50. ports:
  51. - containerPort: 8080
  52. name: echoserverv1

查看v1版本创建的资源

  1. $ [K8sSj] kubectl get pod,service,ingress -n echoserver
  2. NAME READY STATUS RESTARTS AGE
  3. pod/echoserverv1-657b966cb5-7grqs 1/1 Running 0 24h
  4. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  5. service/echoserverv1 ClusterIP 10.99.68.72 <none> 8080/TCP 24h
  6. NAME HOSTS ADDRESS PORTS AGE
  7. ingress.extensions/echoserverv1 echo.chulinx.com 80 24h

访问v1的服务,可以看到10个请求都是访问到一个pod上也就是v1版本的服务

  1. $ [K8sSj] for i in `seq 10`;do curl -s echo.chulinx.com|grep Hostname;done
  2. Hostname: echoserverv1-657b966cb5-7grqs
  3. Hostname: echoserverv1-657b966cb5-7grqs
  4. Hostname: echoserverv1-657b966cb5-7grqs
  5. Hostname: echoserverv1-657b966cb5-7grqs
  6. Hostname: echoserverv1-657b966cb5-7grqs
  7. Hostname: echoserverv1-657b966cb5-7grqs
  8. Hostname: echoserverv1-657b966cb5-7grqs
  9. Hostname: echoserverv1-657b966cb5-7grqs
  10. Hostname: echoserverv1-657b966cb5-7grqs
  11. Hostname: echoserverv1-657b966cb5-7grqs

创建v2版本的服务

开启canary功能,将v2版本的权重设置为50%,这个百分比并不能精确的将请求平均分配到两个版本的服务,而是在50%上下浮动
  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. annotations:
  5. kubernetes.io/ingress.class: nginx
  6. nginx.ingress.kubernetes.io/canary: "true"
  7. nginx.ingress.kubernetes.io/canary-weight: "50"
  8. labels:
  9. app: echoserverv2
  10. name: echoserverv2
  11. namespace: echoserver
  12. spec:
  13. rules:
  14. - host: echo.chulinx.com
  15. http:
  16. paths:
  17. - backend:
  18. serviceName: echoserverv2
  19. servicePort: 8080
  20. path: /
  21. ---
  22. kind: Service
  23. apiVersion: v1
  24. metadata:
  25. name: echoserverv2
  26. namespace: echoserver
  27. spec:
  28. selector:
  29. name: echoserverv2
  30. type: ClusterIP
  31. ports:
  32. - name: echoserverv2
  33. port: 8080
  34. targetPort: 8080
  35. ---
  36. apiVersion: extensions/v1beta1
  37. kind: Deployment
  38. metadata:
  39. name: echoserverv2
  40. namespace: echoserver
  41. labels:
  42. name: echoserverv2
  43. spec:
  44. template:
  45. metadata:
  46. labels:
  47. name: echoserverv2
  48. spec:
  49. containers:
  50. - image: mirrorgooglecontainers/echoserver:1.10
  51. name: echoserverv2
  52. ports:
  53. - containerPort: 8080
  54. name: echoserverv2

创建v2版本的服务

开启canary功能,将v2版本的权重设置为50%,这个百分比并不能精确的将请求平均分配到两个版本的服务,而是在50%上下浮动
  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. annotations:
  5. kubernetes.io/ingress.class: nginx
  6. nginx.ingress.kubernetes.io/canary: "true"
  7. nginx.ingress.kubernetes.io/canary-weight: "50"
  8. labels:
  9. app: echoserverv2
  10. name: echoserverv2
  11. namespace: echoserver
  12. spec:
  13. rules:
  14. - host: echo.chulinx.com
  15. http:
  16. paths:
  17. - backend:
  18. serviceName: echoserverv2
  19. servicePort: 8080
  20. path: /
  21. ---
  22. kind: Service
  23. apiVersion: v1
  24. metadata:
  25. name: echoserverv2
  26. namespace: echoserver
  27. spec:
  28. selector:
  29. name: echoserverv2
  30. type: ClusterIP
  31. ports:
  32. - name: echoserverv2
  33. port: 8080
  34. targetPort: 8080
  35. ---
  36. apiVersion: extensions/v1beta1
  37. kind: Deployment
  38. metadata:
  39. name: echoserverv2
  40. namespace: echoserver
  41. labels:
  42. name: echoserverv2
  43. spec:
  44. template:
  45. metadata:
  46. labels:
  47. name: echoserverv2
  48. spec:
  49. containers:
  50. - image: mirrorgooglecontainers/echoserver:1.10
  51. name: echoserverv2
  52. ports:
  53. - containerPort: 8080
  54. name: echoserverv2

再次查看创建的资源

  1. $ [K8sSj] kubectl get pod,service,ingress -n echoserver
  2. NAME READY STATUS RESTARTS AGE
  3. pod/echoserverv1-657b966cb5-7grqs 1/1 Running 0 24h
  4. pod/echoserverv2-856bb5758-f9tqn 1/1 Running 0 4s
  5. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  6. service/echoserverv1 ClusterIP 10.99.68.72 <none> 8080/TCP 24h
  7. service/echoserverv2 ClusterIP 10.111.103.170 <none> 8080/TCP 4s
  8. NAME HOSTS ADDRESS PORTS AGE
  9. ingress.extensions/echoserverv1 echo.chulinx.com 80 24h
  10. ingress.extensions/echoserverv2 echo.chulinx.com 80 4s

访问测试

可以看到请求有4个落到v2版本,6个落到v1版本,理论上来说,请求说越多,落到v2版本的请求数越接近设置的权重50%
  1. $ [K8sSj] for i in `seq 10`;do curl -s echo.chulinx.com|grep Hostname;done
  2. Hostname: echoserverv1-657b966cb5-7grqs
  3. Hostname: echoserverv2-856bb5758-f9tqn
  4. Hostname: echoserverv2-856bb5758-f9tqn
  5. Hostname: echoserverv2-856bb5758-f9tqn
  6. Hostname: echoserverv2-856bb5758-f9tqn
  7. Hostname: echoserverv1-657b966cb5-7grqs
  8. Hostname: echoserverv2-856bb5758-f9tqn
  9. Hostname: echoserverv1-657b966cb5-7grqs
  10. Hostname: echoserverv1-657b966cb5-7grqs
  11. Hostname: echoserverv1-657b966cb5-7grqs

基于header的A/B测试

更改v2版本的编排文件

增加headernginx.ingress.kubernetes.io/canary-by-header: “v2”
  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. annotations:
  5. kubernetes.io/ingress.class: nginx
  6. nginx.ingress.kubernetes.io/canary: "true"
  7. nginx.ingress.kubernetes.io/canary-weight: "50"
  8. nginx.ingress.kubernetes.io/canary-by-header: "v2"
  9. labels:
  10. app: echoserverv2
  11. name: echoserverv2
  12. namespace: echoserver
  13. spec:
  14. rules:
  15. - host: echo.chulinx.com
  16. http:
  17. paths:
  18. - backend:
  19. serviceName: echoserverv2
  20. servicePort: 8080
  21. path: /
  22. ---
  23. kind: Service
  24. apiVersion: v1
  25. metadata:
  26. name: echoserverv2
  27. namespace: echoserver
  28. spec:
  29. selector:
  30. name: echoserverv2
  31. type: ClusterIP
  32. ports:
  33. - name: echoserverv2
  34. port: 8080
  35. targetPort: 8080
  36. ---
  37. apiVersion: extensions/v1beta1
  38. kind: Deployment
  39. metadata:
  40. name: echoserverv2
  41. namespace: echoserver
  42. labels:
  43. name: echoserverv2
  44. spec:
  45. template:
  46. metadata:
  47. labels:
  48. name: echoserverv2
  49. spec:
  50. containers:
  51. - image: mirrorgooglecontainers/echoserver:1.10
  52. name: echoserverv2
  53. ports:
  54. - containerPort: 8080
  55. name: echoserverv2

更新访问测试

测试了header 为v2:always v2:never v2:true这三个hearder值,可以看到当hearder为v2:always时,流量会全部流入v2,当v2:never时,流量会全部流入v1,当v2:true时,也就是非always/never,流量会按照配置的权重流入对应版本的服务
  1. $ [K8sSj] kubectl apply -f appv2.yml
  2. ingress.extensions/echoserverv2 configured
  3. service/echoserverv2 unchanged
  4. deployment.extensions/echoserverv2 unchanged
  5. $ [K8sSj] for i in `seq 10`;do curl -s -H "v2:always" echo.chulinx.com|grep Hostname;done
  6. Hostname: echoserverv2-856bb5758-f9tqn
  7. Hostname: echoserverv2-856bb5758-f9tqn
  8. Hostname: echoserverv2-856bb5758-f9tqn
  9. Hostname: echoserverv2-856bb5758-f9tqn
  10. Hostname: echoserverv2-856bb5758-f9tqn
  11. Hostname: echoserverv2-856bb5758-f9tqn
  12. Hostname: echoserverv2-856bb5758-f9tqn
  13. Hostname: echoserverv2-856bb5758-f9tqn
  14. Hostname: echoserverv2-856bb5758-f9tqn
  15. Hostname: echoserverv2-856bb5758-f9tqn
  16. $ [K8sSj] for i in `seq 10`;do curl -s -H "v2:never" echo.chulinx.com|grep Hostname;done
  17. Hostname: echoserverv1-657b966cb5-7grqs
  18. Hostname: echoserverv1-657b966cb5-7grqs
  19. Hostname: echoserverv1-657b966cb5-7grqs
  20. Hostname: echoserverv1-657b966cb5-7grqs
  21. Hostname: echoserverv1-657b966cb5-7grqs
  22. Hostname: echoserverv1-657b966cb5-7grqs
  23. Hostname: echoserverv1-657b966cb5-7grqs
  24. Hostname: echoserverv1-657b966cb5-7grqs
  25. Hostname: echoserverv1-657b966cb5-7grqs
  26. Hostname: echoserverv1-657b966cb5-7grqs
  27. $ [K8sSj] for i in `seq 10`;do curl -s -H "v2:true" echo.chulinx.com|grep Hostname;done
  28. Hostname: echoserverv1-657b966cb5-7grqs
  29. Hostname: echoserverv2-856bb5758-f9tqn
  30. Hostname: echoserverv2-856bb5758-f9tqn
  31. Hostname: echoserverv1-657b966cb5-7grqs
  32. Hostname: echoserverv1-657b966cb5-7grqs
  33. Hostname: echoserverv1-657b966cb5-7grqs
  34. Hostname: echoserverv2-856bb5758-f9tqn
  35. Hostname: echoserverv2-856bb5758-f9tqn
  36. Hostname: echoserverv1-657b966cb5-7grqs
  37. Hostname: echoserverv2-856bb5758-f9tqn

自定义header-value

  1. apiVersion: extensions/v1beta1
  2. kind: Ingress
  3. metadata:
  4. annotations:
  5. kubernetes.io/ingress.class: nginx
  6. nginx.ingress.kubernetes.io/canary: "true"
  7. nginx.ingress.kubernetes.io/canary-weight: "50"
  8. nginx.ingress.kubernetes.io/canary-by-header: "v2"
  9. nginx.ingress.kubernetes.io/canary-by-header-value: "true"
  10. labels:
  11. app: echoserverv2
  12. name: echoserverv2
  13. namespace: echoserver
  14. spec:
  15. rules:
  16. - host: echo.chulinx.com
  17. http:
  18. paths:
  19. - backend:
  20. serviceName: echoserverv2
  21. servicePort: 8080
  22. path: /
  23. ---
  24. kind: Service
  25. apiVersion: v1
  26. metadata:
  27. name: echoserverv2
  28. namespace: echoserver
  29. spec:
  30. selector:
  31. name: echoserverv2
  32. type: ClusterIP
  33. ports:
  34. - name: echoserverv2
  35. port: 8080
  36. targetPort: 8080
  37. ---
  38. apiVersion: extensions/v1beta1
  39. kind: Deployment
  40. metadata:
  41. name: echoserverv2
  42. namespace: echoserver
  43. labels:
  44. name: echoserverv2
  45. spec:
  46. template:
  47. metadata:
  48. labels:
  49. name: echoserverv2
  50. spec:
  51. containers:
  52. - image: mirrorgooglecontainers/echoserver:1.10
  53. name: echoserverv2
  54. ports:
  55. - containerPort: 8080
  56. name: echoserverv2

更新测试

可以看到只有header为v2:never时,请求流量才会流入v2版本,其他值流量都会按照权重设置流入不同版本的服务
  1. $ [K8sSj] kubectl apply -f appv2.yml
  2. ingress.extensions/echoserverv2 configured
  3. service/echoserverv2 unchanged
  4. deployment.extensions/echoserverv2 unchanged
  5. $ [K8sSj] for i in `seq 10`;do curl -s -H "v2:true" echo.chulinx.com|grep Hostname;done
  6. Hostname: echoserverv2-856bb5758-f9tqn
  7. Hostname: echoserverv2-856bb5758-f9tqn
  8. Hostname: echoserverv2-856bb5758-f9tqn
  9. Hostname: echoserverv2-856bb5758-f9tqn
  10. Hostname: echoserverv2-856bb5758-f9tqn
  11. Hostname: echoserverv2-856bb5758-f9tqn
  12. Hostname: echoserverv2-856bb5758-f9tqn
  13. Hostname: echoserverv2-856bb5758-f9tqn
  14. Hostname: echoserverv2-856bb5758-f9tqn
  15. Hostname: echoserverv2-856bb5758-f9tqn
  16. $ [K8sSj] for i in `seq 10`;do curl -s -H "v2:always" echo.chulinx.com|grep Hostname;done
  17. Hostname: echoserverv2-856bb5758-f9tqn
  18. Hostname: echoserverv2-856bb5758-f9tqn
  19. Hostname: echoserverv2-856bb5758-f9tqn
  20. Hostname: echoserverv2-856bb5758-f9tqn
  21. Hostname: echoserverv1-657b966cb5-7grqs
  22. Hostname: echoserverv1-657b966cb5-7grqs
  23. Hostname: echoserverv2-856bb5758-f9tqn
  24. Hostname: echoserverv1-657b966cb5-7grqs
  25. Hostname: echoserverv2-856bb5758-f9tqn
  26. Hostname: echoserverv2-856bb5758-f9tqn
  27. $ [K8sSj] for i in `seq 10`;do curl -s -H "v2:never" echo.chulinx.com|grep Hostname;done
  28. Hostname: echoserverv2-856bb5758-f9tqn
  29. Hostname: echoserverv1-657b966cb5-7grqs
  30. Hostname: echoserverv1-657b966cb5-7grqs
  31. Hostname: echoserverv2-856bb5758-f9tqn
  32. Hostname: echoserverv1-657b966cb5-7grqs
  33. Hostname: echoserverv2-856bb5758-f9tqn
  34. Hostname: echoserverv2-856bb5758-f9tqn
  35. Hostname: echoserverv1-657b966cb5-7grqs
  36. Hostname: echoserverv2-856bb5758-f9tqn
  37. Hostname: echoserverv1-657b966cb5-7grqs

访问测试

可以看和header的访问效果是一样的,只不过cookie不能自定义value
  1. $ [K8sSj] kubectl apply -f appv2.yml
  2. ingress.extensions/echoserverv2 configured
  3. service/echoserverv2 unchanged
  4. deployment.extensions/echoserverv2 unchanged
  5. $ [K8sSj] for i in `seq 10`;do curl -s --cookie "user_from_shanghai" echo.chulinx.com|grep Hostname;done
  6. Hostname: echoserverv1-657b966cb5-7grqs
  7. Hostname: echoserverv1-657b966cb5-7grqs
  8. Hostname: echoserverv2-856bb5758-f9tqn
  9. Hostname: echoserverv1-657b966cb5-7grqs
  10. Hostname: echoserverv2-856bb5758-f9tqn
  11. Hostname: echoserverv2-856bb5758-f9tqn
  12. Hostname: echoserverv1-657b966cb5-7grqs
  13. Hostname: echoserverv2-856bb5758-f9tqn
  14. Hostname: echoserverv2-856bb5758-f9tqn
  15. Hostname: echoserverv2-856bb5758-f9tqn
  16. # zlx @ zlxdeMacBook-Pro in ~/Desktop/unicom/k8syml/nginx-ingress-canary-deployment [16:01:52]
  17. $ [K8sSj] for i in `seq 10`;do curl -s --cookie "user_from_shanghai:always" echo.chulinx.com|grep Hostname;done
  18. Hostname: echoserverv2-856bb5758-f9tqn
  19. Hostname: echoserverv1-657b966cb5-7grqs
  20. Hostname: echoserverv1-657b966cb5-7grqs
  21. Hostname: echoserverv1-657b966cb5-7grqs
  22. Hostname: echoserverv2-856bb5758-f9tqn
  23. Hostname: echoserverv1-657b966cb5-7grqs
  24. Hostname: echoserverv1-657b966cb5-7grqs
  25. Hostname: echoserverv1-657b966cb5-7grqs
  26. Hostname: echoserverv2-856bb5758-f9tqn
  27. Hostname: echoserverv2-856bb5758-f9tqn
  28. # zlx @ zlxdeMacBook-Pro in ~/Desktop/unicom/k8syml/nginx-ingress-canary-deployment [16:02:25]
  29. $ [K8sSj] for i in `seq 10`;do curl -s --cookie "user_from_shanghai=always" echo.chulinx.com|grep Hostname;done
  30. Hostname: echoserverv2-856bb5758-f9tqn
  31. Hostname: echoserverv2-856bb5758-f9tqn
  32. Hostname: echoserverv2-856bb5758-f9tqn
  33. Hostname: echoserverv2-856bb5758-f9tqn
  34. Hostname: echoserverv2-856bb5758-f9tqn
  35. Hostname: echoserverv2-856bb5758-f9tqn
  36. Hostname: echoserverv2-856bb5758-f9tqn
  37. Hostname: echoserverv2-856bb5758-f9tqn
  38. Hostname: echoserverv2-856bb5758-f9tqn
  39. Hostname: echoserverv2-856bb5758-f9tqn

总结

灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以对新版本进行测试、发现和调整问题,以保证其影响度,以上内容通过实例详细介绍了Ingress-Nginx的实战Canary Annotation,可以借助Ingress-Nginx轻松实现蓝绿发布和金丝雀发布

其他

蓝绿发布

蓝绿部署中,一共有两套系统:一套是正在提供服务系统,标记为“绿色”;另一套是准备发布的系统,标记为“蓝色”。两套系统都是功能完善的,并且正在运行的系统,只是系统版本和对外服务情况不同。 最初,没有任何系统,没有蓝绿之分。 然后,第一套系统开发完成,直接上线,这个过程只有一个系统,也没有蓝绿之分。 后来,开发了新版本,要用新版本替换线上的旧版本,在线上的系统之外,搭建了一个使用新版本代码的全新系统。这时候,一共有两套系统在运行,正在对外提供服务的老系统是绿色系统,新部署的系统是蓝色系统。

蓝色系统不对外提供服务,用来做啥?

用来做发布前测试,测试过程中发现任何问题,可以直接在蓝色系统上修改,不干扰用户正在使用的系统。(注意,两套系统没有耦合的时候才能百分百保证不干扰) 蓝色系统经过反复的测试、修改、验证,确定达到上线标准之后,直接将用户切换到蓝色系统:
  • 切换后的一段时间内,依旧是蓝绿两套系统并存,但是用户访问的已经是蓝色系统。这段时间内观察蓝色系统(新系统)工作状态,如果出现问题,直接切换回绿色系统。
  • 当确信对外提供服务的蓝色系统工作正常,不对外提供服务的绿色系统已经不再需要的时候,蓝色系统正式成为对外提供服务系统,成为新的绿色系统。原先的绿色系统可以销毁,将资源释放出来,用于部署下一个蓝色系统。
  • 蓝绿部署只是上线策略中的一种,它不是可以应对所有情况的万能方案。蓝绿部署能够简单快捷实施的前提假设是目标系统是非常内聚的,如果目标系统相当复杂,那么如何切换、两套系统的数据是否需要以及如何同步等,都需要仔细考虑。

金丝雀发布

金丝雀发布(Canary)也是一种发布策略,和国内常说的灰度发布是同一类策略。蓝绿部署是准备两套系统,在两套系统之间进行切换,金丝雀策略是只有一套系统,逐渐替换这套系统 譬如说,目标系统是一组无状态的Web服务器,但是数量非常多,假设有一万台。 这时候,蓝绿部署就不能用了,因为不可能申请一万台服务器专门用来部署蓝色系统(在蓝绿部署的定义中,蓝色的系统要能够承接所有访问)。 可以想到的一个方法是:
  • 只准备几台服务器,在上面部署新版本的系统并测试验证。测试通过之后,担心出现意外,还不敢立即更新所有的服务器。先将线上的一万台服务器中的10台更新为最新的系统,然后观察验证。确认没有异常之后,再将剩余的所有服务器更新。
  • 这个方法就是金丝雀发布。
实际操作中还可以做更多控制,譬如说,给最初更新的10台服务器设置较低的权重、控制发送给这10台服务器的请求数,然后逐渐提高权重、增加请求数。 这个控制叫做“流量切分”,既可以用于金丝雀发布,也可以用于后面的A/B测试。 蓝绿部署和金丝雀发布是两种发布策略,都不是万能的。有时候两者都可以使用,有时候只能用其中一种。

A/B测试

首先需要明确的是,A/B测试和蓝绿部署以及金丝雀,完全是两回事。 蓝绿部署和金丝雀是发布策略,目标是确保新上线的系统稳定,关注的是新系统的BUG、隐患。 A/B测试是效果测试,同一时间有多个版本的服务对外服务,这些服务都是经过足够测试,达到了上线标准的服务,有差异但是没有新旧之分(它们上线时可能采用了蓝绿部署的方式)。 A/B测试关注的是不同版本的服务的实际效果,譬如说转化率、订单情况等。 A/B测试时,线上同时运行多个版本的服务,这些服务通常会有一些体验上的差异,譬如说页面样式、颜色、操作流程不同。相关人员通过分析各个版本服务的实际效果,选出效果最好的版本。 在A/B测试中,需要能够控制流量的分配,譬如说,为A版本分配10%的流量,为B版本分配10%的流量,为C版本分配80%的流量。