持续集成&持续部署
持续集成的思想
持续集成就是指开发人员修改了代码之后,要经常随时地对代码库进行集成,对代码进行重新构建和测试。目标是让正在开发的软件一直处于可运行状态。(即便是被破坏了,也能很快知道,环境运维人员可以很快修复。)
如何实现持续集成
准备工作
- 版本控制 (与项目相关的所有内容都必须要提交到一个版本控制库中。包括产品代码、测试代码、DB脚本、构建和部署脚本以及所有用于创建、安装、运行和测试该应用程序的东西。)
- 自动化构建 (也就是人和计算机都能用命令行自动执行应用的构建、测试、部署过程。无论是通过命令行程序启动IDE来构建应用程序进行运行和测试,还是使用多个复杂的构建脚本通过互相调用的方式来完成。)
- 团队共识 (需要每个人都能以小步增量的方式频繁地将修改后的代码提交到主干分支,把修复破坏应用程序的任意修改当作最高优先级的任务。)
前提条件
- 频繁提交 (定期地将代码提交到主干分支的好处很多,比如(比较适用于后端同学):每次修改都不大,能够减少构建失败的次数;出了问题可以轻松的回滚或者修复;有助于保证设计多个文件的修改尽量不会影响别人的工作。)
- 创建全面的自动化测试套件(单元测试、组件测试、验收测试;通过组合使用这三类测试,来确保引入的修改不会破坏现有的任何功能。聊聊VT常规版本和XIB的功能冲突)
- 保持较短的构建和测试过程 (如果构建时间很长的话,可能大家不太愿意在本地环境进行构建和测试,导致失败的概率越来越大。集成间隔时间长,该构建会包含很多提交,容易出问题。)
持续交付&部署(CD)
我们的目标应该一直是交付质量足够高的软件,给客户带来价值。尽快的交付软件很重要,保证一定的质量是基础。
实现一个部署流水线
持续集成的主要关注对象是开发团队,关注代码是否可以编译成功以及是否能通过单元测试和验收测试。 持续部署关注的是是否能够通过一键式的方式把某个版本部署好。
部署流水线 (别名:持续集成流水线、构建流水线、部署生产线、现行构建)
根本上就是一个自动化的软件交付的流程。由以下几个阶段组成:
- 对价值流建模,并创建一个可工作的简单框架
- 提交阶段:从技术角度上断言整个系统是可以工作的,这个阶段会进行编译,运行一套自动化测试(主要是单元级别的测试),并进行代码解析。
- 自动化验收测试阶段:从功能和非功能(比如说性能和安全性等方面)角度上断言整个系统是可以工作的。也就是从系统行为上看它满足用户的需要并且符合客户的需求规范。
- 手工测试阶段:用于断言系统是可用的。用于发现那些自动化测试未能捕获的缺陷,并验证系统是否为用户提供了价值。这个阶段通常包括探索性测试、集成环境上的测试、以及UAT(User Acceptance Test 用户接受度测试即验收测试)。
- 发布阶段:旨在将软件交付给用户,可能是套装软件的方式,也可能是直接将其部署到生产环境,或试运行环境。
持续部署的好处
- 越频繁的发布,会让发布风险越低。因为这样版本间的差异越小。
- 持续部署迫使你做正确的事情。没有完整的自动化构建、部署、测试、发布流程就做不到持续部署;没有全面可靠的自动化测试集合也做不到持续部署;没有在类生产环境中运行的系统测试,也做不到持续部署。(划重点)这就是为什么尽管你无法真正的做到每次的修改通过测试后就发布,也应该创建一个自动化流程。当你想这么做时,你就有能力这么做了。
组件管理
什么是组件
组件是一个应用程序中一个规模相当大的代码结构,具有一套定义良好的API,可以被另一种实现方式代替。是能够独立部署的。对于一个基于组件的软件系统来说,通常其代码库被分成多个相互分离的部分,每个部分通过有限的定义良好的接口提供一些服务行为,与其他组件进行有限的交互。
组件开发的优点:
组件开发让软件开发流程更高效,原因是:
- 它将问题分成更小且更达意的代码块
- 组件常常表示出系统不同部分代码的变化率不同,并且有不同的生命周期。
- 它鼓励我们使用清晰的职责描述来设计并维护软件,反过来也限制了因修改产生的影响,并使得理解和修改代码库变得容易。
- 它给我们提供了额外的自由度来优化构建和部署过程。(可独立构建和部署,编译的时间不至于太久)
将组件流水线化
使用多构建流水线的原因:
- 应用程序的某些组成部分有不同的生命周期。
- 应用程序的几个功能领域由不同的团队负责,那么这些团队可能有自己的组件。
- 某些组件使用不同的技术或者构建流程。
- 某些共享组件被不同的几个项目使用。
- 组件相对稳定,不需要频繁修改。
- 全面构建整个应用程序所花时间太长。
组件构建部署步骤同上述部署流水线一致。
事实上,组件构建的原则是:应该尽量将需要管理的构建数量最少化。一个优于两个,两个优于三个,以此类推。持续优化构建,让它更高效,尽可能保持单一流水线,只有当效率低到无法忍受,才使用并行流水线方式。
编译制品是如何运作的
制品是指由源码编译打包生成的二进制文件,不同的开发语言对应着不同格式的二进制文件,这些二进制通常可以直接运行在服务器上。
制品库用以管理源代码编译后的构建产物,支持 Docker、Maven、npm 包等常见制品库类型。制品库可以跟源代码协同进行版本化控制,可以与本地各构建工具和云上的持续集成、持续部署无缝结合,并支持漏洞扫描等特性,是一种企业处理软件开发过程中产生的所有包类型的标准化方式。
制品库最重要的特性就是,它不应该包含哪些无法重现的产物,你应该能删除制品库,却不必担心无法找回有价值的内容。为了达到这一点,版本控制系统就要包含重建这些二进制包所需的所有内容,包括自动化构建脚本。 删除这些二进制产物的原因是这些产物很大,即使现在不大,将来也会变得很大,考虑到存储空间,最终都需要删除它们。将已经通过测试、待发布的候选版本、已发布的制品保存下来是非常值得的。在回滚的时候需要用到,或者需要对旧版本用户提供支持。
最简单的制品库是磁盘上的一个目录结构,构建系统为每个构建生成一个标识,通常是个序号。 为每个流水线创建一个目录,该目录中,为每个构建号创建一个与之对应的子目录,制品都放在子目录下。
部署流水线与制品库相结合
- 编译阶段会创建需要放到制品库的二进制文件
- 单元测试和验收测试阶段会取出这些二进制文件,并在其上运行单元测试和验收测试,将生成的测试报告放到制品库中,方便查看结果。
- 用户验收测试阶段是将制品文件部署到UAT环境中,用于手工测试。
- 发布阶段是取出二进制文件,将其发布给用户或者部署到生产环境中。
应用程序的部署与发布
生产环境与开发环境到底有多大的不同?
如果生产环境要运行在不同的操作系统上,那么UAT环境应该使用与生产环境一样的操作系统; 如果生产环境是一个集群环境,那么应该搭建一个有限的小集群作为试运行环境; 如果生产环境是分布式且多节点环境,就要确保类生产环境至少用一个独立的进程来代表每类进程边界。
为了达到发布质量,一个构建版本要通过那些测试阶段(集成测试、QA验收测试、用户验收测试、试运行以及生产环境)
蓝绿部署
蓝绿部署涉及两个生产环境:
- 蓝环境指代正在使用的生产环境。
- 绿环境则将发布一个新版本。
蓝绿部署的优点:
- 可在绿环境下进行测试,而不会中断蓝环境。
- 切换到绿环境不需要停机,只需要重定向用户流量。
- 问题发生时,可很方便地从绿环境回滚到蓝环境,只要将流量重定向回蓝环境即可,而无需重新构建。
- 需要变更时,利用不可变基础设施原则初始化新的实例,避免实例配置产生不一致性。
灰度发布(金丝雀发布)
灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。就是把系统的某个新版本部署到生产环境中的部分服务器中,从而得到快速的反馈。就像蓝绿部署一样,先部署新版本到一部分服务器上,然后在新版本上做冒烟测试。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。
以前,旷工在下矿洞是面临的一个重要危险是矿井中的毒气,他们想到一个办法来辨别矿井中是否有毒气,矿工们随身携带一只金丝雀下矿井,金丝雀对毒气的抵抗能力比人类要弱,在毒气环境下会先挂掉起到预警的作用。它背后的原理是:用较小的代价试错,即使出现了严重的错误(出现了毒气),系统总体的损失也是可承受的或者是非常小的(失去了一只金丝雀)。