引入
这篇文章是自己工作多年对CI/CD的理解,纯属个人见解。
不想说太多概念性的东西,直接从技术人员实际能接触的过程来展开说说。另外我这篇只是想关注一些通用的流程,细节的不同这里不纠结。比如微服务的CI/CD和单体服务有些不同,如果涉及到容器和k8s,又会有不同的地方。这里都不展开说。
CI指的是持续集成,CD指的是持续部署。合在一起通常包含这几个过程:
代码阶段
代码节点也可以叫开发阶段,这个阶段我们一般是本地开发代码,这个阶段首先涉及到一些开发工具比如idea,vscocode等。
同时,我们需要一个代码托管工具,常用的比如git,当然并不限制一定要用git。
最后还有一个很重要但是容易被忽略的环节,就是code review(简称cr),cr的重要性无需多说,在国外很多科技公司,cr都是一个强制的流程。国内感觉最近几年对cr也越来越重视了,我之前在的一个公司,代码没有经过cr是不允许发布到测试环境的。
关于cr阶段使用的工具,不同的公司一般不一样。我见过直接使用idea等开发工具进行cr的,也有用gitlab等托管工具cr的,有些大点的公司有自己开发的cr工具。不过工具不重要,重要的是过程。
编译阶段
编译阶段也可以叫构建阶段。首先通常会考虑依赖的问题,比如编译java代码会考虑jdk的版本,pom依赖等这些都是需要解决的。
其次一个要关注的点就是单元测试,编译阶段一般都会自动运行你在开发阶段编写的单元测试代码(当然前提是你写了,哈哈)。同时单元测试要确保一定的覆盖率,覆盖率很低的单元测试也没啥意义。这样要求我们要一个良好的开发习惯:写单元测试。关于单元测试的种种,不是本文的重点,这里不表。
编译没问题,并且单元测试没问题,一般就可以构建、打包发布到测试环境了。打包发布常用的工具是jenkins,如果涉及到容器部署,这个阶段通常我们也会打包服务的镜像并且推送的镜像仓库(可以是私有仓库或者公有仓库)。
测试环境
我们的服务打包到测试环境之后,一般我们需要在测试环境进行集成测试,所谓的集成测试,就是把流程整合按照接口或者某个特定功能的测试。比如下单的流程,可能涉及很多模块,我们对下单这个流程的测试就属于集成测试。
生产环境
生产环境涉及的环节比较多,也是最重要的。毕竟这是最终交付的环节,前面所有的努力都是为这一步做准备。
当我们发布到生产环境时,通常不会马上进行全量的发布,而是先进行灰度部署。灰度部署是指逐渐将生产环境流量从老版本切换到新版本。通常流量是按比例分配的。例如 90% 的请求流向老版本,10% 的请求流向新版本。然后没有发现问题,就逐步扩大新版本上的流量,减少老版本上的流量。
这种能最大限度的减少出现故障造成的影响。
实现灰度发布有很多方案,比如通过前端的cdn技术,后端的方案就更多了,比如基于nginx实现,如果你是基于容器部署,可以通过k8s的ingress实现灰度发布等。
灰度验证完没有问题,一般就可以进行全网发布了。尽管前面已经做了各种测试了,全量发布后依然不能保证一定不会出问题,因为有些问题可能是流量很大的时候才会暴露。这就要求我们一定要有回滚机制,当线上出问题时能够快速的回滚到上一个版本。
另外一个关注点就是,服务上线后持续的监控以及出现问题的及时告警机制。这种一般要借助于一些第三方的监控工具,比如Prometheus等。