两年前在开始一个新的商业项目时我花了两个星期时间在项目开发流程中应用上了持续集成,随后一年又随着项目的发展和商用化做了很多改进。所以掌握了GitLab 持续集成这套方案在商业软件中完整的落地实践经验。文章最早发布在其他平台,当时引起了不少关注,内容虽然是对一个PHP项目持续集成的设置,但是整个持续集成是完全容器化的,这套解决方案可以很方便的应用于任何编程语言的项目。希望文章能对你有所帮助和启发。
公众号里关键字回复CI 可以获取完整的持续集成方案的编排文件和容器的Dockerfile 作为实践时的参考。
Gitlab持续集成是Gitlab提供的一整套持续集成、持续交付解决方案。Gitlab自9.0版本开始增加了CI和CD功能,所以如果你的公司里的Gitlab上在Settings里找不到关于CI/CD的配置项那么你们确实该对公司的GitLab进行升级了。
我们公司之前项目部署一直在用一个叫瓦力的工具,虽然也能实现交付项目的功能但是也有不少弊端,比如:
后来公司有的项目陆陆续续开始使用GitLab CI,因为当时对这套解决方案研究不深不知道该如何在CI上进行代码回滚,如何管控生产环境的部署上线(比如只有权限高的人才能部署测试环境、构建完成后想手动部署生产环境而不是push后自动部署)所以只用来做构建和部署测试环境的代码。与此同时执行CI Jobs的机器仍然是一台物理机,上面需要全局安装了这些构建工具来完成项目构建工作,这仍然会遇到上面第二点项目代码版本依赖的冲突。
由于我自己现在在公司一个重点项目里做架构师,在项目开始之初就有打算将持续集成和持续交付这里好好梳理一下,解决上面这些比较突出的问题。最近由于这些问题爆发的越来越严重觉得有义务拿出一套比较好的解决方案来解决这些问题所以一直在研究解决这些问题的方案。
随着对Gitlab CI 这套方案理解的加深慢慢制定了如下的策略:
我基本上是将CI分成 build
, test
, deploy
三个阶段, build
里主要就是完成项目代码依赖包的安装(composer 和 npm install 之类的工作, 我们前后端是两个项目,前端项目事先需要针对不同环境配置不同的打包命令)。
build:
stage: build
image: kevinyan001/git-runner:php7.1-node10
script:
- /usr/local/bin/composer install
only:
- develop
- uat
tags:
- your-runner-tag
test
阶段会去执行项目中编写的测试用例:
test-dev:
stage: test
image: kevinyan001/git-runner:php7.1-node10
script:
- php artisan migrate --force
- ./vendor/bin/phpunit
only:
- develop
tags:
- your-runner-tag
deploy
阶段完成项目最后的部署和一些服务器reload操作最终将项目交付上线。
deploy-testing:
stage: deploy
script:
- rsync -az --delete --exclude=.git --exclude=.gitignore --exclude=.gitlab-ci.yml ./ $SERVER_TOKEN_TEST:$WEB_ROOT_TEST
- ssh $SERVER_TOKEN_TEST -t "chown -R www:www ${WEB_ROOT_TEST}"
environment:
name: test
url: http://test.example.com
only:
- develop
tags:
- your-runner-tag
说明:
$SERVER_TOKEN_TEST
这些是提前在GitLab项目的Settings --> CI/CD Pilelines里定义的变量,执行任务时容器会在BASH SHELL中读入这些预先定义的变量。$SERVER_TOKEN_TEST
里设置的内容是 user@server_ip
, ${WEB_ROOT_TEST}
里设置的是项目在服务端的路径。git runner会在每个Job的开始阶段通过镜像 kevinyan001/git-runner:php7.1-node10
跑一个容器,在容器中执行这些操作,等Job执行完后容器会被停止并清理掉,这就需要我们在每次容器起来的时候在容器里执行一些预备工作,比如与目标服务器建立信任关系这些基础的工作,我是通过将SSH PRIVATE KEY注入到容器中,目标服务器事先放上对应的公钥来建立容器与目标主机的信任关系的:
before_script:
- mkdir -p ~/.ssh
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' > /root/.ssh/id_rsa
- chmod -R 600 ~/.ssh
- echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
- mkdir -p /etc/ansible
- echo 'xx.xx.xxx.xxx db_master' >> /etc/hosts #make container can connect to mysql server
- echo 'xx.xx.xxx.xxx db_slave' >> /etc/hosts
具体可以参考gitlab ci关于这一块的说明文档:https://docs.gitlab.com/ee/ci/ssh_keys/
由于GitLab CI的功能非常多,可配置像也很多所以具体某个配置的作用我就不细说了,贴几个我认为比较有用的说明文档出来节省大家的搜索时间。https://docs.gitlab.com/runner/register/ https://docs.gitlab.com/ee/ci/ https://docs.gitlab.com/ee/ci/examples/laravelwithgitlabandenvoy/ https://docs.gitlab.com/ee/ci/yaml/#jobs https://docs.gitlab.com/ee/ci/environments.html
另外提供一个我写的Laravel项目的CI配置文件供大家参考,这是一个完全可以应用在大型项目交付上的CI配置,实践的时候更换成你们具体的配置,它也同时适用于除Laravel以外的其他项目只需要把不同阶段执行的任务换成对应的命令即可。
kevinyan001/git-runner:php7.1-node10是我做的一个专门用来跑CI任务的容器的镜像,已经上传到了 Docker 官方的镜像源中可以直接使用。你可以针对你的需求制作其他的镜像。公众号回复CI可以获得源版的Dockerfile。
GitLab CI/CD提供了一套通用的解决方案让你从最初的Coding开始到最后代码交付上线都能在它提供的工具集合中轻松完成,通过Git Runner的Executor执行不同阶段定制的任务进行代码build、集成测试、和部署上线。除此之外还可以帮我们完成API文档生成、代码检查、Wiki文档构建等工作,只要在Linux Bash Shell中能实现的任务它都能帮你实现。它支持用很多不同类型的Executor来执行CI Jobs,其中我最推荐使用的类型是Docker Executor,这样我们的build环境就不依赖于Git Runner宿主机上的环境,从而能够应用不同容器完成各种不同项目的构建工作。
如果对 GitLab 持续集成的使用上有什么疑问,可以在文章下方留言, 喜欢我的文章欢迎点在看和转发支持。