一、持續(xù)集成(Continuous Integration)
要了解GitLab-CI與GitLab Runner,我們得先了解持續(xù)集成是什么。
持續(xù)集成是一種軟件開(kāi)發(fā)實(shí)踐,即團(tuán)隊(duì)開(kāi)發(fā)成員經(jīng)常集成他們的工作,通常每個(gè)成員每天至少集成一次,也就意味著每天可能會(huì)發(fā)生多次集成。每次集成都通過(guò)自動(dòng)化的構(gòu)建(包括編譯,發(fā)布,自動(dòng)化測(cè)試)來(lái)驗(yàn)證,從而盡快地發(fā)現(xiàn)集成錯(cuò)誤。許多團(tuán)隊(duì)發(fā)現(xiàn)這個(gè)過(guò)程可以大大減少集成的問(wèn)題,讓團(tuán)隊(duì)能夠更快的開(kāi)發(fā)內(nèi)聚的軟件。
看完這段話,估計(jì)還是有點(diǎn)懵。怎么理解呢?我是這樣理解的:
軟件集成是軟件開(kāi)發(fā)過(guò)程中的一個(gè)環(huán)節(jié),這個(gè)環(huán)節(jié)的工作一般會(huì)包括以下流程:合并代碼---->安裝依賴---->編譯---->測(cè)試---->發(fā)布。軟件集成的工作一般會(huì)比較細(xì)碎繁瑣,為了不影響開(kāi)發(fā)效率,以前軟件集成這個(gè)環(huán)節(jié)一般不會(huì)經(jīng)常進(jìn)行或者只會(huì)等到項(xiàng)目后期再進(jìn)行。但是有些問(wèn)題,如果等到后期才發(fā)現(xiàn),解決問(wèn)題的代價(jià)很大,有可能導(dǎo)致項(xiàng)目延期或者失敗。因此,為了盡早發(fā)現(xiàn)軟件集成錯(cuò)誤,鼓勵(lì)團(tuán)隊(duì)成員應(yīng)該經(jīng)常集成他們的工作,通常每個(gè)成員每天應(yīng)該至少集成一次。這就是所說(shuō)的持續(xù)集成。所以說(shuō),持續(xù)集成是一種軟件開(kāi)發(fā)實(shí)踐。
軟件集成的工作細(xì)碎繁瑣,以前是由人工完成的。但是現(xiàn)在鼓勵(lì)持續(xù)集成,那豈不是要累死人,還影響開(kāi)發(fā)效率。所以,應(yīng)該考慮將軟件集成這個(gè)工作自動(dòng)化,這就出現(xiàn)了所謂的持續(xù)集成系統(tǒng)。
持續(xù)集成詳情見(jiàn)百度百科-持續(xù)集成
二、GitLab-CI
GitLab-CI就是一套配合GitLab使用的持續(xù)集成系統(tǒng)(當(dāng)然,還有其它的持續(xù)集成系統(tǒng),同樣可以配合GitLab使用,比如Jenkins)。而且GitLab8.0以后的版本是默認(rèn)集成了GitLab-CI并且默認(rèn)啟用的。
三、GitLab-Runner
那GitLab-Runner又是什么東東呢?與GitLab-CI有什么關(guān)系呢?
GitLab-Runner是配合GitLab-CI進(jìn)行使用的。一般地,GitLab里面的每一個(gè)工程都會(huì)定義一個(gè)屬于這個(gè)工程的軟件集成腳本,用來(lái)自動(dòng)化地完成一些軟件集成工作。當(dāng)這個(gè)工程的倉(cāng)庫(kù)代碼發(fā)生變動(dòng)時(shí),比如有人push了代碼,GitLab就會(huì)將這個(gè)變動(dòng)通知GitLab-CI。這時(shí)GitLab-CI會(huì)找出與這個(gè)工程相關(guān)聯(lián)的Runner,并通知這些Runner把代碼更新到本地并執(zhí)行預(yù)定義好的執(zhí)行腳本。
所以,GitLab-Runner就是一個(gè)用來(lái)執(zhí)行軟件集成腳本的東西。你可以想象一下:Runner就像一個(gè)個(gè)的工人,而GitLab-CI就是這些工人的一個(gè)管理中心,所有工人都要在GitLab-CI里面登記注冊(cè),并且表明自己是為哪個(gè)工程服務(wù)的。當(dāng)相應(yīng)的工程發(fā)生變化時(shí),GitLab-CI就會(huì)通知相應(yīng)的工人執(zhí)行軟件集成腳本。如下圖所示:

