XXOps实践:持续发布和部署

DevOps也好,NoOps也罢,关键看是否解决了业务问题,消除了痛点,这才是价值。

上周分享了一篇文章《有了CMDB,为什么还要应用配置管理》,主要讲了基础层面应该怎么做,那基础的东西做好了,如果用不起来,就没有价值,那我们今天就来看看在此基础之上的一些实践。

为什么要先做持续发布和部署?

首先,根本原因还是为了提升代码的交付效率(好像是句正确的废话),从技术上,主要原因还是因为从单体工程拆分成了服务化的应用。

单体工程的历史原因也很好理解,在创业初期,技术人员有限的情况下,为了快速找到正确的业务发展方向,技术人员必定会把全部的精力放到业务需求的实现上,这时技术或架构层面的事情是次要的,且在创业早期,用户量和业务模型也没有这么复杂,也没有必要搞复杂的架构出来,LNMP足矣,从我们的实践来看这样的技术选择是无比正确的。

但是,随着业务量和业务复杂度的增加(如电商的用户、商家、店铺、商品、交易和支付体系),业务服务质量要求变得越来越苛刻(低时延、高可用),需求的交付周期却要求越来越短(脑补下产品经理站在程序员身后的场景),同时工程师数量也已经到了几百人规模,这时单体工程就暴露出很多问题,比如代码逻辑耦合严重、底层公共方法不敢动,代码量巨大已经没有任何一个人能对整个工程代码熟悉,上百个工程师同时向同一个工程提交代码,代码维护耗费的精力非常大。最终一张图看下当时的场景:

所以,解决方案向着Java服务化的方向演进(具体原因就不解释了),简单示意如下:

单体应用拆分成服务化应用后,应用的情况就变成了许许多多、大大小小的应用模式,下图示意:

这个时候遇到的最棘手的问题,就是发布问题,这么多的应用对应的代码都是不同的,且Java服务化之后涉及编译构建、服务优雅上下线等一系列等问题,环节也多了很多(后面会看到),这些环节单纯的靠手工执行脚本和人为的串联已经成为不可能的事情,这个直接影响到开发、测试和运维整个研发体系的效率,所以是摆在面前必须要首要解决的。

好的,接下来我们就开始做发布系统了,提炼一下,发布做的事情就是,将提交后的应用代码,进行编译打包,然后发布到应用对应IP主机的指定目录下,并且做到应用服务的优雅上下线(或者叫做优雅启停)。

理解起来不复杂,其实我们可以抽象出发布的最重要的三步,我们也是始终围绕着这三步在不断的完善,如下:

下面就分阶段详细描述三个主要环节:

代码提交环节(分支合并管理)

代码管理工具是Gitlab,代码提交过程中最重要的就是对于分支合并的管理(这里又涉及到标准规范的制定),我们的策略示意大致如下:

描述如下:

1、master分支,跟线上应用代码保持同步,也就是说随时可以发布到线上进行部署运行。

2、开发分支,通常以feature/defect来表示,比如开发一个新的需求,就会以当前master为基线,拉一个feature分支出来进行开发,同一个应用可以同时存在多个feature分支并行开发。

3、发布分支,以release表示,在发布时会将所有提交集成的代码commit合并,形成release_环境_时间戳为分支名称,比如release_dev_01_29_20_52_10 就代表该分支是在1月29号20:52:10在dev环境发布时创建的临时发布分支。

4、从预发进入线上时,会以当前预发环境的发布分支release_pre_xxxx为基线创建一个release_online分支,作为线上的发布分支,线上发布结束后会把release_online分支合并到master中,这也就保证了发布到线上的代码最终一定会跟master的代码保持一致。

编译构建环节

上面讲完了代码提交环节,下一个环节就是要构建了,以Java为例,构建我们用到了两个工具,Docker和Maven。Docker主要用来提供一个干净独立的编译环境,Maven作为我们的依赖管理和打包工具。整个构建过程如下:

以Java为例,简单描述如下:

1、首先准备好JDK的编译镜像,这个镜像环境与线上环境保持一致,当有新的构建任务进来时,就创建一个对应的Docker实例进行代码编译;

2、构建任务会根据应用配置管理中的Git地址,将代码clone下来放到指定的编译目录,Docker实例启动后,将编译目录挂在到Docker实例中;

3、对于Java应用,在这个Docker实例环境中,就可以执行mvn package命令打包了,最终会生成一个可发布xxx.war的软件包;

4、同样的,对于C++,Go、NodeJs,也会准备好类似的编译镜像,不同的是打包时,对于C++是cmake&make,Go就是go install等等,最终也会生成一个可发布的软件包;

5、构建完成后,Docker实例销毁;

这里面Docker发挥了一个很大的作用,就是提供了干净的,互不干扰的编译环境,且对于并发打包的情况,Docker快速创建多个并行的实例出来提供编译环境,使用完销毁,这个效率上的优势也是非常大的。

6、关于配置管理,当时设计时考虑比较简单,我们的做法是同时做三个配置文件出来,dev_pom.xml,pre_pom.xml,online_pom.xml,分别对应开发、预发和线上三个不同的环境,根据发布的环境不同,将不同的配置文件替换上去。这样做其实可扩展性不够,对于多机房、多分组的情况会有更多的配置文件创建出来,且对于有敏感信息的配置项保密也不够(不过这些配置都已经加密挪到中间件的配置中心了),更好的办法可以考虑采用阿里早已开源的auto-config方案,这里就不细讲了。

部署环节

