赞
踩
首先,我们需要发布系统的初衷是什么呢?效率,安全,高可用。但是这三者很多时候因为时间等成本的问题,是相互冲突的。所以在不同时期对发布系统功能的健全性,和延展性有不同的要求。
当我们最开始处于手动或者半自动状态下的发布,可以参考如下流程图。
初期的发布系统,都是手动控制发布流程,人为因素导致很多不稳定的地方,例如:
1.发错了分支
2.发错了机器
3.出了问题不能及时回滚
4.人员素质不齐,有些人想干什么就干什么,导致相互依赖的系统不能提供稳定的服务。
等等。
但是,这个时期对于中小公司而言,由于运维成本高昂,各方面变动多。大多数技术总监会选择无视发布系统带来的效率提升,选择all in,让所有研发什么活都干,没有什么流程管理可言。出各种线上问题在所难免,大部分负责人内心ps:大不了让客服和销售去道歉。
稍微优秀点的,会使用诸如jenkins这样的构建工具,但是还是有很多人不能理解,jenkins的定位,就是一款构建工具,他不适合参与多人的生产环境,因为jenkins不具备流程管理的功能。
如下给出一家中等规模公司可能出现的线上发布流程
中等规模的公司,有个特点,多人员协作。涉及到人员协作,就会用上代码版本的管理工具,如svn和gitlab。在这种人员规模的环境下,生产周期涉及到的方面很多,如任务的产生,人员的流转,代码的实现,产品的实现,产品的运维,等等。用人力来管理,成本实在是可怕。大多数发展到中等规模公司都会遇到一个严峻的问题,需要对应用进行拆分,来提高发布效率,这个时期会进入很多新人。如果没有一套成熟的生产体制,那么生产管理混乱,事故就会频发。
如上图给出的流程,所有的流程都由发布系统来管理,流转,自动控制机器的运行。每个人员,只需要在发布系统内关注自己的一部分即可,责任分明,分明的责任,才能更高的提升效率。例如,任务产生后自动输出工作用的代码分支,发布结束后,自动合并代码分支。看到这里,会有很多人很奇怪,“我们接触的研发生产流程,是每个环境都有一个单独的分支啊”。这种就是没有完整发布系统管理走出来的路子,其成因很简单。大家对自己的二方包都没有管理,需要一个分支来打包,什么版本管理的,我才懒得管。同时,公司也不想多花成本部署单独的研发服务用的环境,都公用一套。比如,生产有个develoop分支,测试有个test分支,生产还有个。等等等,这种做法可怕的地方在于,这些分支上混杂着很多神奇的,不会有人去负责的代码。每个人都为所欲为,没有清晰的责任链。很有可能某次发布,会带着一些神奇的代码,上了生产环境。
一款优秀的发布系统,发出来的东西应该像一辆大巴,一艘航母,一枚火箭。不存在让人半路截胡,可以随时,快速,稳定的发布。
一款成熟的发布系统,至少应该具有如下模块功能
对相关项目的授权管理,对相关任务的授权管理,对相关人员的授权管理。简单的描述,例如这个项目可不可以发,谁可以发,谁在什么时间段可以发,谁来授权发,谁来控制发,对这几个方面来进行控制。
管理整个系统的资源,包括编译机有多少台,如何均衡,如何分配。可发布的机器有多少台,如何控制,在什么机房,网段是什么样子的,等等。
发布流程的定制化,为什么需要这一个功能呢。对于每家公司而言,发布流程不尽相同,甚至同一个公司同一个项目,都不同。例如,同一个项目,有平时的日常发布,同时,存在紧急发布这两种不同的流程。所以需要有流程的管理,例如,如何去申请紧急发布流程。也有一些特殊的服务,比如一个api服务,会先发sandbox给客户使用后,再上生产环境。所以同一个项目会有多种发布流程。这个在发布任务时,来进行选择,我应该使用什么样的流程来发布。这个流程里谁会把关,谁会关注,等等。
顾名思义,管理需要发布的项目,每种项目可能使用的技术不一样,发布的脚本,形式也不同。例如java,vue。例如有的项目可以滚动发布,而有的项目由于并发量大,或者安全性需求,不可以滚动发布,需要进行池化发布,稳定后再替换。项目管理需要配置相应的项目onwer,代码仓库地址,基础配置文件等等。更复杂一点的,某一个项目需要同时发几个应用,对应的流程需要配置上项目管理。还有该项目运行在机器的什么空间之下,是否使用容器化的手段发布,等等。
对过去发布过的任务溯源,对正在发布的任务进行监控。例如测试人员需要关注,自己名下有没有任务被分配到,自己需不需要处理,等等。
控制当前发布任务的特定流程的发布,例如研发提交了review,另外一个负责人需要review代码,需要在此关注。发布到机器上,需要看日志,也在此观测。控制整个发布流程
配置应用和对应仓库地址。
运维经常会做网络变动,需要对机器进行上下架,但是运维不可能一直等着机器在使用低谷期下架。此功能可有效提高运维效率。再例如,在动态容灾时,发布系统进行自动调度的任务,也需要有地方可以查看(后面有讲解动态容灾)。
没什么可描述的,大家可以发挥想象。主要是针对发布平台的初始配置,项目demo,任务demo等等配置的管理。
每次发布之后的稳定版本的程序包都应该保存与记录,以备不时之需。这个很重要,例如系统紧急扩容发布时,可以直接来选对应版本的程序包。
开放的接口平台,将绝大部分功能暴露出去,对接监控系统,任务系统等。打通上下游,贯穿生产流程和容灾流程。任务下达,分支就产生了。线上机器不够,或者挂了,自动复活。
有了线上项目,大多数技术都会装上监控,例如collectd + influxdb + grafana
刚开始的时候,都是人为监控,最多写个邮件或者钉钉之类的信息告警,让人员来处理。但是很多时候,关键人员并不在场,不能立马解决,导致公司错失或者损失了巨额财富。
自动化容灾和扩容,意义就凸显出来了。将监控系统和发布系统进行打通,这就是为什么上面最后提到了需要openApi,将发布系统的功能暴露出来。
例如,某天深夜,贵司提供的服务,被某个合作方疯狂的使用(碰上了促销没沟通,或者超出了预期),这会技术人员正在吃着火锅,唱着歌,突然被麻匪给。。。。。公司的期望很简单,第一,不能损失钱。第二,不能给客户造成坏映像(坏映像直接能导致客户逃离,甚至在圈内都流传坏名声)。贵司正好有监控系统,发现了服务器内存从20%占用率飙升到70%,监控系统同时向相关负责人和发布系统告警。发布系统进入自动扩容程序,自动从资源池中,拉取N台机器进行扩容。直到扩容到低于70%,自动停止。当流量降下来的时候,自动减容到应用基础容量。全过程技术甚至不需要手动干预。容灾也是同理,挂了一台,被监控发现,直接告知发布平台进行复活发布。
上面这个过程,绝对比你挨个打电话,手动去搞,要高效稳定的多。
(ps:自动化容灾对编码有一定要求,例如,程序包的稳定性,不能有启动初始化,夸张的缓存数据,等)
不同的公司,对于配置文件的管理方式不同。
1.全部放在代码里(安全性堪忧,需要变更时维护性差)
2.一部分放代码里,一部分放配置中心(脑瘫做法,两边都要维护)
3.代码里没有配置文件,全部放在配置中心,优点,一次打包,全局使用,适合高效快速发布。
首先在发布期,每台机器都要去频繁的查数据库,写缓存。发布时间可怕,笔者曾经接触的应用就有单台启动需要半小时以上的应用,后期优化到3分钟。半小时一台3台就是1小时多,效率及其低下,遇上回滚,那将是非常可怕的。同事给其他服务造成的压力也不小。在发布的时候,发布系统也不好鉴别,当前机器是发布出了问题还是没有发布完成导致的超时。
同时,大缓存,不适合如电商这样的倍增流量场景,例如,你需要迅速扩容200台应用机来抵御峰流。如果不能再30秒内发布完成,轻则错过流量市场,重则全环境系统崩溃,一天白给。
解决方案
1.专用缓存发布程序(最优解)
2.懒加载(自己研究下如何防止缓存穿透吧,无限兜底大法)
很多公司体量不大,痴迷docker这样的容器发布系统,但是没有理解其精髓,造成没有必要的浪费。如果你有很多的不同语言,对环境需求不同的应用需要发布,那使用docker没毛病。例如公司所有的资源池都是同一个机器池,里面什么样配置的机器都有。同时存在,java,python,c++,golang。为了保证环境的整洁,不能每台机器都按装各种版本不同类型的运行环境。那用docker就挺好,或者你会用异地机房,去其他云服务发布,容器那也不错。
但是绝大多数公司,都是一套语言,即使有不同的语言,也是单独配置的,linux用户空间目录就是最好的容器,用docker就是画蛇添足,徒增工作量。慎重选择。
发布分为滚动发布和池化发布,这二者并不冲突,发布系统应该同时支持这两套方案,例如在用户量不大,但是发布资源紧张的情况下,应用发布可以选择滚动发布。在特殊应用有缓存变动,流量高峰期等特殊情况下,需要用不同的配置,这个时候用池化发布,成功后直接切流量即可。二者的使用主要考量在成本上,分别是时间成本,机器成本,和用户体验成本上。这是个均衡的问题。
以上就是作者对自动化发布系统的浅见,任何一个系统都不是一个人可以完全掌握透彻的,本人也只看到了自己看到的一面,甚至只写出来自己想到记到的地方。后续会继续编写有关发布系统的机制构成,脚本编写的帖子。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。