理解 DevOps —— CI 持续集成

DevOps 是 Development 和 Operations 的组合,即将软件交付过程中开发与测试运维的环节通过工具链打通,并通过自动化的测试与监控,减少团队的时间损耗,更加高效稳定地交付产品。

理解 DevOps —— CI 持续集成_第1张图片

CI(Continuous Integration),即持续集成,指频繁地(一天多次)将代码集成到主干的行为。这里既包含持续将代码集成到主干的含义,也包含持续将源码生成可供实际使用的制品的过程。在 CI 阶段的实现至少应该有:

  1. 静态代码检查:ESLINT/TSLINT 静态语法检查,验证 git commit message 是否符合规范,提交文件是否有对应 owner 可以 review 等等。这些静态检查不需要编译过程,直接扫描源代码就可以完成。
  2. 单元测试/集成测试/e2e 测试:自动化测试是保障制品质量的关键。测试用例的覆盖率及用例质量直接决定了构建产物的质量,因此,全面且完善的测试用例也是实现持续交付的必备要素。
  3. 编译并整理产物:对于大型项目来说,多次频繁的提交构建会产生数量庞大的构建产物,需要得到妥善的管理。

流水线

需要确立合适流水线的组织形式,和版本的发布模式以及源码仓库的分支策略。

CI 工具都原生或通过插件方式支持 ConfigurationasCode,即使用配置文件管理流水线作为组织形式。如此,便不再需要页面专门用于流水线管理。其次,将流水线配置集成在源码仓库中,享受与源码同步升级的方式,使得 CI 流程也能使用 git 的版本管理进行规范与审计溯源。

版本发布模式有三要素: 交付时间、特性数量以及交付质量。大型项目持续交付的要求是每开发完成一个特性通过持续集成不断自动进行测试,完成后合入等待发布。

可以主干开发,主干发布的分支策略:开发团队的成员尽量每天都将自己分支的代码提交到主干。在到达发布条件时,从主干直接拉出发布分支用于发布。若发现缺陷,直接在主干上修复,并根据需要 cherry pick 到对应版本的发布分支。是否有必要采用主干开发的方式:

  • 完善且快速的自动化测试。只有在单元测试、集成测试、E2E 测试覆盖率极高,且通过变异测试得出的测试用例质量较高的情况下,才能对项目质量有一个整体的保证。
  • Owner 责任制的 Code Review 机制。让开发人员具有 Owner 意识,对自己负责的模块进行逐行审查,可以在代码修改时规避许多设计架构上的破坏性修改与坑点。
  • 大量的基础设施投入。高频的自动化测试其实是一个相当消耗资源的操作,尤其是 E2E 测试,每一个测试用例都需要启动一个无头浏览器来支撑。另外,为了提升测试的效率,需要多核的机器来并行执行。
  • 快速稳定的回滚能力和精准的线上及灰度监控等等。只有在高度自动化的全链路监控下,才能保证该机制下发布的新版本能够稳定运行。

产物 -> 产品

代码编译完成生成产物,如果采用直接使用复制粘贴的方式来操作文件的更新与覆盖,这样既不方便对更新历史的审计与追溯,同时这样的更改也很难保证正确性。而且当需要回滚版本时,由于服务器上并没有存放历史版本,而回滚的方式也就成了重新编译打包生成历史版本的产物进行覆盖。这样的回滚速度和正确性显然无法得到保证。

正确的做法是:不要对文件进行任何的覆盖更新,所有的产物都应该被上传持久化存储。可以在请求上游增设一个流量分发服务,来判断每一条请求应该返回哪一个版本的产物。

在每次编译完成后,产物将会进行如下的整理以生成最终的前端制品:

  1. 针对静态文件,如 CSS、JS 等资源将会发布到云对象存储中,并以此为源站同步给 CDN 做访问速度优化。

  2. 针对 HTML 制品,需要一个直出服务做支撑,并打包成 docker 镜像,与后端的微服务镜像同等级别,供上游的流量分发服务(网关)根据用户请求选择调起哪些服务负载进行消费。

效率

流水线的执行时间——集成速度即效率。可以从以下几个方面进行流水线效率优化:

  • 流水线任务编排原则: 无前置的任务优先, 执行时间短的任务优先, 无关联的任务并行
  •  Docker Cache:在 Docker 镜像的构建过程中,Dockerfile 的每一条可执行语句都会构建出一个新的镜像层,并缓存起来。在第二次构建时,Docker 会以镜像层为单位逐条检查自身的缓存,若命中相同镜像层,则直接复用该条缓存,使得多次重复构建的时间大大缩短。比如首次构建时将 node_modules这个文件夹打包成为镜像供下次编译时调用。 在下次编译之前,比对本次构建与镜像缓存中的 package-lock.json文件的 md5 码是否一致。
  • 分级构建:即把CI 流水线拆分为主构建和次级构建两类,其中主构建需要在每次提交代码时都要执行,并且若检查不通过无法进行下一步操作。而次级构建不会阻塞工作流,通过旁路的方式在代码合入后继续执行。但是,一旦次级构建验证失败,流水线将会立即发出通知告警,并阻塞其他所有代码的合入,直到该问题被修复为止。

任务归于次级构建的原则:

  • 执行时间长(如超过 15 分钟)、耗费资源多的任务,如自动化测试中的 E2E 测试。
  • 用例优先级低或者出错可能性低的任务,尽量不要包含重要链路。
  • 考虑用合适的方法分割测试用例,并行测试。

你可能感兴趣的:(前端,devops,ci)