持续部署理论

以前写前端项目打包部署,都是手动运行命令,打包完,然后压缩,再上传到服务器解压。这种方式确实有点low并且效率也不高。 自从用了Jenkins持续集成工具,写前端项目越来越工程化,再也不用担心忘记部署项目,也不用烦躁每次打包压缩后还要部署多个服务器和环境,更开心的是每次家里写完代码,不用远程公司部署项目,提交代码后自动会为你部署。 本文基于.NET4.0的web项目和SVN的代码仓库以及Windows(其他系统平台大同小异),简述Jenkins实现自动部署的配置。

名词解释

持续集成

持续集成(Continous Intergration):一个大项目是由多个模块组成的,每一个模块都有具体的小组负责开发,但有时候本模块独立测试正常,但与其他模块一起集成测试就会出问题。需要经常把所有模块集成在一起进行测试,尽早发现问题。关注点在于尽早发现项目整体运行问题,尽早解决。 在持续集成方面,我们选择Jenkins。Jenkins是一款开源软件,拥有众多优秀的插件,依靠这些插件,我们可以完成一些周期、繁琐、复杂的任务。例如我们今天分享的持续发布,虽然Jenkins解决了我们繁琐复杂周期性的操作,但是没有解决我们在多种环境下编译构建的需求。而这个场景正是Docker的强项。通过Jenkins的pipeline我们可以实现代码检出、单元测试、编译、构建、发布、测试等流程的自动化,而最终通过Jenkins的Docker插件将产出物构建成镜像,方便部署到Docker环境。

持续部署

部署(deployment)还是发布(release)?部署一般指把应用或者服务“安装”到目标环境(开发、测试或者生产)中,而发布则应指把应用或者服务交付给最终用户使用。尽管这两个动作(尤其是在生产环境中)经常是同时发生的,但它们理应是两个完全不同的阶段。实际上一个好的持续交付流程恰恰应该把“部署”和“发布”解耦,变成两个可以独立控制的阶段。 部署的内容包括什么?无论是增量部署还是全量部署,都需要关注其部署的内容是什么,尤其是在广泛讨论微服务的今天。如果从部署角度看,我们把任何可以独立部署的内容称为一个“部署单元”。一个部署单元可以是一个模块,几个模块的联合体或者一个完整的应用,而如何划分则要视具体场景来定。一般来说,划分部署单元的最佳实践为一个可以独立演化、部署且和应用其他部分松耦合的集合。 全量部署(full):全部文件重新拷贝并覆盖。优点稳定性好,但对带宽的要求大,更新时间长。 增量部署(min):更新上个版本与最新版本之间的文件。优点速度快,对带宽的要求小,更新时间短,但若更新失败,则需要全量更新覆盖一次。 半增量部署(semi-increment):只更新近期有更改的文件。保存一个时间范围内的更新文件,最长一个月,集合了全量部署与增量部署的优点。压缩包小,对带宽的要求小,更新时间短,容错率高,可以实现一个月内的增量更新。 持续集成让我们新的代码源源不断的构建成了可发布的工程,这些工程经历了单元测试,自动化测试,但还没有接受过测试团队的严格测试。Jenkins是一个强大的持续集成工具,然而持续部署并不是Jenkins的强项,但是Jenkins拥有很多强大的插件。

持续交付