以上,代码提交和编译构建完成后,就该进入发布到线上的部署环节了,也就是将代码发布到应用对应IP主机的指定目录下,并且能够优雅的上下线应用服务,貌似很简单,但是,看下图:

这个过程的环节还是比较多的,这些环节内部又会有很多的细节,所以整个部署环节是很复杂的,下面将整体思路介绍一下:

0、从CMDB中,拿到应用-主机IP对应关系,然后再从1开始做,后面的过程可以是针对单台机器做,也可以是分批或分组多台机器同时做。(从第0步开始,原因就是我们上一篇文章里面说的CMDB和应用配置管理的基础要先打好,这个基础没有,下面的环节就无法顺畅地执行);

1、检查每台机器上的服务是否正常运行的,如果是正常服务的,说明可以发布,但是服务本身异常,就要记录或跳过了;

2、下载war包到指定目录(应用的目录信息,应用配置管理又发挥作用了);

3、将监控关闭,以免服务下线和停止产生误告警;

4、优雅下线,包含RPC服务从LB下线或Web服务从Nginx下线(如果不提供http服务就不涉及),下线动作均通过API接口调用方式实现;

5、下线后自动检测无新的流量进入,停止应用,发布代码,然后启动应用(这时应用配置管理里面,启停命令等等就又发挥作用了);

6、优雅上线,进行健康监测,检查进程和应用状态是否正常,如果全部监测通过,开始上线服务,开启监控;

7、分批发布,这里简单提一下,假设我们一个应用有100台主机,这个时候做发布不可能全部一把停掉,这样服务会中断,但是也不能一台台的做,这样效率又太低,所以我们可以折中分批发,比如可以分5批,每批20台,也可以分10批,每批10台,这样既可以保证在线升级,也可以保证效率能够跟的上。当然复杂一点,还有分组分批,或者按步长分批,第一批5台,第二批10台,后面每批20台等等。示例如下:

整个过程下来我们可以看到:

1、基于场景入手,将业务流程梳理细致,做到细分环节,每步自动化,流程串联

2、上篇文章提到的CMDB和应用配置管理的内容,在这一部分无时无处不在发挥着基础的作用

效果:NoOps or DevOps?

发布系统上线后,整个过程已经可以做到开发全程自助发布,之前运维还在参与审批,后来审批环节也省略,在发布这个过程中,全流程NoOps。效果如下图所示:


志强和库瑞两位同学是我们发布系统的主要设计者和开发者,老司机带新司机上路,又快又稳。因为篇幅原因没法列出其他同学,也同时感谢为发布系统做出贡献的各位。

原文发布于微信公众号 - Forrest随想录(forrest_thinking)

原文发表时间:2017-07-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏公众号文章

干货| 架构师入门实战视频课程(二) 附下载地址

5. 回复:zeromq,获取 基于案例学Java服务器端程序设计ZeroMQ Netty视频教程 相关教程

22630
来自专栏携程技术中心

微分享回放 | Openstack虚拟云桌面在携程的应用

【携程技术微分享】是携程技术中心推出的线上公开分享课程,每月1-2期,采用目前最火热的直播形式,邀请携程技术人,面向广大程序猿和技术爱好者,一起探讨最新的技术热...

739120
来自专栏互联网技术栈

读《大型网站技术架构》

《大型网站技术架构》是自己接触的第一本架构知识的书籍,还是在14年时买的实体书,前后读了几遍,颇有所得,后来实体书被朋友借走再没归还,也就没再翻过。

15720
来自专栏butterfly100

Chris Richardson微服务翻译:微服务介绍

作者简介:Chris Richardson,世界著名的软件架构师,经典著作《POJOS IN ACTION》的作者,cloudfoundry.com 的创始人 ...

310120
来自专栏菜鸟致敬

【1】网络爬虫简介

网络爬虫何时有用 假设我们有一个鞋店,并且想要及时了解竞争对手的价格。我们可以每天访问他们的网站,与我们的价格进行对比。但是,如果我们店铺只能够的鞋类种类繁多,...

28070
来自专栏北京马哥教育

Uread 自动化运维平台七大阶段实践

首先技术并没有好坏之分,只能说一种技术在特定场景会优于另一种技术。 首先uread优读( http://aiuread.com/ )作为一个还处于起步阶段的团队...

39440
来自专栏韩伟的专栏

经典软件架构模式(三)

REST模式 让我们回到服务器端开发。一直以来,互联网服务就以数据互通为最重要的业务特性。我们来看看一个微博系统的案例。 ? 【此案例并非完全真实情况,有一定提...

34470
来自专栏Java架构

了解为什么要使用微服务!

单体应用就是将应用程序的所有功能都打包成一个独立的单元,最终以一个WAR包或JAR包存在,没有外部的任何依赖,里面包含DAO、Service、UI等所有的逻辑。...

27430
来自专栏xingoo, 一个梦想做发明家的程序员

【插件开发】—— 1 Eclipse插件开发导盲

在真正接触eclipse插件开发一个月后,对插件的开发过程以及技术要求,也有了一定的了解。遥想之前像无头苍蝇一样乱撞乱学,真心觉得浪费了不少时间。这里就总结...

44890
来自专栏企鹅号快讯

Go 语言如何去解决 Web 开发人员面临的众多问题?

坦白的说,我的团队非常厌恶我对 Go 语言传道的方式,每当我们团队的代码库出现问题时,他们希望我用一种更委婉的方式提出。 我学会的第一门编程语言是 PHP,这是...

383100

扫码关注云+社区

领取腾讯云代金券