GitLab CI 打造一條自己的流水線
大廠技術(shù)??堅持周更??精選好文
前言
最近接手的業(yè)務(wù)需求由于歷史原因,項目部署在阿里云服務(wù)器上,所以沒有使用公司內(nèi)部的流水線進行集成和部署。其中流水線使用到了GitLab自帶的CI工具進行集成,所以正好借此機會給大家分享一下GitLab CI/CD,教大家如何打造一條項目的流水線。
CI/CD的背景
正式介紹之前我們先簡單過一下CI/CD的背景
CI/CD是什么
https://www.redhat.com/zh/topics/devops/what-is-CI-CD
CI (Continuous Integration)
即持續(xù)集成,它是指頻繁地(一天多次)將代碼集成到主干,目的就為了讓產(chǎn)品保證質(zhì)量的同時快速迭代;通常它需要通過自動化測試,從而保證集成的代碼的穩(wěn)定性;
CD (Continuous Delivery/Deployment)
即持續(xù)交付/部署,可以看作持續(xù)集成的下一步,它指的是頻繁地將軟件的新版本,交付給質(zhì)量團隊or用戶測試。如果測試通過,代碼就可以部署到生產(chǎn)環(huán)境中。
為什么需要CI/CD?
過去,一個團隊的開發(fā)人員可能會孤立地工作很長一段時間,只有在他們的工作完成后,才會將他們的更改合并到主分支中。這使得合并代碼更改變得困難而耗時,而且還會導(dǎo)致錯誤積累很長時間而得不到糾正。這些因素導(dǎo)致更加難以迅速向客戶交付更新。
而有了 CI/CD,我們可以獲得以下收益:
解放了重復(fù)性勞動。自動化部署工作可以解放集成、測試、部署等重復(fù)性勞動,而機器集成的頻率明顯比手工高很多。
更快地修復(fù)問題。持續(xù)集成更早的獲取變更,更早的進入測試,更早的發(fā)現(xiàn)問題,解決問題的成本顯著下降。
更快的交付成果。更早發(fā)現(xiàn)錯誤減少解決錯誤所需的工作量。集成服務(wù)器在構(gòu)建環(huán)節(jié)發(fā)現(xiàn)錯誤可以及時通知開發(fā)人員修復(fù)。集成服務(wù)器在部署環(huán)節(jié)發(fā)現(xiàn)錯誤可以回退到上一版本,服務(wù)器始終有一個可用的版本。
減少手工的錯誤。在重復(fù)性動作上,人容易犯錯,而機器犯錯的幾率幾乎為零。
減少了等待時間。縮短了從開發(fā)、集成、測試、部署各個環(huán)節(jié)的時間,從而也就縮短了中間可以出現(xiàn)的等待時機。持續(xù)集成,意味著開發(fā)、集成、測試、部署也得以持續(xù)。 更高的產(chǎn)品質(zhì)量。集成服務(wù)器往往提供代碼質(zhì)量檢測等功能,對不規(guī)范或有錯誤的地方會進行標志,也可以設(shè)置郵件和短信等進行警告。
GitLab CI/CD
GitLab-CI 是GitLab提供的CI工具。它可以通過指定通過如push/merge代碼、打tag等行為觸發(fā)CI流程;同時也可以指定不同場景要觸發(fā)的不同的構(gòu)建腳本(腳本可以看作是流水線中的一個操作步驟or單個任務(wù))

具體的使用方式是在項目根目錄中配置一個 .gitlab-ci.yml 文件來啟動其功能;我們先了解一下這個 .gitlab-ci.yml 文件
配置文件介紹
gitlab-ci.yml 用的是?YAML語法[1]?,我們可以把它理解類似 json 的格式,只不過語法方面有一些不同。比如:
?tabitha:
????name:?Tabitha?Bitumen
????job:?Developer
?????skills:
??????-?lisp
??????-?fortran
??????-?erlang
對應(yīng)到j(luò)son:
{
?????tabitha?:?{
?????????name?:??Tabitha?Bitumen?,
?????????job?:??Developer?,
???????? skills :?[ lisp , fortran , erlang ],
????}
}
即:縮進對應(yīng)的是json對象中的key,-?對應(yīng)的是數(shù)組中的一項,還是比較好理解的~
正式介紹 .gitlab-ci.yml 配置文件之前,我們要提一下 GitLab CI中的幾個相關(guān)概念
Job
Job[2]?可以理解為CI流程中的單個任務(wù)。
job是一個頂級元素(相當于yml配置的一個根元素),它可以起任意的名稱、并且不限數(shù)量,但必須至少包含 script 子句,用于指定當前任務(wù)要執(zhí)行的腳本,如:
job1:
??script:??execute-script-for-job1?
job2:
??stage:?build
??script:
????-?scripts/build.sh
??only:
????-?master
#?job?n...
Stages
Stages 用來定義一次CI有哪幾個階段,如下
stages:
??-?build
??-?test
??-?deploy
同時每個stage又可以與若干個job關(guān)聯(lián),即一個階段可以并行執(zhí)行多個job;如下,在每個job中使用stage關(guān)鍵字關(guān)聯(lián)到對應(yīng)stage即可:
stages:
??-?build
??-?test
??-?deploy
??
build_job:
??stage:?build
??script:
????-?scripts/build.sh
test_job:
??stage:?test
??script:
????-?scripts/test.sh
deploy_job:
??stage:?deploy
??script:
????-?scripts/deploy.sh
Pipeline
Pipeline[3]?是持續(xù)集成、交付和部署的頂級組件,它可以理解為是流水線的一次完整的任務(wù)流程;
Pipeline 可以包含若干Stage,而每個Stage又可以指定執(zhí)行若干job,這樣我們就可以把整個構(gòu)建的流程串起來了。如下,我們就可以在GitLab 的pipeline中看到這些Stages,及其對應(yīng)的job:

