k8s 应用更新策略:灰度发布和蓝绿发布
Posted 笨小孩@GF 知行合一
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了k8s 应用更新策略:灰度发布和蓝绿发布相关的知识,希望对你有一定的参考价值。
-
生产环境如何实现蓝绿部署?
-
什么是蓝绿部署?
-
蓝绿部署中,一共有两套系统:一套是正在提供服务系统,标记为“绿色”;另一套是准备发布的系统,标记为“蓝色”。两套系统都是功能完善的、正在运行的系统,只是系统版本和对外服务情况不同。
-
开发新版本,要用新版本替换线上的旧版本,在线上的系统之外,搭建了一个使用新版本代码的全新系统。 这时候,一共有两套系统在运行,正在对外提供服务的老系统是绿色系统,新部署的系统是蓝色系统。
-
蓝色系统不对外提供服务,用来做什么呢?
-
用来做发布前测试,测试过程中发现任何问题,可以直接在蓝色系统上修改,不干扰用户正在使用的系统。
(注意,两套系统没有耦合的时候才能百分百保证不干扰) - 蓝色系统经过反复的测试、修改、验证,确定达到上线标准之后,直接将用户切换到蓝色系统:
- 切换后的一段时间内,依旧是蓝绿两套系统并存,但是用户访问的已经是蓝色系统。这段时间内观察蓝色系统(新系统)工作状态,如果出现问题,直接切换回绿色系统。
- 当确信对外提供服务的蓝色系统工作正常,不对外提供服务的绿色系统已经不再需要的时候,蓝色系统正式成为对外提供服务系统,成为新的绿色系统。 原先的绿色系统可以销毁,将资源释放出来,用于部署下一个蓝色系统。
-
蓝绿部署的优势和缺点
-
优点:
1、更新过程无需停机,风险较少
2、回滚方便,只需要更改路由或者切换 DNS 服务器,效率较高 -
缺点:
1、成本较高,需要部署两套环境。如果新版本中基础服务出现问题,会瞬间影响全网用户;如果新版本有问题也会影响全网用户。
2、需要部署两套机器,费用开销大
3、在非隔离的机器(Docker、VM)上操作时,可能会导致蓝绿环境被摧毁风险
4、负载均衡器/反向代理/路由/DNS 处理不当,将导致流量没有切换过来情况出现 -
通过 k8s 实现线上业务的蓝绿部署
- Kubernetes 不支持内置的蓝绿部署。目前最好的方式是创建新的 deployment,然后更新应用程序的 service 以指向新的 deployment 部署的应用
-
创建绿色部署环境(旧的部署环境)
-
下面步骤在 k8s 的控制节点操作:
# kubectl create ns blue-green
# vim lv.yaml创建前端 service
vim service_lanlv.yaml -
创建蓝色环境(新的部署环境)
vim lan.yaml -
在浏览器访问 http://k8s-master 节点 ip:30062 显示如下:
-
修改 service_lanlv.yaml 配置文件,修改标签,让其匹配到蓝程序(升级之后的程序)
-
实验完成之后,把资源先删除,以免影响后面实验:
kubectl delete -f lan.yaml
kubectl delete -f lv.yaml
kubectl delete -f service_lanlv.yaml -
通过 k8s 实现滚动更新-滚动更新流程和策略
-
滚动更新简介
-
滚动更新是一种自动化程度较高的发布方式,用户体验比较平滑,是目前成熟型技术组织所采用的主流发布方式,一次滚动发布一般由若干个发布批次组成,每批的数量一般是可以配置的(可以通过发布模板定义),例如第一批 1 台,第二批 10%,第三批 50%,第四批 100%。每个批次之间留观察间隔,通过手工验证或监控反馈确保没有问题再发下一批次,所以总体上滚动式发布过程是比较缓慢
- 在 k8s 中实现滚动更新
- 首先看下 Deployment 资源对象的组成:
kubectl explain deployment
kubectl explain deployment.spec
paused <boolean> #暂停,当更新的时候创建 pod 先暂停,不是立即更新
revisionHistoryLimit <integer> #保留的历史版本数,默认是 10 个
strategy <Object> #更新策略,支持的滚动更新策略 Default is RollingUpdate.
#支持两种更新,Recreate 和 RollingUpdate
#Recreate 是重建式更新,删除一个更新一个
#RollingUpdate 滚动更新,定义滚动更新的更新方式的,也就是 pod 能多几个,少几个,控制更新力度的
maxSurge <string> #更新的过程当中最多允许超出的指定的目标副本数有几个;它有两种取值方式,第一种直接给定数量,第二种根据百分比,百分比表示原本是 5 个,最多可以超出 20%,那就允许多一个,最多可以超过 40%,那就允许多两个
maxUnavailable <string> #最多允许几个不可用 ,假设有 5 个副本,最多一个不可用,就表示最少有 4 个可用 -
自定义滚动更新策略
maxSurge 和 maxUnavailable 用来控制滚动更新的更新策略
取值范围
数值
1. maxUnavailable: [0, 副本数]
2. maxSurge: [0, 副本数]
注意:两者不能同时为 0。
比例
1. maxUnavailable: [0%, 100%] 向下取整,比如 10 个副本,5%的话==0.5 个,但计算按照 0个;
2. maxSurge: [0%, 100%] 向上取整,比如 10 个副本,5%的话==0.5 个,但计算按照 1 个;
注意:两者不能同时为 0。
建议配置
1. maxUnavailable == 0
2. maxSurge == 1
这是我们生产环境提供给用户的默认配置。即“一上一下,先上后下”最平滑原则:
1 个新版本 pod ready(结合 readiness)后,才销毁旧版本 pod。此配置适用场景是平滑更新、保证服务平稳,但也有缺点,就是“太慢”了。
-
总结:
maxUnavailable:和期望的副本数比,不可用副本数最大比例(或最大值),这个值越小,越能保证服务稳定,更新越平滑;
maxSurge:和期望的副本数比,超过期望副本数最大比例(或最大值),这个值调的越大,副本更新速度越快。 -
查看默认的滚动更新策略
#最多允许多 25%个 pod,25%表示不足一个,可以补一个 -
查看控制器的滚动历史
kubectl rollout history deployment mongodb-kubernetes-operator
回滚操作:
kubectl rollout undo deployment/mongodb-kubernetes-operator --to-revision=1自定义策略:
修改更新策略:maxUnavailable=1,maxSurge=1
kubectl patch deployments.apps mongodb-kubernetes-operator -p '"spec":"strategy":"rollingUpdate":"maxSurge":1,"maxUnavailable":1'
显示如下:
RollingUpdateStrategy: 1 max unavailable, 1 max surge
上面可以看到 RollingUpdateStrategy: 1 max unavailable, 1 max surge
这个 rollingUpdate 更新策略变成了刚才设定的,因为我们设定的 pod 副本数是 3,1 和 1 表示最少不能少于 2 个 pod,最多不能超过 4 个 pod
这个就是通过控制 RollingUpdateStrategy 这个字段来设置滚动更新策略 -
通过 k8s 完成线上业务的金丝雀发布
-
金丝雀发布简介
-
金丝雀发布的由来:17 世纪,英国矿井工人发现,金丝雀对瓦斯这种气体十分敏感。空气中哪怕有极其微量的瓦斯,金丝雀也会停止歌唱;当瓦斯含量超过一定限度时,虽然人类毫无察觉,金丝雀却早已毒发身亡。当时在采矿设备相对简陋的条件下,工人们每次下井都会带上一只金丝雀作为瓦斯检测指标,以便在危险状况下紧急撤离。
-
金丝雀发布(又称灰度发布、灰度更新):金丝雀发布一般先发 1 台,或者一个小比例,例如 2%的服务器,主要做流量验证用,也称为金丝雀 (Canary) 测试 (国内常称灰度测试)。
-
简单的金丝雀测试一般通过手工测试验证,复杂的金丝雀测试需要比较完善的监控基础设施配合,通过监控指标反馈,观察金丝雀的健康状况,作为后续发布或回退的依据。 如果金丝测试通过,则把剩余的 V1 版本全部升级为 V2 版本。如果金丝雀测试失败,则直接回退金丝雀,发布失败。
-
优点:灵活,策略自定义,可以按照流量或具体的内容进行灰度(比如不同账号,不同参数),出现问题不会影响全网用户
缺点:没有覆盖到所有的用户导致出现问题不好排查 -
在 k8s 中实现金丝雀发布
打开一个标签 1 监测更新过程
kubectl get pods -l app=myapp -n blue-green -w - 打开另一个标签 执行如下操作:
kubectl set image deployment myapp-v1 myapp=janakiramm/myapp:v2 -n blue-green && kubectl rollout pause deployment myapp-v1 -n blue-green
注:上面的解释说明把 myapp 这个容器的镜像更新到 janakiramm/myapp:v2 版本 ,更新镜像之后,创建一个新的 pod 就立即暂停,这就是我们说的金丝雀发布;
如果暂停几个小时之后没有问题,那么取消暂停,就会依次执行后面步骤,把所有 pod 都升级 -
解除暂停:
回到标签 1 继续观察: -
打开标签 2 执行如下:
kubectl rollout resume deployment myapp-v1 -n blue-green
-
kubectl get rs -n blue-green
可以看到 replicaset 控制器有 2 个了
-
回滚:
如果发现刚才升级的这个版本有问题可以回滚,查看当前有哪几个版本:
kubectl rollout history deployment myapp-v1 -n blue-green上面说明一共有两个版本,回滚的话默认回滚到上一版本,可以指定参数回滚:
kubectl rollout undo deployment myapp-v1 -n blue-green --to-revision=1
#回滚到的版本号是 1
kubectl rollout history deployment myapp-v1 -n blue-green上面可以看到第一版没了,被还原成了第三版,第三版的前一版是第二版
以看到下面的 rs 已经用第一个了,这个就是还原之后的 rs
-
自定义 CRD 资源
通过 crd 部署 mongodb 集群
部署 mongodb-aperator
1、项目地址
https://github.com/mongodb/mongodb-kubernetes-operator.git 找到 0.5.0,看这个版本对应使用
2、创建名称空间 mongodb,并进入到 mongodb-kubernetes-operator 目录应用 crd 资源,
创建自定义资源类型
kubectl create ns mongodb
cd mongodb-kubernetes-operator-0.5.0
kubectl apply -f deploy/crds/mongodb.com_mongodbcommunity_crd.yaml#查看 mongodb 是否创建成功
kubectl get crd/mongodbcommunity.mongodb.com
3、安装 operator
kubectl apply -f deploy/operator/ -n mongodb提示:mongodb-kubernetes-operator 这个项目是将自定义控制器和自定义资源类型分开实现的;其 operator 只负责创建和监听对应资源类型的变化,在资源有变化时,实例化为对应资源对象,并保持对应资源对象状态吻合用户期望状态;上述四个清单中主要是创建了一个 sa 账户,并对对应的 sa 用户授权;
验证:查看 operator 是否正常运行
kubectl get pods -n mongodb验证:使用自定义资源类型创建一个 mongodb 副本集集群
kubectl apply -f deploy/crds/mongodb.com_v1_mongodbcommunity_cr.yaml -n mongodb
kubectl get pods -n mongodb
提示:这里可以看到对应 pod 处于 pending 状态;
查看 pod 详细信息提示:这里提示没有可以用的 pvc; 4 pod has unbound immediate PersistentVolumeClaims.
删除 mongodb 名称空间下 pvc
kubectl get pvc -n mongodb
kubectl delete pvc --all -n mongodb
创建 pv 和 pvc
vim pv-demo.yaml
在 nfs 服务器 上创建 nfs 共享目录
mkdir /data/p1,2,3创建 pvc 资源
vim pvc-demo.yaml可以看到对应的pod已经正常跑起来了;
验证:连接mongodbpod,看看对应副本集集群是否工作正常?
以上是关于k8s 应用更新策略:灰度发布和蓝绿发布的主要内容,如果未能解决你的问题,请参考以下文章