从零打造自己的CI/CD系统|编译产物分发
不同语言的编译结果是不一样的,
Java
的使用mvn
编译之后的产物是jar
或tar
包,PHP
采用composer
编译后的产物非压缩包,nodejs
采用npm
编译后的产物也是非压缩包,这个时候每个公司的同步场景可能不一样,有的是把编译后的产物上传到工件库里,在CD
的过程中进行拉的动作,这样的实现是不同的环境使用同一份编译后的产出,避免因环境不同而造成的代码不同偏差。下面我们来聊聊应用编译后产物的同步机制。
常见的同步机制
•编译一次,上传工件库,然后各环境部署的时候都是从工件库里获取•在中控机(发布机)上进行编译动作,然后进行分发•在RS
上进行编译动作,然后把编译后的产物移动到指定的目录
工件库分发
大家看到这个,其实会想到Docker
, 因为这个工作机制和Docker
的镜像是类似的,好处就是减少时间因环境环境变更(dev--->test--->prod)确保都是同一份源代码编译出的产物,减少因为环境变更过程中有人再次提交代码到上线分支里去,不过,真的要实现上述所说的场景还是有点难度的,首先选型的工件库要支持多语言的存储,再则就是应用对应的gitlab
的仓库名称尽可能要和项目的名称保持一致,或有一个约定,这样在后续CD
分发的过程中,调用工件库获取对应的编译后产物才能做到一对一(当然也可以入库,每次读取最新的)。
其实也有不好的点,那就是CI
这一部分没有做好的话,用这种方式其实是自带枷锁,大家可以自己思考下~
发布机分发
在发布机器上编译一次,然后进行分发操作,这种方式也有自己的优缺点
优点
•不用每台RS
上都安装编译环境(mvn, composer, npm)等•同样的工作只需做一次(发布机上做一次编译即可)•分发之前不会产生额外的网络消耗
缺点
•每次都是拉最新的代码进行编译,如果分支模型没有一个很好的约束,那将是一场灾难
RS机器上分别操作
在机器上直接进行编译动作,这个在有几台机器的情况下这么做还凑合,机器也业务量上来的情况下,再这么搞,真的是挖坑了,原因是有两点:
•在RS机器上进行编译,首先需要环境,你需要在每台机器上都要安装对应的环境•在业务机器上,我个人是很反感安装和当前业务无关的应用的(监控,日志组件这些不算)
分发注意事项
类似php, python等语言的编译产物,一定要排除.git目录
相信大家在网上也会经常看到很多文章提到,通过.git
目录还原源代码的操作,如果没有做防范,大家打开你的站点,https://example.xxx/.git/config, 那真的是呵呵了,当然了,java的话,那就不需要这么做了,视场景来决策要采取的动作。
过滤不必要的目录
在我们写代码或使用Docker
的时候,我们会用到.gitignore
和.dockerignore
两个文件来排除掉我们不想上传到仓库或打到镜像里的文件或目录,那么在CI/CD
的过程中,我们同样需要去主动排除一些非runtime
依赖的目录和文件。
使用Ansible实现编译产物分发
这里我们采用的方式是上面说的第二种方式,在发布机器上进行编译,然后分发
逻辑大概讲解
•区分环境,然后根据上篇文档描述,创建本地编译后的产物的存放目录•然后同步本地目录内的产物到远程机器上去,部署过程rolling update
实现代码如下
总结
应用分发也是一门大学问,在海量机器 顶级流量的场景下,分发一次的时间成本还是蛮高的,所以很多公司自研了内部分发平台,大家可以去搜索下p2p传输
看看,之前百度是有做过类似的公开演进,十万 机器的极速分发,感兴趣的小伙伴可以去搜索下看看。