
kubernete编排技术二:deployment
作者 | 朱晋君
来源 | 君哥聊技术(ID:gh_1f109b82d301)
kubernete中的控制器模式,是指用一种对象来控制另一种对象,这个控制器是由组件kube-controller-manager来实现的。deployment就是一种控制器,用来控制pod的创建、水平扩展收缩、滚动更新。deployment是kubernete中一个对无状态pod的控制器,本文来介绍一下。
deployment简介
先回顾一下我们之前定义的yaml文件,这个文件定义了2个pod副本(replicas: 2),这个deployment的编排逻辑就是带app: springboot-mybatis这个label的数量只能有2个,超过就需要删除,少了就需要创建。
上面yaml文件中的template,被称作pod模板,而template上面的代码部分,就是控制器的定义。这儿的控制器其实就是上面的控制器部分对下面pod模板的控制。创建时,控制器会从etcd查找label是springboot-mybatis的pod个数,因为是0,所以会创建2个;如果运行过程中,有一个pod挂了,会再创建一个。
pod水平扩展和收缩
上一节的yaml文件定义了一个2个pod的deployment控制器,这样会生成2个pod。在我们实际工作中,有时会遇到突增流量,比如促销活动之类的,这时候我们可以用增加pod来应对。最直接的方式就是修改replicas,比如改为replicas: 4。但是生成环境中,这样效率太低了,我们可以执行如下命令:
之后我们查看集群上的pod,这2个AGE=10s的pod就是后来扩展出来的。
我们查看其中一个新pod的状态,跟之前的pod创建过程完全一样。
查看replicas
检测一下应用运行正常
如果流量降下来了,我们可以收缩pod数量,执行命令
查看pod数量,后来扩展的2个pod被删除了
可以看出,这种控制器模式,是由deployment控制ReplicaSet,ReplicaSet控制pod。
滚动更新
在实际开发工作中,升级服务上线是经常的事情。以本文中的应用为例,之前的deployment使用的镜像是zjj2006forever/springboot-mybatis:1.2,如果我们升级镜像版本到1.3,需要怎么操作呢?
注:镜像的升级版本我已经打好并且发布到dockerhub,感兴趣的同学自行拉取测试。
这个升级操作我们可以直接修改yaml文件,也可以执行如下命令进行修改,这个命令的原理是直接编辑etcd里面的springboot-mybatis-deployment控制器对象,可以跟编辑文件一样进行编辑
编辑完成保存后,就会触发滚动更新。执行下面命令查看滚动更新的日志。
这时我们再次查看pod,发现新的pod已经创建出来了
从下面springboot-mybatis-deployment的描述Events中可以看出滚动更新的过程
上面event中最后4行就是滚动更新的过程。很明显,滚动更新过程是创建一个新的pod,删除一个旧的pod,直到新的pod全部创建,旧的pod的全部删除。可以"滚动更新"这个词非常形象。滚动更新有如下优势:
1.新pod启动失败整个过程就会停止,剩下的旧pod依然可以提供服务。
2.为了保证服务不中断,deployment控制器会保证一次删除pod的比例和一次创建的pod的比例,默认都是yaml中replicas的25%。
3.这2个比例也可以通过参数来配置,看下面的yaml。maxSurge指每次滚动过程中可以创建多少个pod,maxUnavailable指一次更新中可以删除几个pod,这2个参数值也可以用百分数表示,指的是滚动过程中一次创建或删除的pod数量占replicas配置的pod的比例。
失败回滚
如果我们升级应用的过程中,pod启动失败,这时候我们为了不中断服务,必须回滚。比如之前的yaml文件中,我们定义的springboot-mybatis镜像版本是1.3,如果我们改成1.4版本,dockerhub上并没有这个版本,拉取失败导致pod启动失败。修改yaml文件中镜像版本到1.4后,执行更新命令
这时deployment就会触发滚动更新,但是这时因为镜像拉取失败,pod创建失败,如下结果中第4行
我们再查看deployment的状态,如下,镜像版本是1.4,这时我们可以触发回滚操作。
下面命令可以查看deployment的升级历史
从上面的deployment的describe中我们可以看出目前revision是3(deployment.kubernetes.io/revision: 3),我们应该恢复到2,如下命令
执行之后,再看deployment状态,镜像版本已经恢复到zjj2006forever/springboot-mybatis:1.3
最后,从replicas的结果中我们可以看出,每次无论升级成功失败都会有一个replicas创建出来,为了限制保留的历史版本个数,可以通过参数spec.revisionHistoryLimit来进行设置。
总结
deployment是kubernete中非常重要的一个编排技术,不过它有一个局限,只能编排无状态的pod,比如一个应用的集群,集群中的节点都是平等的,不存在主备关系。但是我们日常的开发中,好多pod是有状态的,比如一个部署在kubernete中的redis集群,会存在主从节点,这样启动的时候pod就存在顺序,deployment就不能满足了。
