前置假设
整体环境
将docker,jenkins服务器,目标服务器视作三个不同的环境
部署核心流程:获取代码,编译代码,部署代码
每个整体环境都有可能承担部分或者所有核心流程,或者增加一些额外流程。
针对于不同语言,不同体系,核心流程可能有不同
| | 获取代码 | 编译代码 | 部署代码 |
| —— | ———————- | ——————— | ——— |
| java | git/svn/压缩包压缩解压 | mvn, gradle等 | java -jar |
| Node | git/svn/压缩包压缩解压 | npm build | nginx |
| Python | git/svn/压缩包压缩解压 | 无需编译/某种形式编译 | gunicorn |
核心流程外的额外流程:静态检查,ut,sit等
假设docker,jenkins服务器,目标服务器均有能力做到获取代码,编译代码,部署代码功能。
部署常见思路
为了规避形如security,耗时等问题,将获取代码,编译代码,部署代码三个流程拆分到不同的整体环境去做。
1)A和B为同一台服务器
即jenkins服务器就是目标服务器,A做到clone代码,编译,运行即可。
2)A和B是不同的服务器
A clone代码,如果jenkins有对应的编译环境,则可考虑让jenkins编译好,将编译后代码传输给B,B进行部署即可。
3)A是内网的机器,B是外网的机器,但是不需要保障代码安全
此时仅A有clone代码的权利,除此之外和A无区别。
4)A,B都是内网服务器,但是无法传输文件,只能传输命令
此种情况少见,但是由于A,B均在内网,B应该也有clone代码的权限,所以可以由A调用B,让B实现clone,编译,运行。
5)不止一台B服务器,B总共包含10台服务器,需要一起启动
类似于分布式部署,在B具备合理环境的情况下,形如1,2,3,4处理均可。
6)B服务器不仅包含多台服务器,还具备不同的环境
此种情况复杂,可以一台台服务器解决环境问题,另一种方式是将通用环境打成docker image,传给各台服务器进行部署。
从以上结果来分析,部署的复杂程度是由于服务器环境造成的,如何屏蔽环境因素影响是重要问题,所以可以引入docker来解决。
较为通用的解决方案
几个大原则:
- 将部署环境交给docker,从而解决目标服务器环境不一致的问题;
- 如果目标服务器的编译环境较好,例如部署java应用,则可以考虑将编译过程交接给目标服务器,从而降低jenkins服务器的编译压力,也降低jenkins的环境管理压力(如果jenkins承载服务较多的情况);
- 在2的情况下,还有种较为魔幻的做法,将编译环境也打包成一个docker,每次需要编译的时候就启动这个docker打包一下,将打包结果留下来,然后通过jenkins分发给目标服务器(群)。
另类做法:如果jenkins服务器压力非常巨大,甚至可以考虑将pull代码的流程交接给docker,即docker承载了获取代码,编译代码,部署代码三个大任务。
但是此种做法具备一些细节问题:
- docker的镜像将会较大,因为编译代码需要的环境通常需要下载,成本较高;
- docker build或者run的时长会较长,时间成本较高。
即使如此,他拥有一个无法比拟的优势:干净,在何处运行该代码都不会出问题,除非内核不兼容,所以在某些特殊情况下依然是一个可选项。
对docker的常规用法
- 每次pull代码后,进行编译,然后将编译结果用命令放到docker image中,进行docker build,之后docker run;
- 每次pull代码后,进行编译,然后将编译结果用命令放到docker image中,进行docker build,之后上传到dockerhub,从而让其他服务器都能pull该image进行部署。
用法1适合于用于部署数量较少(或单台)的服务器情况,因为可能需要每台服务器单独去做build,用法2适合用于部署数量较多,或者环境不干净(或不统一)的服务器的方式,成本是增加了dockerhub的转接。
总结
总体来说,在有限资源,有限环境等情况下里做自动化的CI/CD需要衡量应用部署的数量,服务器的承压能力,上线耗时,部署成本等,并且想办法选取一种尽可能具有通用性的方式来进行部署,尽可能降低ops的人工成本,也降低dev的开发成本。
目前SKR1.0和Inspire运维方案
SKR1.0
不使用jenkins,手工部署,使用prod, test来区分运维环境。
Inspire
后端
jenkins clone 代码,压缩后传输给目标服务器,目标服务器解压,通过解压得到的dockerfile来build image,build完成后,使用docker-compose启动,开放端口用于访问。
前端
前端同事编译代码,并且压缩,提交代码,jenkins clone代码,将压缩后的编译结果传输给目标服务器,目标服务器解压得到h5目录(静态资源),然后使用服务器自带的nginx进行静态资源映射,从而使外网访问。
未来可能考虑方案
后端:由于要迁移到btp,而btp上的cloud foundry只有java1.8的环境,所以无法使用cf直接进行编译和部署,因此采用docker的形式进行部署,需要上传image到dockerhub来完成(已试验成功)。
前端:暂未测试,使用docker大概率可以走通,成本较高,最好还是不走docker。