如果Pipeline中的一個任務(wù)成功,將進入其下一個Stage的Job;反之如果中途失敗,則默認會中斷流水線的執(zhí)行。
常用配置
接下來重點介紹一下?.gitlab-ci.yml配置[4]?的常用關(guān)鍵字:
stage
上述有提到過,用?stage?可以定義 job 在哪個階段運行:
stages:
??-?build
??-?test
??-?deploy
script
用于指定運行器要執(zhí)行的腳本命令,可以指定多條
job:
??script:?
??????-?echo??start?job!?
??????-?scripts/deploy.sh
before_script & after_script
用于定義應(yīng)在job 在執(zhí)行腳本之前/后時要執(zhí)行的內(nèi)容:
job:
??before_script:
????-?echo??Execute?this?command?before?the?`script`?section?completes.?
??script:
????-?echo??An?example?script?section.?
??after_script:
????-?echo??Execute?this?command?after?the?`script`?section?completes.?
allow_failure
用于配置當前 job 失敗時 pipeline 是否應(yīng)繼續(xù)運行:
job2:
??stage:?test
??script:
????-?execute_script_2
??allow_failure:?true?#?or?false?(default)
cache
指定緩存的文件列表,用戶在不同的 job 之間共享;
cache:key:可以給每個緩存一個唯一的標識鍵,如果未設(shè)置,則默認鍵為default;
cache:paths:指定要緩存的文件或目錄
rspec:
??script:
????-?echo??This?job?uses?a?cache.?
??cache:
????key:?binaries-cache
????paths:
??????-?binaries/*.apk
??????-?.config
only?/?except
only 用于定義何時執(zhí)行job,反之 except 用于定義何時不執(zhí)行job;
它們有四個關(guān)鍵字可以一起配合使用:
ref:匹配 分支名稱 或 分支名匹配的的正則;
variables:變量表達式;
changes:對應(yīng)路徑的文件是否修改;
job1:
??script:?echo
??only:?#?or?except
????-?main?#?ref可省略
????ref:
??????-?tags
??????-?/^feat-.*$/
??????-?merge_requests
????variables:
??????-?$RELEASE?==??staging?
??????-?$STAGING
????changes:
??????-?Dockerfile
??????-?docker/scripts/*
??????-?dockerfiles/**/*
??????-?more_scripts/*.{rb,py,sh}
??????-??**/*.json?
retry
設(shè)置在 job 執(zhí)行失敗時候重試次數(shù):
job:
??script:?rspec
??retry:
????max:?2
????when:?#?搭配when關(guān)鍵字,在下列情況下重試
??????-?runner_system_failure
??????-?stuck_or_timeout_failure
variables
可用于定義執(zhí)行過程中的一些變量
variables:
??DEPLOY_SITE:??https://example.com/?
deploy_job:
??stage:?deploy
??script:
????-?deploy-script?--url?$DEPLOY_SITE?--path??/?
deploy_review_job:
??stage:?deploy
??variables:
????REVIEW_PATH:??/review?
??script:
????-?deploy-review-script?--url?$DEPLOY_SITE?--path?$REVIEW_PATH
when
用于配置 job 運行的條件:
on_success(默認):僅在之前stage的所有job都成功或配置了allow_failure: true;
manual:僅在手動觸發(fā)時運行 job;
always:無論之前stage的job狀態(tài)如何,都運行;
on_failure:僅當至少一個之前stage的job失敗時才運行;
delayed:延遲執(zhí)行job;
never: 永不執(zhí)行 job;
cleanup_build_job:
??stage:?cleanup_build
??script:
????-?cleanup?build?when?failed
??when:?on_failure
tags
選擇特定tag的GitLab-runner來執(zhí)行
job:
??tags:
????-?ruby
????-?postgres
GitLab-runner 安裝&注冊
配置好我們的 yml 文件之后,還需要配置GitLab-runner,用于執(zhí)行對應(yīng)的腳本。
安裝[5]:
#?下載
#?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.html
curl?-LJO??https://GitLab-runner-downloads.s3.amazonaws.com/latest/rpm/GitLab-runner_${arch}.rpm?
#?安裝
rpm?-i?GitLab-runner_.rpm
注冊[6]:
注冊時需要的 URL & token可以在 GitLab -> Settings -> CI/CD -> Runners 中獲取
sudo?GitLab-runner?register
#?Enter?the?GitLab?instance?URL?(for?example,?https://GitLab.com/):
${url}
#?Enter?the?registration?token:
${token}
#?Enter?a?description?for?the?runner:
${description}
#?Enter?tags?for?the?runner?(comma-separated):
${tags}
#?Registering?runner...?succeeded?
#?Enter?an?executor:?shell,?virtualbox,?docker+machine,?docker-ssh+machine,?docker,?docker-ssh,?parallels,?custom,?ssh,?kubernetes:
${executor}
#?Runner?registered?successfully.?Feel?free?to?start?it,?but?if?it's?running?already?the?config?should?be?automatically?reloaded!
打造一條流水線
預(yù)覽Pipeline
當有了以上的準備,我們配置好 .gitlab-ci.yml 文件、寫好對應(yīng)的腳本,同時配置好 GitLab-runner 后,就可以開啟并體驗 CI 流水線了。當提交代碼后(當然也可以按上述的only關(guān)鍵字設(shè)置為打tag、提mr時觸發(fā)),就可以觸發(fā)GitLab CI的Pipeline,并執(zhí)行對應(yīng)的stages及其jobs啦 ??
如下圖,我們可以在 GitLab -> CI/CD -> Pipeline 中看到:

