用 GitLab 持续集成解放你的双手

CI

GitLab CI/CD

Gitlab持续集成是Gitlab提供的一整套持续集成、持续交付解决方案。Gitlab自9.0版本开始增加了CI和CD功能,所以如果你的公司里的Gitlab上在Settings里找不到关于CI/CD的配置项那么你们确实该对公司的GitLab进行升级了。

我们公司之前项目部署一直在用一个叫瓦力的工具,虽然也能实现交付项目的功能但是也有不少弊端,比如:

  1. 前置任务和后置任务功能不够强大,需要专门写shell脚本来完成复杂的任务。
  2. build环境永远是一套,公司里有的php项目用的版本有5.6、7.0、7.1 ,java项目依赖的jdk版本不同,这些版本都会相互排斥,一旦一个版本的项目构建成功后必定会影响其他版本的项目。
  3. 构建过程和构建结果不够可视化。

后来公司有的项目陆陆续续开始使用GitLab CI,因为当时对这套解决方案研究不深不知道该如何在CI上进行代码回滚,如何管控生产环境的部署上线(比如只有权限高的人才能部署测试环境、构建完成后想手动部署生产环境而不是push后自动部署)所以只用来做构建和部署测试环境的代码。与此同时执行CI Jobs的机器仍然是一台物理机,上面需要全局安装了这些构建工具来完成项目构建工作,这仍然会遇到上面第二点项目代码版本依赖的冲突。

由于我自己现在在公司一个重点项目里做架构师,在项目开始之初就有打算将持续集成和持续交付这里好好梳理一下,解决上面这些比较突出的问题。最近由于这些问题爆发的越来越严重觉得有义务拿出一套比较好的解决方案来解决这些问题所以一直在研究解决这些问题的方案。

随着对Gitlab CI 这套方案理解的加深慢慢制定了如下的策略:

  1. 使用Docker来作为git runner 的executor(执行器),这样在每个Job完成后都会清理build环境。
  2. 应用不同的docker镜像来解决构建代码版本依赖的问题(php7的项目用php7的镜像起的容器来执行构建工作,5.6的就用php5.6 镜像起的容器去执行构建工作)
  3. 控制Git工作流,针对不同功能的代码分支分别写CI Job去执行构建、测试和部署的工作。并且master只接受合并请求不允许任何人push, 这样就能够控制发布正式环境的时间点了,而且部署操作除了push自动触发外也可以配置成在GitLab项目页面里手动点击按钮来部署。

我基本上是将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}里设置的是项目在服务端的路径。
  • 我在容器的镜像里安装了ansible, 发布正式环境时使用ansible将项目部署到正式环境对应的多个主机上。

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/lar...
https://docs.gitlab.com/ee/ci/yaml/#jobs
https://docs.gitlab.com/ee/ci/environments...

另外提供一个我写的Laravel项目的CI配置文件供大家参考,这是一个完全可以应用在大型项目交付上的CI配置,实践的时候更换成你们具体的配置,它也同时适用于除Laravel以外的其他项目只需要把不同阶段执行的任务换成对应的命令即可。

.gitlab-ci.yml: https://github.com/kevinyan815/gitlab-ci/b...

kevinyan001/git-runner:php7.1-node10是我做的一个专门用来跑CI任务的容器的镜像, 你可以针对你的需求制作其他的镜像。

Conclusion

GitLab CI/CD提供了一套通用的解决方案让你从最初的Coding开始到最后代码交付上线都能在它提供的工具集合中轻松完成,通过Git Runner的Executor执行不同阶段定制的任务进行代码build、集成测试、和部署上线。除此之外还可以帮我们完成API文档生成、代码检查、Wiki文档构建等工作,只要在Linux Bash Shell中能实现的任务它都能帮你实现。它支持用很多不同类型的Executor来执行CI Jobs,其中我最推荐使用的类型是Docker Executor,这样我们的build环境就不依赖于Git Runner宿主机上的环境,从而能够应用不同容器完成各种不同项目的构建工作。


推荐一个这两天很火的数据结构和算法课程,之前买过不少讲持续交付、和微服务架构的课程,无奈东西太空看了两天就坚持不下去了,数据结构和算法是一个可以边学边实践练习比较基础的东西,不光对技术水平有提升,对参加一线公司的面试也是很有帮助的。

本作品采用《CC 协议》,转载必须注明作者和本文链接
公众号:网管叨bi叨 | Golang、Laravel、Docker、K8s等学习经验分享
本帖由系统于 5年前 自动加精
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 16
ThinkQ

很好

5年前 评论

111 配置的服务器,跑不动 Gitlab ,心情复杂 (´・_・`)

5年前 评论

@dongzt 其实如果公司规模小不用自己搭建GitlLab服务,可以在gitlab.com官网上创建私有仓库托管你的代码, 官方会提供共享的runner供项目使用。

5年前 评论

@花蝴蝶 这个确实是的,上次在自己的服务器上面搭建,内存一直是跑满的状态,无赖回滚系统

5年前 评论

@花蝴蝶 自己的项目可以在gitlab官网托管代码用免费的runner来跑,现在改叫auto devops了。公司的项目就用公司服务器吧,我们在一个8核16g的服务器上跑,构建速度还可以。

5年前 评论

phpcs_source.html 这个文件哪里能获取

5年前 评论

@zhaomengqiao 需要基于自己的Gitlab仓库域名或者IP
{仓库组}.域名/项目名/phpcs_source.html

5年前 评论

不好意思,我理解错了。
再问您个问题,我看了您github的那个yml片段,有2个测试环境,如果2个测试环境不是一个服务器的话
$SSH_KNOWN_HOSTS
这个变量就得放2个部署公钥吗?
@KevinYan

5年前 评论

@zhaomengqiao

不需要哦, 你可以把所有环境服务器的主机的host keys放在里面, 就跟你电脑连接所有主机后所有主机的hostkey 都放在本地电脑的known_hosts文件里一样。 这块有两个目的:
一是确认是受信任的机器与主机连接,二是因为docker容器每次构建后都会销毁,相当于每次ssh连接主机时都是首次连接没有known_hosts的话会提示让输入yes信任主机,这个会直接中断任务。

5年前 评论

老哥,我最近也在弄这一块,有些概念不太清晰,能否请教你一些问题,

stages:
  - deploy
deploy:
    stage: deploy
    script:
      - script
    only:
      - master
    tags:
      - local-tag

就类似这个yml配置中的script中的脚本的执行环境是在哪里呀,我自己的理解是在GitLab-runner的主机上,但是我是用docker部署GitLab-runner的,这么一来我的运行环境就是在这个docker容器中,但是我这个脚本是在主机上的,那我岂不是 在运行这个容器的时候还要把主机中脚本路径和ssh key及操作的目录映射到docker容器中嘛?我不知道我的理解对不对,请大佬指点!拜谢~

4年前 评论

@changpeng script在docker里执行

4年前 评论
qiuyuhome

没有数据库镜像, 怎么执行的数据迁移?

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
113
粉丝
364
喜欢
484
收藏
314
排名:34
访问:20.3 万
私信
所有博文
社区赞助商