持续交付(Continous Delievery):用小版本不断进行快速迭代,不断收集用户反馈信息,用最快的速度改进优化。关注点在于研发团队的最新代码能够尽快让最终用户体验到。
作者:张熙 链接:https://www.jianshu.com/p/7e1e8d8e8ec5 来源:简书
1、传统我们的项目开发模式是产品调研提出需求,开发团队研究决定开发方案选型。然后开始一个周期的开发,模块开发完成之后开始模块间的联调。联调结束之后打包交付给测试团队。测试团队,系统测试或自动化测试,然后提交bug,开发团队修复bug,周而复始。
2、传统的模式中,存在着较多的不确定因素。例如,开发环境、编译环境、测试环境、生产环境,等不确定因素。人为介入打包中的不确定因素,缺乏单元测试和自动化测试的整合。从而导致的结果是,开发-测试-修复的周期较长,而且很多小的问题完全可以由单元测试进行覆盖。
持续交付并不是某个特定的软件,而是一个结果。这个结果要求团队可以随时的发布一个新的准确版本,而且要求在编译发布的过程中进行自动化测试,通过自动化测试可以及时的发现并定位存在的bug,修复bug之后再进行快速的发布到测试环境,测试团队直接进行测试。与传统模式的区别在于持续交付可以提前发现bug的存在和快速修复而不必等到测试人员的介入之后才发现。持续交付分解出来就是“持续”和“交付”。  持续 :持续要求任何时,候任何情况都能进行准确的发布,做到准确的发布需要注意以下几个关键点。
持续应该是一个周期性的,可以是每天的某个时间点,也可以是某次代码的提交,或者某次人为触发。所以人工进行构建是不可能的,需要自动化的构建,自动化要求构建的任何一个流程都必须以脚本的形式运行,代码检出、代码构建、各模块代码单元测试、集成测试、UI自动化测试等。
发布的程序版本不允许是各个模块在开发环境编译出一个版本作为交付,而要求在一个纯净的编译环境中进行构建。
构建的过程应该要求最大可能的固化,例如操作系统的版本,构建环境的版本,相关的依赖等。
避免从网络获取相关的文件,这点以nodejs为开发或编译的项目尤其重要,安装node的依赖包总是一个漫长的过程,就算有国内的源,一般的项目也需要一两分钟的node依赖包,这不符合快速构建。
交付 : 在持续编译的过程,使用自动化已经可以避免大多数的错误了。但是还是需要人为介入的系统测试,毕竟自动化的测试一般只能覆盖到70%左右。
根据我们团队内部推广这种工作方式的效果来看,持续集成确实让我们工作便利了许多, 每次代码的构建和自动化测试让我们及时发现存在的bug。好的工作模式也需要团队成员的遵守,团队成员应该积极的拥抱这种工作方式。

自动化优点

  1. 满足大型项目的需求:有时候开发人员在更新代码时在本地测试是正常的,但放在服务器上运行就会出问题。只有在生产环境下能正常跑起来的代码才算合格,关注点在于项目功能部署至服务器后可以运行。
  2. 节约人力成本:开发人员以前每次都是手动复制文件到所有服务器进行更新替换操作,而且每次更新都要需要多次登录多台服务器,容易产生厌倦感。
  3. 统一的版本控制:定期执行部署脚本,实现了单一源码统一部署,保证所实施的单位都是同一套代码的统一的版本。而且集成了自动为js文件和css文件创建hash值的功能,每次部署后都能自动更新cshtml文件引用js文件的版本信息,从而满足不清理浏览器缓存也能更新js文件的目的。
  4. 部署速度快:每次仅对增量部分进行更新,无论是文件分发还是配置更新的内容都会更少,部署需要的时间也就相对较短。
  5. 高安全性:部署时生成的更新包每次只会集成增量更新的文件,不会直接暴露系统的整套代码,避免代码泄露的风险。
  6. 高稳定性:由于是使用脚本进行操作,脚本能自行判断是否需要更新,更新时不会重复执行更新脚本;而且使用脚本进行文件替换,操作快速而准确,避免了手工误覆盖造成的平台不稳定。部署时是并发部署,互不影响。
  7. 代码检查:若代码有问题,则编译不成功,不会进行推送。增加了手动执行脚本回滚到上一个版本的功能。
  8. 集成度高:使用统一的管理平台,把所有操作都写成一套脚本,方便修改。操作都封装好了,不熟悉的人只要按操作步骤执行构建命令即可自动进行部署。
  9. 集成邮件通知:源码获取、编译、打包与部署分离;有完善的日志系统,可自动将每次编译打包的日志分发给提交代码的开发人员,并将简要的部署结果按事先编制的模板写入邮件正文;这样由于源码打包和部署是分离的,就明确了开发人员与运维人员的责任划分,开发人员只要关注是否能通过编译即可,运维人员在部署失败后会收到邮件,进行测试,并排查问题。

自动化缺点

  1. 第一次需要手动先同步更新一次:无法完成初始化的部署操作,若已部署过的系统,但不知道部署时的版本号,只能先进行一次全量部署,而且若因为网络原因导致部署失败,则没有提示,需要人工操作进行判断。
  2. 代码检查:无法满足所有的使用需求,因为有些代码虽然符合语法规范,可以正常编译,但里面的逻辑问题无法检测出来。所以增加了手动回滚到上一个版本的功能。