配置一條流水線
規(guī)劃實現(xiàn)如下:
代碼編譯:提供一個build.sh腳本,用于編譯代碼;
自動化測試:scripts 關(guān)鍵字執(zhí)行測試的指令,從而運行事先編寫好的自動化測試腳本;
人工卡點:利用上述提到的 when:manual人工觸發(fā),配合allow_failure: false,即可達到卡點效果;
項目部署:也是利用一個腳本,將我們之前的構(gòu)建產(chǎn)物發(fā)送到目標機器、目錄下進行部署;同時使用 only:master指定只有在提交到master分支才執(zhí)行該步驟的 job。
綜合以上,我們可以得到以下大致的 .gitlab-ci.yml 配置(job 對應(yīng)的 script 可根據(jù)實際情況和需要編寫):
stages:
??-?scm
??-?test
??-?manual-point
??-?deploy
scm:
??stage:?scm
??script:
????-?scripts/build.sh
test:
??stage:?test
??script:
????-?scripts/test.sh
manual-point:
??stage:?manual-point
??script:
????-?echo??I?am?manual?job?
??only:
????-?master
??when:?manual
??allow_failure:?false
deploy:
??stage:?deploy
??script:
????-?scripts/deploy.sh
??only:
????-?master
觸發(fā)pipeline后,我們可以看到,經(jīng)過了scm編譯、test自動化測試的步驟后,到了Manual-point卡點,此時流水線已經(jīng)鎖定執(zhí)行,需要人工手動點擊確認才可以繼續(xù)執(zhí)行;

當點擊執(zhí)行 job 后

定時任務(wù)
有些場景我們想定時地執(zhí)行Pipeline,而不是通過事件觸發(fā),可以在GitLab -> Setting -> Schedule 進行設(shè)置

間隔的設(shè)置采用的是?cron 語法[7],它是Unix和類Unix系統(tǒng)中設(shè)置定時任務(wù)的語法;
它使用5個占位符分別代表 分鐘、小時、月份的日期、月份、周幾;如下:
#?┌───────────?minute?(0?-?59)
#?│?┌───────────?hour?(0?-?23)
#?│?│?┌───────────?day?of?the?month?(1?-?31)
#?│?│?│?┌───────────?month?(1?-?12)
#?│?│?│?│?┌───────────?day?of?the?week?(0?-?6)?(Sunday?to?Saturday;
#?│?│?│?│?│?????????????????????????????????7?is?also?Sunday?on?some?systems)
#?│?│?│?│?│
#?│?│?│?│?│
#?*?*??*??*??*?
#?例子:
*?*?*?*?*?#?每分鐘執(zhí)行
30?10?*?*?*?#?每天10:30
30?10?*?*?SAT,SUN?#?每周六、周天10:30
0?8?1-20?*?*?#?每個月的1-20號的8點
設(shè)置好后即可看到定時任務(wù)列表:

參考資料
YAML語法:?https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
[2]Job:?https://docs.gitlab.com/ee/ci/jobs/
[3]Pipeline:?https://docs.gitlab.com/ee/ci/pipelines/
[4].gitlab-ci.yml配置:?https://docs.gitlab.com/ee/ci/yaml/
[5]安裝:?https://docs.gitlab.com/runner/install/linux-manually.html
[6]注冊:?https://docs.gitlab.com/runner/register/index.html#linux
[7]cron 語法:?https://en.wikipedia.org/wiki/Cron
???H5-Dooring,讓H5制作更簡單
???謝謝支持
以上便是本次分享的全部內(nèi)容,希望對你有所幫助^_^
喜歡的話別忘了?分享、點贊、收藏?三連哦~。