Runner可以分布在不同的主機(jī)上,同一個(gè)主機(jī)上也可以有多個(gè)Runner。
Runner類型
GitLab-Runner可以分類兩種類型:Shared Runner(共享型)和Specific Runner(指定型)。
Shared Runner:這種Runner(工人)是所有工程都能夠用的。只有系統(tǒng)管理員能夠創(chuàng)建Shared Runner。
Specific Runner:這種Runner(工人)只能為指定的工程服務(wù)。擁有該工程訪問(wèn)權(quán)限的人都能夠?yàn)樵摴こ虅?chuàng)建Shared Runner。
四、GitLab-Runner的安裝與使用
我的操作系統(tǒng)是:Centos 7.0 64位
安裝gitlab-ci-multi-runner
- 添加yum源
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.rpm.sh | sudo bash
- 安裝
yum install gitlab-ci-multi-runner
這里是官網(wǎng)的安裝教程,其它操作系統(tǒng)的請(qǐng)參考
https://gitlab.com/gitlab-org/gitlab-ci-multi-runner
使用gitlab-ci-multi-runner注冊(cè)Runner
安裝好gitlab-ci-multi-runner這個(gè)軟件之后,我們就可以用它向GitLab-CI注冊(cè)Runner了。
向GitLab-CI注冊(cè)一個(gè)Runner需要兩樣?xùn)|西:GitLab-CI的url和注冊(cè)token。
其中,token是為了確定你這個(gè)Runner是所有工程都能夠使用的Shared Runner還是具體某一個(gè)工程才能使用的Specific Runner。
如果要注冊(cè)Shared Runner,你需要到管理界面的Runners頁(yè)面里面去找注冊(cè)token。如下圖所示:

如果要注冊(cè)Specific Runner,你需要到項(xiàng)目的設(shè)置的Runner頁(yè)面里面去找注冊(cè)token。如下圖所示:

找到token之后,運(yùn)行下面這條命令注冊(cè)Runner(當(dāng)然,除了url和token之外,還需要其他的信息,比如執(zhí)行器executor、構(gòu)建目錄builds_dir等)。
gitlab-ci-multi-runner register
注冊(cè)完成之后,GitLab-CI就會(huì)多出一條Runner記錄,如下圖所示:

