Gitlab+Jenkins实现简单的CICD
前言
首先我这里用的Gitlab比较老8.16.9且是源码编译安装, Jenkins版本2.303.1,Gitlab、Jenkins的安装就不细说了。主要想解决的问题是,在某个git项目提交的时候调用Jenkins,然后Jenkins把项目自动打包/部署到某一台服务器的指定目录。
- 注: 公司内的网络打通、权限和账号开通就不在这里详细说了。
方案设计
整体有两套设计方案, 各有千秋,按照自己公司内的实际情况来选择。当然你也可以不用Jenkins,也可以在钩子或者cicd触发的时候直接执行拉取-打包-同步-启动等命令。
方案一:
- 使用Gitlab Hooks,在用户提交代码后增加自己的操作、校验逻辑;
- 优点:配置灵活,可以配置全局、单项目等;
- 缺点:全局钩子需要会写ruby,单项目钩子需要放在项目仓库内, 维护不方便;
方案二:
- 使用Gitlab 7.0以后新增的CICD流程,使用Gitlab runner,控制提交后的操作、校验逻辑。
- 优点:单项目配置,任务可视化做的很好,维护方便;
- 缺点:需要添加Gitlab Runner组件。
个人认为钩子适合做提交代码检查之类的动作,Gitlab Runner更适合做CICD。
方案实施
Jenkins配置
首先创建Jenkins用户,并添加新的API TOKEN,记住TOKEN只会展示一次, 刷新页面后将无法再次获取。
我们创建一个新的任务,由于该项目比较简单,所以在构建里添加"Send files or execute commands over SSH"即可。
接下来我们尝试调用Jenkins API触发构建任务,这里面USER、TOKEN、JENKINSURI我用变量的形式替代,还有需要注意view后面的地址一定要用浏览器的地址+build,尽量不要手打。
并且由于Jenkins有 CSRF保护, 需要使用先获取CRUMB,然后后续请求在header中带着CRUMB即可。
> CRUMB=$(curl -s 'https://$USER:$TOKEN@$JENKINSURI/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
> curl -X POST -H "$CRUMB" https://$USER:$TOKEN@$JENKINSURI/view/%E6%95%B0%E6%8D%AE%E7%BB%84/job/datacenter/build
至此通过Jenkins API构建项目就可以了, 接下来我们把Git提交后触发自动构建做好就可以了。偷懒把命令写成一个shell脚本。
> vim jenkins_tools.sh
#!/bin/bash
USER=user
TOKEN=token
JENKINSURI=jenkins
CRUMB=$(curl -s 'https://$USER:$TOKEN@$JENKINSURI/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
curl -X POST -H "$CRUMB" https://$USER:$TOKEN@$JENKINSURI/view/%E6%95%B0%E6%8D%AE%E7%BB%84/job/datacenter/build
curl 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=send-key' -H 'Content-Type: application/json' -d '{"msgtype": "text","text": {"content": "已发布成功,请注意查看!"}}'
Gitlab Hooks
放一张网上找的图,大家可以看一下Git本身有很多钩子,大致分为两类(本地钩子、远程钩子),我们这里要用到远程钩子post-receive,其他钩子大家有兴趣可以自行搜索。
> ls gitlab-shell/hooks/
post-receive pre-receive update
使用vim并查看post-receive
#!/usr/bin/env ruby
# This file was placed here by GitLab. It makes sure that your pushed commits
# will be processed properly.
refs = $stdin.read
key_id = ENV.delete('GL_ID')
repo_path = Dir.pwd
require_relative '../lib/gitlab_custom_hook'
require_relative '../lib/gitlab_post_receive'
if GitlabPostReceive.new(repo_path, key_id, refs).exec &&
GitlabCustomHook.new(repo_path, key_id).post_receive(refs)
exit 0
else
exit 1
end
大家可以看出来这个脚本是用ruby写的,如果想要添加自己的操作并执行shell文件需要用以下方式,我用的触发脚本,把我需要的逻辑写到脚本里
puts `curl www.baidu.com`
或者
puts `sh ~/jenkins_tools.sh`
添加项目钩子,在项目仓库目录创建custom_hooks,并把jenkind_tools.sh内容写在post-receive里也可以。
> mkdir custom_hooks
> vim post-receive
> chmod 755 post-recevie
Gitlab Runner
首先下载Gitlab runner,官网参考连接: https://docs.gitlab.com/runner/install/linux-manually.html
由于我是Centos X86架构,直接wget就好了
>sudo wget https://gitlab-ci-multi-runner-downloads.s3.amazonaws.com/v1.11.2/binaries/gitlab-ci-multi-runner-linux-386
>chmod +x gitlab-ci-multi-runner-linux-386
>sudo ./gitlab-ci-multi-runner-linux-386 install --user=git --working-directory=~/gitlab-runner
在Gitlab项目中找到Runner,并根据setup配置,注意
#执行注册
>./gitlab-ci-multi-runner-linux-386 register
WARNING: Running in user-mode.
WARNING: The user-mode requires you to manually start builds processing:
WARNING: $ gitlab-runner run
WARNING: Use sudo for system-mode:
WARNING: $ sudo gitlab-runner...
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
http://gitlab.cn/ci # gitlab 地址
Please enter the gitlab-ci token for this runner:
xxxxxxxxxxxxxxxx # Token
Please enter the gitlab-ci description for this runner:
[code]: demo # 描述
Please enter the gitlab-ci tags for this runner (comma separated):
Registering runner... succeeded runner=arvrsApX
Please enter the executor: ssh, docker-ssh+machine, kubernetes, docker, docker-ssh, parallels, shell, virtualbox, docker+machine:
shell # 选择那种执行器, 我这里选的是shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
这时注册就完成了
# 查看已注册的runner
> ./gitlab-ci-multi-runner-linux-386 list
Listing configured runners ConfigFile=/home/git/.gitlab-runner/config.toml
demo Executor=shell Token=2ba6335XXXXXXXXXXXXXX5ee603d6 URL=http://gitlab.com/ci
# 启动runner
> ./gitlab-ci-multi-runner-linux-386 run >> ~/gitlab-runner/access.log 2>&1 &
在git项目里添加.gitlab-ci.yml
job1:
stage: build
script:
- sh /home/git/jenkins_tools.sh
only:
- master
这时可以尝试提交了,出现下图就标示成功了。
Trouble Shooting
问题1,报错500
出现无法clone,并且日志报错:
gitlab JWT::DecodeError (Nil JSON web token)
修改Nginx配置
upstream gitlab-workhorse {
server unix:/var/opt/gitlab/gitlab-workhorse/socket;
}
...
proxy_pass http://gitlab-workhorse;
...
问题2,报错403
无法clone,报错如下:
把Gitlab管理员账户添加到项目里即可。
问题3,一直pending
在代码提交后任务一直处于pending状态,最后失败,报错超时,需要在服务器上启动Gitlab Runner,命令如下
>./gitlab-ci-multi-runner-linux-386 run >> ~/gitlab-runner/access.log 2>&1 &
总结
基于Gitlab+Jenkins的简单CICD就完成了,实现了简单的发布流程,毕竟条条大路通罗马,选择适合自己的方式。