导读: 网易云信的 gitlab 服务器搭建在外网,Jenkins 服务器搭建在内网,因而 gitlab 没方法间接把 webhook 发送给 Jenkins,而 pipeline 的搭建采纳第三方 relay 转发的形式,然而这个 relay 常常“罢工”。本文依据网易云信的落地实际,具体介绍了如何借助 Gitlab-ci 代替 webhook 触发 Jenkins job。
文|邹李勇 网易云信资深 C++ 开发 /DevOps 工程师
背景
Gitlab 如何触发 Jenkins job?
咱们 push 代码或提交 merge request 的时候,gitlab 会发送一个 webhook(单纯地了解成一个 http 申请或 restful api 即可)给 Jenkins,申请执行某个 job。
窘境
网易云信应用的 gitlab 服务由杭研保护,服务器搭建在外网。而咱们的 Jenkins 服务器搭建在内网,这意味着 gitlab 没方法间接把 webhook 发送给 Jenkins,而咱们的 pipeline 在搭建之初采纳了第三方 relay 转发的形式,把 gitlab 的 webhook 转发给 Jenkins。尽管把 webhook 从 gitlab 发送到 Jenkins 的目标达到了,然而这个收费的第三方 relay 可能常常“罢工”。
借助 Gitlab-ci 代替 webhook 触发 Jenkins job
gitlab-ci
简略来讲,gitlab-ci 是 gitlab 自带的个性,通过源码根目录下的 .gitlab-ci.yml 文件配置。在代码 push 或 merge request 的时候主动运行。
以下是官网的解释:
GitLab Auto DevOps is a collection of pre-configured features and integrations that work together to support your software delivery process.
GitLab CI/CD can automatically build, test, deploy, and monitor your applications by using Auto DevOps.
To use GitLab CI/CD, you need:
- Application code hosted in a Git repository.
- A file called .gitlab-ci.yml in the root of your repository, which contains the CI/CD configuration.
官网的 you need 中其实还少了一点 —— GitLab runner,运行 GitLab-ci job 的中央,也就是说 .gitlab-ci.yml 中定义的所有工作都会散发到这里。
在咱们这个实际中,咱们会在 GitLab runner 中搭建一套 python 环境和 python-jenkins 模块,而后通过 python 脚本触发 Jenkins job,最初把这个触发 Jenkins job 的 python 脚本部署到 gitlab-ci 中。
因而整个实际分成 3 个局部。
- 搭建 Gitlab runner
- 通过 python-jenkins 触发 Jenkins job
- 应用 gitlab-ci 在 push 代码和 merge request 时调用 python 脚本
搭建 gitlab runner
装置 gitlab runner 客户端
官网: GitLab Runner can be installed and used on GNU/Linux, macOS, FreeBSD, and Windows.
因而抉择任意一台长期在线的打包机即可。笔者举荐优先选择 GNU/Linux,通常 linux 上搭建常驻服务要比其余零碎更不便,MacOS 次之,最初是 Windows。
以下是 GNU/Linux 平台的装置办法的搬运:
-
Download
To download the appropriate package for your system:
- Find the latest file name and options athttps://gitlab-runner-downloa…
- Choose a version and download a binary, as described in the documentation for downloading any other tagged releases for bleeding edge GitLab Runner releases.
For example, for Debian or Ubuntu:
# Replace ${arch} with any of the supported architectures, e.g. amd64, arm, arm64# A full list of architectures can be found here https://gitlab-runner-downloads.s3.amazonaws.com/latest/index.htmlcurl -LJO "https://gitlab-runner-downloads.s3.amazonaws.com/latest/deb/gitlab-runner_${arch}.deb"
For example, for CentOS or Red Hat Enterprise Linux:
# Replace ${arch} with any of the supported architectures, e.g. amd64, arm, arm64# A full list of architectures can be found here https://gitlab-runner-downloads.s3.amazonaws.com/latest/index.htmlcurl -LJO "https://gitlab-runner-downloads.s3.amazonaws.com/latest/rpm/gitlab-runner_${arch}.rpm"
-
Install
- Install the package for your system as follows.
For example, for Debian or Ubuntu:
dpkg -i gitlab-runner_<arch>.deb
For example, for CentOS or Red Hat Enterprise Linux:
rpm -i gitlab-runner_<arch>.rpm
其余平台的装置计划请点击官网教程传送门:
https://docs.gitlab.com/runne…
通常作为一个 trigger 代理,工作开销很小,咱们能够把 /etc/gitlab-runner/config.toml 配置里的 concurrent 能够改得大一些,以反对更高的并发量。
注册 gitlab runner
-
留神
- 搭建 gitlab runner 每台 runner 只须要执行一次
- 注册 gitlab runner 每个 git 仓库每台 runner 都须要独自注册
<!—->
-
筹备工作
– 先登入 gitlab,进入对应的 git 仓库(project)
– 开展右边侧边栏最上面 Settings -> CI/CD。点击页面上 Runners 栏左边的 Expand,页面往下滚动一点可看到大略如下,留神红框中的内容。
-
注册
以官网 GNU/Linux 为例,其余平台高度雷同。
1. Run the following command:
sudo gitlab-runner register
2. Enter your GitLab instance URL.
上图红框中 Register the runner with this URL 上面的内容。
3. Enter the token you obtained to register the runner.
上图红框中 And this registration token 上面内容。
4. Enter a description for the runner. You can change this value later in the GitLab user interface.
在 gitlab 中显示的 runner 形容,该实际中咱们把他当名字用,叫 scapegoat-01。
5. Enter the tags associated with the runner, separated by commas. You can change this value later in the GitLab user interface.
tag 相当于 Jenkins 中的 label,用于 runner 分类。该实际中输出 scapegoat。
6. Provide the runner executor. For most use cases, enter docker.
这里咱们选 shell,window 可选 powershell。
其余平台命令雷同,官网传送门:
https://docs.gitlab.com/runne…。
注册胜利后可在红框上面 Available specific runners 里看到咱们刚刚注册的 runner,相似下图。其中:
- scapegoat-01 是 runner 的 description
- scapegoat 对应 runner 的 tag,tag 能够不只一个
通过 python-jenkins 触发 Jenkins job
环境装置
-
在 gitlab runn er 里装置 python
Linux 发行版中个别自带,Debian 系列能够应用以下命令,其余平台能够 Google 查看。
sudo apt install python 或 sudo apt install python3
-
装置 pip
python3 通常自带,python 须要本人装置。
sudo apt install python-pip
- 装置 python-jenkins
python -m pip install python-jenkinsor python3 -m pip install python-jenkins
-
获取 gitlab access token
登入 jenkins,点击菜单栏左边的用户图标。
在弹出的左侧边栏点击 Configure。
在 APT Token 栏点击 Add new token,输出 token 名,点击 Generate。
如下红框中的内容就是新生成的 token,在上面 python 脚本中要用。
编写 python 脚本
#!/usr/bin/python# file name: Jenkins-Compile-trigger.py
import jenkinsimport requestsimport timeimport sysimport os
jenkins_url = "http://yunxin-jenkins.netease.im:8080"# gitlab 的登录账号 jenkins_user = "zouliyong" #获取 gitlab access token 章节获取到的 tokenjenkins_token = "xxxxxxxxxxxxxxxxx" #Jenkins job namejob_name = "Lava-CI"# 从 gitlab-ci 中获取 Jenkins job 的参数,按需批改 job_parameters = {"_GitlabSourceBranch" : os.getenv("CI_MERGE_REQUEST_SOURCE_BRANCH_NAME"), "_GitlabTargetBranch" : os.getenv("CI_MERGE_REQUEST_TARGET_BRANCH_NAME"), "_GitlabMergeRequestLastCommit" : os.getenv("CI_COMMIT_SHA"), "_GitlabSourceRepoHomepage" : os.getenv("CI_PROJECT_URL"), "_GitlabMergeRequestIid" : os.getenv("CI_MERGE_REQUEST_IID"), "_GitlabPipelineId" : os.getenv("CI_PIPELINE_ID"), "_GitlabPipelineUrl" : os.getenv("CI_PIPELINE_URL"), "_GitlabJobId" : os.getenv("CI_JOB_ID"), "_GitlabUserName" : os.getenv("GITLAB_USER_NAME"), "_GitlabUserEmail" : os.getenv("GITLAB_USER_EMAIL")}
build_number = 0build_info = {"building" : False} print("jenkins job name:", job_name)print("jenkins job parameters:", job_parameters)
#连贯 Jenkins 服务 server = jenkins.Jenkins(jenkins_url, username= jenkins_user, password= jenkins_token)
#获取 Jenkins job 最初一次 build 的 build numberdef last_build_number(server, job): last_build = server.get_job_info(job)['lastBuild'] return 1 if None == last_build else last_build['number']
last_build = server.get_job_info(job_name)['lastBuild']next_build_number = last_build_number(server, job_name) + 1
#触发 Jenkinsjobqueue_id = server.build_job(job_name, parameters=job_parameters)print("Jenkins build is waiting for running [queue id = %d] ..." % queue_id)sys.stdout.flush()
#到这里,Jenkins job 曾经被放到执行队列里了,# 只是触发不必期待 Jenkins job 完结的话,python 脚本能够到此为止
#期待 Jenkins job 开始执行 while True: if next_build_number <= last_build_number(server, job_name): try: build_info = server.get_build_info(job_name, next_build_number) except requests.exceptions.RequestException as e: print(e) server = jenkins.Jenkins(jenkins_url, username= jenkins_user, password= jenkins_token) build_info = server.get_build_info(job_name, next_build_number) if queue_id == build_info["queueId"]: build_number = next_build_number print("build number: %d" % build_number) break next_build_number = next_build_number + 1 time.sleep(0.1)
print("Jenkins build is running [build number = %d] ..." % build_number)print("Jenkins job URL: %s/job/%s/%d/display/redirect" % (jenkins_url, job_name, build_number))sys.stdout.flush()
#到这里 Jenkins job 曾经被正式调度,并开始执行
#期待 Jenkins job 执行完结 while build_info["building"]: try: build_info = server.get_build_info(job_name, build_number) except requests.exceptions.RequestException as e: print(e) server = jenkins.Jenkins(jenkins_url, username= jenkins_user, password= jenkins_token) build_info = server.get_build_info(job_name, build_number) time.sleep(1)
# 获取执行后果 result = server.get_build_info(job_name, build_number)["result"]print("jenkins build result: %s" % result)assert("SUCCESS" == result)
运行如上脚本即可触发对应的 Jenkins job,
python Jenkins-Compile-trigger.py
应用 gitlab-ci 在 push 代码和 merge request 时调用 python 脚本 编写 .gitlab-ci.yml 文件。
#file name: .gitlab-ci.yml
stages: - build
# 在代码 push 的时候触发 Compilation: stage: build tags: - scapegoat # runner tag 参照下面注册 gitlab runner 章节 script: - python Jenkins-Compile-trigger.py
# 只在 merge request 的时候触发 CI: stage: build tags: - scapegoat script: # 这个脚本能够依据状况参照 Jenkins-Compile-trigger.py 自行批改 - python Jenkins-CI-trigger.py only: - merge_requests
把如上 .gitlab-ci.yml 和触发用 Jenkins job 的 python 一起放在源码根目录下,同代码一起上传仓库。通过 gitlab-ci 触发 Jenkins job 的性能就实现了。
作者介绍
邹李勇,网易云信资深 C++ 开发 /DevOps 工程师。Linux 平台 RTC SDK 开发,负责 DevOps 零碎开发和运维。