GitLab-CI會(huì)為這個(gè)Runner生成一個(gè)唯一的token,以后Runner就通過(guò)這個(gè)token與GitLab-CI進(jìn)行通信。
那么,問(wèn)題來(lái)了。注冊(cè)好了的Runner的信息存放在哪兒了呢?
原來(lái),Runner的信息是存放在一個(gè)配置文件里面的,配置文件的格式一般是.toml。這個(gè)配置文件的存放位置有以下幾種情況:
- 在類Unix操作系統(tǒng)下(0.5.0之后版本)
- 如果是以root用戶身份運(yùn)行
gitlab-ci-multi-runner register,那么配置文件默認(rèn)是/etc/gitlab-runner/config.toml - 如果是以非root用戶身份運(yùn)行
gitlab-ci-multi-runner register,那么配置文件默認(rèn)是~/.gitlab-runner/config.toml
- 在其他操作系統(tǒng)下以及0.5.0之前版本
配置文件默認(rèn)在當(dāng)前工作目錄下./config.toml
一般情況下,使用默認(rèn)的配置文件存放Runner的配置信息就可以了。當(dāng)然,如果你有更細(xì)化的分類需求,你也可以在注冊(cè)的時(shí)候通過(guò)-c或--config選項(xiàng)指定配置文件的位置。具體查看register命令的使用方法:gitlab-ci-multi-runner register --help。
問(wèn)題:如果不運(yùn)行gitlab-ci-multi-runner register命令,直接在配置文件里面添加Runner的配置信息可以嗎?
回答:當(dāng)然不可以。因?yàn)?code>gitlab-ci-multi-runner register的作用除了把Runner的信息保存到配置文件以外,還有一個(gè)很重要的作用,那就是向GitLab-CI發(fā)出請(qǐng)求,在GitLab-CI中登記這個(gè)Runner的信息并且獲取后續(xù)通信所需要的token。
讓注冊(cè)好的Runner運(yùn)行起來(lái)
Runner注冊(cè)完成之后還不行,還必須讓它運(yùn)行起來(lái),否則它無(wú)法接收到GitLab-CI的通知并且執(zhí)行軟件集成腳本。怎么讓Runner運(yùn)行起來(lái)呢?gitlab-ci-multi-runner提供了這樣一條命令gitlab-ci-multi-runner run-single,詳情如下:
[root@iZ25bjcxoq5Z ~]# gitlab-ci-multi-runner run-single --help
NAME:
run-single - start single runner
USAGE:
command run-single [command options] [arguments...]
OPTIONS:
--name, --description Runner name [$RUNNER_NAME]
--limit Maximum number of builds processed by this runner [$RUNNER_LIMIT]
--ouput-limit Maximum build trace size [$RUNNER_OUTPUT_LIMIT]
-u, --url Runner URL [$CI_SERVER_URL]
-t, --token Runner token [$CI_SERVER_TOKEN]
--tls-ca-file File containing the certificates to verify the peer when using HTTPS [$CI_SERVER_TLS_CA_FILE]
--executor Select executor, eg. shell, docker, etc. [$RUNNER_EXECUTOR]
--builds-dir Directory where builds are stored [$RUNNER_BUILDS_DIR]
--cache-dir Directory where build cache is stored [$RUNNER_CACHE_DIR]
--env Custom environment variables injected to build environment [$RUNNER_ENV]
--shell Select bash, cmd or powershell [$RUNNER_SHELL]
--ssh-user User name [$SSH_USER]
--ssh-password User password [$SSH_PASSWORD]
--ssh-host Remote host [$SSH_HOST]
--ssh-port Remote host port [$SSH_PORT]
--ssh-identity-file Identity file to be used [$SSH_IDENTITY_FILE]
--docker-host Docker daemon address [$DOCKER_HOST]
--docker-cert-path Certificate path [$DOCKER_CERT_PATH]
--docker-tlsverify Use TLS and verify the remote [$DOCKER_TLS_VERIFY]
--docker-hostname Custom container hostname [$DOCKER_HOSTNAME]
--docker-image Docker image to be used [$DOCKER_IMAGE]
--docker-privileged Give extended privileges to container [$DOCKER_PRIVILEGED]
--docker-disable-cache Disable all container caching [$DOCKER_DISABLE_CACHE]
--docker-volumes Bind mount a volumes [$DOCKER_VOLUMES]
--docker-cache-dir Directory where to store caches [$DOCKER_CACHE_DIR]
--docker-extra-hosts Add a custom host-to-IP mapping [$DOCKER_EXTRA_HOSTS]
--docker-links Add link to another container [$DOCKER_LINKS]
--docker-services Add service that is started with container [$DOCKER_SERVICES]
--docker-wait-for-services-timeout How long to wait for service startup [$DOCKER_WAIT_FOR_SERVICES_TIMEOUT]
--docker-allowed-images Whitelist allowed images [$DOCKER_ALLOWED_IMAGES]
--docker-allowed-services Whitelist allowed services [$DOCKER_ALLOWED_SERVICES]
--docker-image-ttl [$DOCKER_IMAGE_TTL]
--parallels-base-name VM name to be used [$PARALLELS_BASE_NAME]
--parallels-template-name VM template to be created [$PARALLELS_TEMPLATE_NAME]
--parallels-disable-snapshots Disable snapshoting to speedup VM creation [$PARALLELS_DISABLE_SNAPSHOTS]
--virtualbox-base-name VM name to be used [$VIRTUALBOX_BASE_NAME]
--virtualbox-disable-snapshots Disable snapshoting to speedup VM creation [$VIRTUALBOX_DISABLE_SNAPSHOTS]
要讓一個(gè)Runner運(yùn)行起來(lái),--url、--token和--executor選項(xiàng)是必要的。其他選項(xiàng)可根據(jù)具體情況和需求進(jìn)行設(shè)置。我們可以看出來(lái),這個(gè)命令里面的選項(xiàng)跟配置文件中Runner的配置項(xiàng)基本上是一樣的。那這個(gè)命令的運(yùn)行和配置文件有沒(méi)有什么關(guān)系呢?從我的試驗(yàn)和思考來(lái)看,應(yīng)該是沒(méi)有什么關(guān)系的。因?yàn)椋?/p>
- 這個(gè)命令里面并沒(méi)有指定配置文件位置的選項(xiàng),如果讀取配置文件難道去讀取默認(rèn)位置嗎?但是配置文件的位置是可以指定的,不一定在默認(rèn)位置,這不符合邏輯,所以它應(yīng)該不會(huì)去讀配置文件。
- 我刪掉配置文件,這個(gè)命令依然能夠運(yùn)行
所以,這個(gè)命令應(yīng)該只是一個(gè)能讓Runner運(yùn)行起來(lái)的基礎(chǔ)命令。但這個(gè)命令運(yùn)行起來(lái)的前提是,GitLab-CI中必須事先注冊(cè)有這個(gè)Runner。
那配置文件有毛用?配置文件的作用在后面,但是從這里我們知道一點(diǎn):配置文件里面有Runner運(yùn)行時(shí)所需要的信息。
可能你還有一個(gè)問(wèn)題:我用root的用戶注冊(cè)Runner時(shí),注冊(cè)完Runner就可以用了,并沒(méi)有手動(dòng)地去運(yùn)行Runner啊?這個(gè)后面講。
批量地運(yùn)行Runner
正常情況下,如果我有多個(gè)Runner,我并不想手動(dòng)一個(gè)個(gè)地運(yùn)行,要是能一次運(yùn)行多個(gè)Runner多爽??!嗯哼,gitlab-ci-multi-runner就提供了這樣一個(gè)命令gitlab-ci-multi-runner run,詳情如下:
[root@iZ25bjcxoq5Z gitlab-runner]# gitlab-ci-multi-runner run --help
NAME:
run - run multi runner service
USAGE:
command run [command options] [arguments...]
OPTIONS:
-c, --config "/etc/gitlab-runner/config.toml" Config file [$CONFIG_FILE]
-n, --service "gitlab-runner" Use different names for different services
-d, --working-directory Specify custom working directory
-u, --user Use specific user to execute shell scripts
--syslog Log to syslog
這個(gè)命令總共有5個(gè)選項(xiàng),讓我們從選項(xiàng)來(lái)理解一下這個(gè)命令:
-
-c, --config選項(xiàng)
這個(gè)選項(xiàng)是用來(lái)指定配置文件路徑的。如果你想同時(shí)運(yùn)行多個(gè)Runner,你必須得知道你要運(yùn)行哪些Runner以及這些Runner運(yùn)行時(shí)所需要的信息。而前面我們說(shuō)過(guò),配置文件里面就存放著Runner運(yùn)行時(shí)所需要的信息。而且一個(gè)配置文件是可以存放多個(gè)Runner的信息的。如果不指定這個(gè)選項(xiàng),就會(huì)使用默認(rèn)的配置文件。 -
-n, --service選項(xiàng)
這個(gè)選項(xiàng)是用來(lái)指定服務(wù)的別名的。為什么要有這個(gè)選項(xiàng)呢?指定別名有什么意義呢?我們從上一個(gè)選項(xiàng)可以看出來(lái),一次只能運(yùn)行一批Runner,因?yàn)橐淮沃荒苤付ㄒ粋€(gè)配置文件。那如果我有多個(gè)配置文件,我要運(yùn)行多批Runner,那是不是給每一次批量運(yùn)行服務(wù)取不同的別名來(lái)區(qū)分更好一點(diǎn)呢。 -
-d, --working-directory選項(xiàng)
這個(gè)選項(xiàng)是用來(lái)指定此次批量運(yùn)行服務(wù)的工作目錄的。如果自己沒(méi)有指定builds_dir的話,此次運(yùn)行起來(lái)的Runner會(huì)把builds_dir放到這個(gè)目錄里面。 -
-u, --user選項(xiàng)
這個(gè)選項(xiàng)很重要,它指定了該以什么用戶權(quán)限來(lái)運(yùn)行Runner。為了安全,我認(rèn)為不應(yīng)該給運(yùn)行Runner的用戶過(guò)高的權(quán)限,更不應(yīng)該以root用戶來(lái)運(yùn)行Runner。 -
--syslog選項(xiàng)
如果指定了這個(gè)選項(xiàng),則把日志記錄到系統(tǒng)日志。
使用服務(wù)
能夠批量地運(yùn)行Runner已經(jīng)很好了,但是還不夠好,為什么呢?
首先,gitlab-ci-multi-runner run默認(rèn)是前臺(tái)運(yùn)行的,使用體驗(yàn)不好;
其次,當(dāng)gitlab-ci-multi-runner run在后臺(tái)運(yùn)行的時(shí)候,要查看其運(yùn)行狀態(tài)不方便,而且也沒(méi)有提供停止gitlab-ci-multi-runner run的命令。
所以,要是能將批量運(yùn)行Runner這個(gè)功能安裝為一項(xiàng)服務(wù),就更爽了!
gitlab-ci-multi-runner確實(shí)就提供了這樣的功能。
install、uninstall、start、stop、restart、status這6個(gè)命令就是和服務(wù)相關(guān)的。
我一開(kāi)始對(duì)gitlab-ci-multi-runner的服務(wù)概念感覺(jué)比較懵,讓我們來(lái)看看安裝服務(wù)install這個(gè)命令到底干了一件什么事情。
[root@iZ25bjcxoq5Z ~]# gitlab-ci-multi-runner install --help
NAME:
install - install service
USAGE:
command install [command options] [arguments...]
OPTIONS:
--service, -n "gitlab-runner" Specify service name to use
--working-directory, -d "/root" Specify custom root directory where all data are stored
--config, -c "/etc/gitlab-runner/config.toml" Specify custom config file
--user, -u Specify user-name to secure the runner
從選項(xiàng)可以看出,一項(xiàng)服務(wù)的信息有4個(gè):服務(wù)名、工作目錄、配置文件和用戶。這個(gè)命令的選項(xiàng)和gitlab-ci-multi-runner run的選項(xiàng)基本一樣??梢?jiàn),批量運(yùn)行Runner和服務(wù)之間的關(guān)系曖昧。至于是什么關(guān)系,往下看gitlab-ci-multi-runner start這個(gè)命令。
[root@iZ25bjcxoq5Z ~]# gitlab-ci-multi-runner start --help
NAME:
start - start service
USAGE:
command start [command options] [arguments...]
OPTIONS:
--service, -n "gitlab-runner" Specify service name to use
啟動(dòng)一項(xiàng)服務(wù),只要指定服務(wù)的名稱就行了(默認(rèn)服務(wù)名稱是gitlab-runner)。啟動(dòng)服務(wù)后,運(yùn)行命令ps -aux | grep gitlab-runner查看后臺(tái)程序,發(fā)現(xiàn)啟動(dòng)服務(wù)其實(shí)就是在后臺(tái)執(zhí)行了一個(gè)批量運(yùn)行Runner的任務(wù),所以服務(wù)安裝命令的選項(xiàng)才會(huì)和批量運(yùn)行Runner命令的選項(xiàng)基本一樣。
root 18219 0.0 0.1 331872 5332 ? Ssl 00:06 0:00 /usr/bin/gitlab-ci-multi-runner run --working-directory /home/gitlab-runner --config /etc/gitlab-runner/config.toml --service gitlab-runner --user gitlab-runner --syslog
還有stop命令用于停止服務(wù),restart命令用于重啟服務(wù),status用于查看服務(wù)狀態(tài)。這三個(gè)命令的使用方法和start類似,就不一一介紹了。
五、其他一些思考
什么情況下需要注冊(cè)Shared Runner?
比如,GitLab上面所有的工程都有可能需要在公司的服務(wù)器上進(jìn)行編譯、測(cè)試、部署等工作,這個(gè)時(shí)候注冊(cè)一個(gè)Shared Runner供所有工程使用就很合適。什么情況下需要注冊(cè)Specific Runner?
比如,我可能需要在我個(gè)人的電腦或者服務(wù)器上自動(dòng)構(gòu)建我參與的某個(gè)工程,這個(gè)時(shí)候注冊(cè)一個(gè)Specific Runner就很合適。什么情況下需要在同一臺(tái)機(jī)器上注冊(cè)多個(gè)Runner?
比如,我是GitLab的普通用戶,沒(méi)有管理員權(quán)限,我同時(shí)參與多個(gè)項(xiàng)目,那我就需要為我的所有項(xiàng)目都注冊(cè)一個(gè)Specific Runner,這個(gè)時(shí)候就需要在同一臺(tái)機(jī)器上注冊(cè)多個(gè)Runner。
六、最后
啰啰嗦嗦寫(xiě)了一堆,大體上也算把自己對(duì)GitLab-Runner的理解過(guò)程寫(xiě)清楚了。為了把GitLab-Runner的用法了解清楚,自己做了很多的測(cè)試,但也難全面,中間有一些內(nèi)容也只是個(gè)人理解,未必準(zhǔn)確,歡迎批評(píng)指正。