Kubernetes 滚动发布和回滚入门实战
(给Go开发大全
加星标)
【导读】k8s的滚动发布和回滚是如何实现的?如何使用?本文介绍了这些技术细节、带你实战滚动发布与回滚。
预备知识
Deployment
Deployment是kubernetes管理工作负载(workload)的机制之一。Deployment是被Deployment controller管理的。
工作负载(workload)概念见官方文档:https://kubernetes.io/docs/concepts/workloads/controllers/
k8s中,控制器是监控着集群状态的,在需要的时候发生变更或请求变更。每个controller的目标是让集群状态更加接近用户需要的状态。
对于一个deployment来说,“用户需要的状态”是对于pod而言的。k8s中一切都是声明式定义的,结果状态定义在Deployment配置文件的spec。
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
如果任何pod实例要失败或者更新(这两个都是变更的状态),k8s系统会针对变更之间的spec配置的diff做出更正操作,结果就是让deploymeng和最新的spec定义保持一致。
Deployment的底层实现
Deployment是ReplicaSet上的一层抽象,实际上是Deployment创建了一个ReplicaSet、创建过程中会在我们的集群上创建pod。ReplicaSet的功能如其名,就是用来管理我们的pod的副本的。
总之就是Controller会读取Deployment配置的spec,把pod的配置发给ReplicaSet,ReplicaSet负责选合适的副本创建pod。
Deployment > ReplicaSet > Pods:
滚动发布
kubernetes保证服务可用,其中保证了可用性的一个非常有用的功能点就是滚动发布。k8s在发布过程中,使用滚动发布可以保证要到达pod的流量不被中断。
回滚
回滚的意思是让当前的deployment回到之前部署的deployment的实例版本上去。
实战
让我们通过实战演练学习deployment的逻辑策略和执行逻辑吧!
安装KinD
首先要在本机用Kind(kubernetes in Docker)工具装一个单节点K8s集群,确保Docker已经在运行。
安装KinD https://kind.sigs.k8s.io/docs/user/quick-start/
用下面的命令创建一个K8s集群:
$ kind create cluster
用这个集群就可以部署Deployment了。这篇教程中不会用YAML做任何定义,只通过调用kubectl
命令行工具操作。
创建Deployment
用nginx镜像创建第一个Deployment:
$ kubectl create deployment test-nginx --image=nginx:1.18-alpine
如之前所讲,一个Deployment会创建一个有Pod的ReplicaSet。通过下面的命令检查新创建的资源:
$ kubectl get deploy,rs,po -l app=test-nginx
新创建的Deployment,ReplicaSet,Pod列表
用下面的命令检查Deployment有没有创建Replicaset:
$ kubectl describe rs <replica-set-name>
检查Deployment创建的ReplicaSet
检查Pod创建情况:
$ kubectl describe po <pod-name>
扩容Deployment
把nginx pod数量扩容到3个:
$ kubectl scale deploy test-nginx --replicas=3
创建3副本nginx pod
现在集群上已经有了一定数量pod了,那我们来试试deployment策略。
实战:滚动发布deployment
比如现在你的系统里nginx的v18版本有些问题,v19版本修复了,现在你需要滚动升级pod里的nginx镜像版本。升级当前pod的镜像会触发状态变更,kubernetes就会滚动发布一个新deployment。
$ kubectl set image deploy test-nginx nginx=nginx:1.19-alpine
设置了新镜像后,可以看到旧pod被关闭、新pod被启动。
滚动发布,新pod替换旧pod:
kubernetes会保证pod被合理维护。最后一个旧版本镜像的pod不会被停止得很快,要等到整个replica的新pod都创建好才能杀掉。旧pod都会有一个比较长和完整的实际等待pod停止,目的是保证pod承载的流量一段时间内不会断开。直到请求可以安全打到新pod上旧pod才会被删掉。
成功升级所有pod,使用nginx v19
版本镜像,查看命令:
$ kubectl describe deploy test-nginx
升级到nginx v19的pod:
实战:回滚deployment
假设新nginx版本比老版本问题还多,现在必须回退到上一个版本,要如何操作?
你可能注意到现在有两个ReplicaSet,这是因为我们更新了Deployment,此时会创建一个新replicaSet、创建了新pod。kubernetes默认保留10个历史ReplicaSet,可以修改deployment文件中的revisionHistoryLimit参数修改这个值。
这些历史叫rollout
,只有最新的rollout处于活动状态。
到这里,我们就对test-nginx这个deployment做了两次变更了,查看变更历史能看到两个记录:
$ kubectl get rs
$ kubectl rollout history deploy test-nginx
$ kubectl rollout history deploy test-nginx --revision=1
test-nginx deployment滚动发布历史:
好,那立马回滚到前一个发布版本。要回滚到的版本是用nginx v18
的版本,就是滚动发布到Revision 1
。
$ kubectl rollout undo deploy test-nginx --to-revision=1
取消滚动发布的pod的状态:
和滚动发布deployment类似,rollback deployment会关掉当前pod,把pod替换包含Revision 1
中spec
的pod。
再次查看滚动发布历史,可以看到Revision 1
已经被拿去创建最新的pod了,tag是Revision 3
。相同spec之间不需要维护多个版本,kubernetes就删掉了Revision 1
,因为它有和Revision 3
同样的spec。
reversion历史:
这样就回退到了nginx v18
版本,通过下面的命令查看:
$ kubectl describe deploy test-nginx
检查回滚后的nginx版本:
总结
kubernetes的这些策略让管理应用的deployment非常方便,本文梳理了一遍滚动发布和回滚操作,是一篇入门文章。在实际工作中,这些步骤可能会把上面这些步骤都集成到CICD中,比如集成到ArgoCD,就不需要手动执行了。
感谢阅读,希望本文让能帮你理解滚动发布和回滚在k8s中如何使用。
- EOF -
Go 开发大全
参与维护一个非常全面的Go开源技术资源库。日常分享 Go, 云原生、k8s、Docker和微服务方面的技术文章和行业动态。
关注后获取
回复 Go 获取6万star的Go资源库
分享、点赞和在看
支持我们分享更多好文章,谢谢!