CICD是什么?
由于目前公司使用的gitlab,大部分項目使用的CICD是gitlab的CICD,少部分用的是jenkins,使用了gitlab-ci一段時間后感覺還不錯,因此總結(jié)一下
介紹gitlab的CICD之前,可以先了解CICD是什么
我們的開發(fā)模式經(jīng)歷了如下的轉(zhuǎn)變:瀑布模型->敏捷開發(fā)→DevOps(Development、Operations的組合詞,是一組過程、方法與系統(tǒng)的統(tǒng)稱)
后來隨著DevOps的興起,出現(xiàn)了持續(xù)集成(Continuous Integration)、持續(xù)交付(Continuous Delivery) 、持續(xù)部署(Continuous Deployment) 的新方法,關(guān)于持續(xù)集成、持續(xù)交付、持續(xù)部署,總結(jié)如下:
- 持續(xù)集成的重點是將各個開發(fā)人員的工作集合到一個代碼倉庫中。通常,每天都要進行幾次,主要目的是盡早發(fā)現(xiàn)集成錯誤,使團隊更加緊密結(jié)合,更好地協(xié)作。
- 持續(xù)交付的目的是最小化部署或釋放過程中固有的摩擦。它的實現(xiàn)通常能夠?qū)?gòu)建部署的每個步驟自動化,以便任何時刻能夠安全地完成代碼發(fā)布(理想情況下)。
- 持續(xù)部署是一種更高程度的自動化,無論何時對代碼進行重大更改,都會自動進行構(gòu)建/部署。
持續(xù)集成的好處是什么?
持續(xù)集成可以使問題盡早暴露,從而也降低了解決問題的難度,持續(xù)集成無法消除bug,但卻能大大降低修復的難度和時間。
持續(xù)交付的好處是什么?
持續(xù)交付的好處在于快速獲取用戶反饋;適應市場變化和商業(yè)策略的變化。開發(fā)團隊保證每次提交的修改都是可上線的修改,那么決定何時上線,上線哪部分功能則完全由產(chǎn)品業(yè)務團隊決定。
雖然持續(xù)交付有顯著的優(yōu)點,但也有不成立的時候,比如對于嵌入式系統(tǒng)的開發(fā),往往需要軟硬件的配合。
持續(xù)部署的好處是什么?
持續(xù)部署的目標是通過減少批量工作的大小,并加快團隊工作的節(jié)奏,幫助開發(fā)團隊在其開發(fā)流程中消除浪費。這使團隊能夠一直處于一種可持續(xù)的平穩(wěn)流狀態(tài), 讓團隊更容易去創(chuàng)新、試驗,并達到可持續(xù)的生產(chǎn)率
市面上的CI有很多,如果在github上搜一下ci工具,也會搜到很多,比如:
- Travis CI
- Circle CI
- Jenkins
- AppVeyor
- CodeShip
- Drone
- Semaphore CI
- Buildkite
- Wercker
- TeamCity
這里只介紹Gitlab-CI
Gitlab-CI
-
項目頁面:
Continuous Integration and Delivery | GitLab
-
源代碼:
GitLab.org / GitLab FOSS · GitLab
-
遵循 MIT 許可協(xié)議
GitLab 是 CI/CD 領域的一個新手玩家,但它已經(jīng)在 Forrester Wave 持續(xù)集成工具中占據(jù)了領先地位。在這樣一個競爭對手眾多而水平又很高的領域,這是一項巨大的成就。是什么讓 GitLab CI 如此了不起?
- 它使用 YAML 文件來描述整個管道。
- 它還有一個功能叫 Auto DevOps,使比較簡單的項目可以自動構(gòu)建內(nèi)置了若干測試的管道。
- 使用 Herokuish 構(gòu)建包來確定語言以及如何構(gòu)建應用程序。有些語言還可以管理數(shù)據(jù)庫,對于構(gòu)建新的應用程序并在開發(fā)過程一開始就將其部署到生產(chǎn)環(huán)境中,這是一個很重要的功能。
- 提供到 Kubernetes 集群的原生集成,并使用多種部署方法的一種(如基于百分比的部署和藍綠部署)將應用程序自動部署到 Kubernetes 集群中。
除了 CI 功能之外,GitLab 還提供了許多補充功能,比如自動把 Prometheus 和你的應用程序一起部署,實現(xiàn)運行監(jiān)控;使用 GitLab 問題(Issues)、史詩(Epics)和里程碑(Milestones)進行項目組合和項目管理;管道內(nèi)置了安全檢查,提供跨多個項目的聚合結(jié)果;使用 WebIDE 在 GitLab 中編輯代碼的能力,它甚至可以提供預覽或執(zhí)行管道的一部分,以獲得更快的反饋。
相關(guān)概念
pipeline(管道、流水線)
- 一次 Pipeline 其實相當于一次構(gòu)建任務,里面可以包含多個流程(
Stage
),比如自動構(gòu)建、自動進行單元測試、自動進行代碼檢查等流程 ; - 任何提交或者 Merge Request 的合并都可以觸發(fā) Pipeline ;
Stage(構(gòu)建階段)
- Stage表示構(gòu)建階段,就是上面提到的流程 ;
- 可以在一次?
Pipeline
中定義多個?Stage
; - Stage有如下特點 :
- 所有 stages 會按照順序運行,即當一個 stage 完成后,下一個 Stage才會開始
- 只有當所有 Stage 成功完成后,該構(gòu)建任務?
Pipeline
?才算成功 - 如果任何一個 Stage失敗,那么后面的 Stage 不會執(zhí)行,該構(gòu)建任務 (Pipeline) 失敗
階段是對批量的作業(yè)的一個邏輯上的劃分,每個?pipeline
都必須包含至少一個?Stage
。多個 Stage是按照順序執(zhí)行的,如果其中任何一個 Stage失敗,則后續(xù)的 Stage不會被執(zhí)行,整個 CI 過程被認為失敗。
Jobs(任務)
- job表示構(gòu)建工作,表示某個stage里面執(zhí)行的工作 ;
- 一個stage里面可以定義多個job ;
- jobs有如下特點 :
- 相同 stage 中的jobs 會并行執(zhí)行
- 相同 stage 中的 jobs 都執(zhí)行成功時,該 stage 才會成功
- 如果任何一個job 失敗,那么該 stage 失敗,即該構(gòu)建任務 (Pipeline) 失敗
舉一個例子,比如下面這個圖:
這里的四個Statge(階段):?Verify、Build、Dockerpush、Deploy
四個,這四個階段組成一條Pipeline
每個階段都有一個job,所以總共四個job,也就是unit-test
、java-package
、docker-push
、service-1
這四個,當然,每個stage可以由多個job組成,比如下面這個圖:
Job 的執(zhí)行過程中往往會產(chǎn)生一些數(shù)據(jù),默認情況下 GitLab Runner 會保存 Job 生成的這些數(shù)據(jù),然后在下一個 Job 執(zhí)行之前(甚至不局限于當次 CI/CD)將這些數(shù)據(jù)恢復。這樣即便是不同的 Job 運行在不同的 Runner 上,它也能看到彼此生成的數(shù)據(jù)。
.gitlab-ci.yml
中提供了 before_script 和 after_script 兩個全局配置項。這兩個配置項在所有 Job 的 script 執(zhí)行前和執(zhí)行后調(diào)用。
關(guān)于.gitlab-ci.yml、before_script、after_script是什么,先別急,在后面有介紹
在了解了 Job 配置的 script、before_script、after_script 和 cache 以后,可以將整個 Job 的執(zhí)行流程用一張圖概括:
所以了解了Pipeline、Stage、Jobs后,還有一個很重要的東西,就是Runner
Runner
Runner就像一個個的工人,而Gitlab-CI就是這些工人的一個管理中心,所有工人都要在Gitlab-CI里面登記注冊,并且表明自己是為哪個工程服務的。當相應的工程發(fā)生變化時,Gitlab-CI就會通知相應的工人執(zhí)行軟件集成腳本。如下圖所示:
gitlab里面的runner叫Gitlab-Runner
,Gitlab-Runner是配合Gitlab-CI進行使用的。一般地,Gitlab里面的每一個工程都會定義一個屬于這個工程的軟件集成腳本,用來自動化地完成一些軟件集成工作。當這個工程的倉庫代碼發(fā)生變動時,比如有人push了代碼,GitLab就會將這個變動通知Gitlab-CI。這時Gitlab-CI會找出與這個工程相關(guān)聯(lián)的Runner,并通知這些Runner把代碼更新到本地并執(zhí)行預定義好的執(zhí)行腳本(也就是在Job執(zhí)行流程
那個圖中所示的第三步:script),所以,Gitlab-Runner就是一個用來執(zhí)行軟件集成腳本script
的東西。
Runner類型
Gitlab-Runner可以分類兩種類型:Shared Runner(共享型)和Specific Runner(指定型)。
- Shared Runner:這種Runner(工人)是所有工程都能夠用的。只有系統(tǒng)管理員能夠創(chuàng)建Shared Runner。
- Specific Runner:這種Runner(工人)只能為指定的工程服務。擁有該工程訪問權(quán)限的人都能夠為該工程創(chuàng)建Shared Runner。
關(guān)于Gitlab-runner的安裝,會以單獨一個文章進行介紹,注冊runner會對應一個tag,記住這個tag;
.gitlab-ci.yml簡介
.gitlab-ci.yml 文件被用來管理項目的 runner 任務,Gitlab CI通過.gitlab-ci.yml文件管理配置job,該文件定義了statge順序、job應該如何觸發(fā)和工作、執(zhí)行什么腳本、如何構(gòu)建pipeline等流程
該文件存放于倉庫的根目錄, 默認名為
.gitlab-ci.yml
我們先看一個簡單的例子:.gitlab-ci.yml
## 定義pipeline流程:verify->build->dockerpush->deploy
stages:
- verify
- build
- dockerpush
- deploy
#單元測試
unit-test:
stage: verify # 屬于哪個流程
tags:
- test-cicd # 在哪個runner上面執(zhí)行,在注冊runner可以自定義
script:
- echo unit-test # 執(zhí)行腳本
#java編譯
java-package:
stage: build
tags:
- test-cicd
script:
- echo build
#push鏡像
docker-push:
stage: dockerpush
tags:
- test-cicd
script:
- echo docker-push
#deploy
service-1:
stage: deploy
tags:
- test-cicd
script:
- echo deploy
該配置對應下面的pipeline,test-cicd
是一個Specific Runner
,執(zhí)行腳本的類型是shell
所以,以unit-test
這個job為例,點擊該任務可以進入到log界面查看整個log執(zhí)行流程
剩下的job的執(zhí)行日志都大部分如此,就不一一列舉了
幾個重要的關(guān)鍵字解析
關(guān)于gitlab-ci.yml,里面有很多關(guān)鍵字配置,下面我主要列舉一些比較常用的關(guān)鍵字
before_script和after_script
隨著項目越來越大,Job 越來越多,Job 中包含的重復邏輯可能會讓配置文件臃腫不堪。.gitlab-ci.yml 中提供了?before_script
?和?after_script
?兩個全局配置項。這兩個配置項在所有 Job 的?script
?執(zhí)行前和執(zhí)行后調(diào)用。
before_script
?和?script
?在一個上下文中是串行執(zhí)行的,after_script
?是獨立執(zhí)行的。所以根據(jù)執(zhí)行器(在runner注冊的時候,可以選擇執(zhí)行器,docker,shell 等)的不同,工作樹之外的變化可能不可見,例如,在before_script中執(zhí)行軟件的安裝。
你可以在任務中定義?before_script
,after_script
,也可以將其定義為頂級元素,定義為頂級元素將為每一個任務都執(zhí)行相應階段的腳本或命令。
stages
stages的允許定義多個,靈活的場景階段的pipline。定義的元素的順序決定了任務執(zhí)行的順序。例如:
## 定義pipeline流程:verify->build->dockerpush->deploy
stages:
- verify
- build
- dockerpush
- deploy
- build場景的任務將被并行執(zhí)行。test、deploy 同理
- build 任務成功后,test 執(zhí)行。test 成功后,deploy 執(zhí)行
- 所有的都成功了,提交將會標記為成功
- 任何一步任務失敗了,提交標記為失敗并之后的場景,任務都不回執(zhí)行。
tags
tags可以從允許運行此項目的所有Runners中選擇特定的Runners來執(zhí)行jobs。
在注冊Runner的過程中,我們可以設置Runner的標簽,tags可通過tags來指定特殊的Runners來運行jobs:
#單元測試
unit-test:
stage: verify # 屬于哪個流程
tags:
- test-cicd # 在哪個runner上面執(zhí)行,在注冊runner可以自定義
script
script是一段由Runner執(zhí)行的shell腳本,可以執(zhí)行多個,例如:
job:
script: mvn clean test
這個參數(shù)也可以使用數(shù)組包含好幾條命令
job:
script:
- pwd
- mvn clean test
only and except
only和except兩個參數(shù)說明了job什么時候?qū)粍?chuàng)建:
- only定義了job需要執(zhí)行的所在分支或者標簽
- except定義了job不會執(zhí)行的所在分支或者標簽
以下是這兩個參數(shù)的幾條用法規(guī)則:
- only和except如果都存在在一個job聲明中,則所需引用將會被only和except所定義的分支過濾.
- only和except允許使用正則
-
only
和except
可同時使用。如果only
和except
在一個job配置中同時存在,則以only
為準,跳過except
(從下面示例中得出)。 -
only
和except
允許使用特殊的關(guān)鍵字:branches
,tags
和triggers
。 -
only
和except
允許使用指定倉庫地址但不是forks的倉庫(查看示例3)。
例子解析:
1.job將會只在issue-開頭的refs下執(zhí)行,反之則其他所有分支被跳過:
job:
# use regexp
only:
- /^issue-.*$/
# use special keyword
except:
- branches
2.job只會在打了tag的分支,或者被api所觸發(fā),或者每日構(gòu)建任務上運行
job:
# use special keywords
only:
- tags # tag 分支 commit 之后觸發(fā)
- triggers # API 觸發(fā)
- schedules # 每日構(gòu)建觸發(fā)
3.job將會在父倉庫gitlab-org/gitlab-ce的非master分支有提交時運行。
job:
only:
- branches@gitlab-org/gitlab-ce
except:
- master@gitlab-org/gitlab-ce
when
when可以設置以下值:
- on_success - 只有前面stages的所有工作成功時才執(zhí)行。 這是默認值。
- on_failure - 當前面stages中任意一個jobs失敗后執(zhí)行。
- always - 無論前面stages中jobs狀態(tài)如何都執(zhí)行。
-
manual
?- 手動執(zhí)行(GitLab8.10增加)。
stages:
- build
- cleanup_build
- test
- deploy
- cleanup
build_job:
stage: build
script:
- make build
cleanup_build_job:
stage: cleanup_build
script:
- cleanup build when failed
when: on_failure
test_job:
stage: test
script:
- make test
deploy_job:
stage: deploy
script:
- make deploy
when: manual
cleanup_job:
stage: cleanup
script:
- cleanup after jobs
when: always
腳本說明:
- 只有當build_job失敗的時候才會執(zhí)行`cleanup_build_job 。
- 不管前一個job執(zhí)行失敗還是成功都會執(zhí)行`cleanup_job 。
- 可以從GitLab界面中手動執(zhí)行deploy_jobs。
manual:
- 在GitLab的用戶界面中顯示該作業(yè)的“播放”按鈕
- 意味著deploy_job僅在單擊“播放”按鈕時才會觸發(fā)job。
修改上面那個例子
stages:
- verify
- build
- dockerpush
- deploy
- cleanup
before_script:
- pwd
after_script:
- echo after_script
#單元測試
unit-test:
stage: verify
tags:
- test-cicd
script:
- echo unit-test
#java編譯
java-package:
stage: build
tags:
- test-cicd
script:
- echo build
#push鏡像
docker-push:
stage: dockerpush
tags:
- test-cicd
script:
- echo docker-push
#deploy
service-1:
stage: deploy
tags:
- test-cicd
script:
- echo deploy
when: manual # 手動觸發(fā)job,只有點擊按鈕才會觸發(fā)
cleanup_job:
stage: cleanup
script:
- echo clean up
when: always # 前面的job成功與否,都會執(zhí)行該job
pipeline如下:
allow_failure
跟when
一起控制job執(zhí)行與否
的配置還有一個就是allow_failure
allow_failure可以用于當你想設置一個job失敗的之后并不影響后續(xù)的CI組件的時候。失敗的jobs不會影響到commit狀態(tài)。
下面的這個例子中,java-package
和java-package2
將會并列進行,如果java-package2
失敗了,它也不會影響進行中的下一個stage,因為這里有設置了allow_failure: true。
stages:
- verify
- build
- dockerpush
- deploy
- cleanup
before_script:
- pwd
after_script:
- echo after_script
#單元測試
unit-test:
stage: verify
tags:
- test-cicd
script:
- echo unit-test
#java編譯
java-package:
stage: build
tags:
- test-cicd
script:
- echo build
#java編譯
java-package2:
stage: build
tags:
- test-cicd
script:
- execute_script_that_will_fail # 該shell會導致job執(zhí)行失敗
allow_failure: true # 不影響后面的任務進行
#push鏡像
docker-push:
stage: dockerpush
tags:
- test-cicd
script:
- echo docker-push
#deploy
service-1:
stage: deploy
tags:
- test-cicd
script:
- echo deploy
when: manual
cleanup_job:
stage: cleanup
tags:
- test-cicd
script:
- echo clean up
when: always
java-package2會執(zhí)行錯誤
運行的pipeline如下,可見java-package2
的執(zhí)行錯誤
variables
GitLab CI允許你為.gitlab-ci.yml增加變量,該變量將會被設置入任務環(huán)境。通過兩種方式可以引用
- 美元符+大括號引用:
${}
- 美元符:
$
示例如下:
variables:
SOFT_VERSION: '1.0'
TAG_NAME: 'xxx'
#構(gòu)建鏡像
docker-build:
stage: dockerpush
tags:
- test-cicd
script:
- docker build -t $TAG_NAME:${SOFT_VERSION}
如果有些值不想在配置文件中顯示,比如密碼什么的,可以在代碼倉庫中setting->CICD->Variables 自定義變量,跟在.gitlab-ci.yml
配置變量效果是一樣的
variables的保留字
gitlab-ci有一些預定義變量,這些變量大部分以CI
開頭文章來源:http://www.zghlxwxcb.cn/news/detail-815023.html
預定義變量:
Variable | GitLab | Runner | Description |
---|---|---|---|
CI | all | 0.4 | 標識該job是在CI環(huán)境中執(zhí)行 |
CI_COMMIT_REF_NAME | 9.0 | all | 用于構(gòu)建項目的分支或tag名稱 |
CI_COMMIT_REF_SLUG | 9.0 | all | 先將$CI_COMMIT_REF_NAME 的值轉(zhuǎn)換成小寫,最大不能超過63個字節(jié),然后把除了0-9 和a-z 的其他字符轉(zhuǎn)換成- 。在URLs和域名名稱中使用。 |
CI_COMMIT_SHA | 9.0 | all | commit的版本號 |
CI_COMMIT_TAG | 9.0 | 0.5 | commit的tag名稱。只有創(chuàng)建了tags才會出現(xiàn)。 |
CI_DEBUG_TRACE | 9.0 | 1.7 | debug tracing開啟時才生效 |
CI_ENVIRONMENT_NAME | 8.15 | all | job的環(huán)境名稱 |
CI_ENVIRONMENT_SLUG | 8.15 | all | 環(huán)境名稱的簡化版本,適用于DNS,URLs,Kubernetes labels等 |
CI_JOB_ID | 9.0 | all | GItLab CI內(nèi)部調(diào)用job的一個唯一ID |
CI_JOB_MANUAL | 8.12 | all | 表示job啟用的標識 |
CI_JOB_NAME | 9.0 | 0.5 |
.gitlab-ci.yml 中定義的job的名稱 |
CI_JOB_STAGE | 9.0 | 0.5 |
.gitlab-ci.yml 中定義的stage的名稱 |
CI_JOB_TOKEN | 9.0 | 1.2 | 用于同GitLab容器倉庫驗證的token |
CI_REPOSITORY_URL | 9.0 | all | git倉庫地址,用于克隆 |
CI_RUNNER_DESCRIPTION | 8.10 | 0.5 | GitLab中存儲的Runner描述 |
CI_RUNNER_ID | 8.10 | 0.5 | Runner所使用的唯一ID |
CI_RUNNER_TAGS | 8.10 | 0.5 | Runner定義的tags |
CI_PIPELINE_ID | 8.10 | 0.5 | GitLab CI 在內(nèi)部使用的當前pipeline的唯一ID |
CI_PIPELINE_TRIGGERED | all | all | 用于指示該job被觸發(fā)的標識 |
CI_PROJECT_DIR | all | all | 倉庫克隆的完整地址和job允許的完整地址 |
CI_PROJECT_ID | all | all | GitLab CI在內(nèi)部使用的當前項目的唯一ID |
CI_PROJECT_NAME | 8.10 | 0.5 | 當前正在構(gòu)建的項目名稱(事實上是項目文件夾名稱) |
CI_PROJECT_NAMESPACE | 8.10 | 0.5 | 當前正在構(gòu)建的項目命名空間(用戶名或者是組名稱) |
CI_PROJECT_PATH | 8.10 | 0.5 | 命名空間加項目名稱 |
CI_PROJECT_PATH_SLUG | 9.3 | all |
$CI_PROJECT_PATH 小寫字母、除了0-9 和a-z 的其他字母都替換成- 。用于地址和域名名稱。 |
CI_PROJECT_URL | 8.10 | 0.5 | 項目的訪問地址(http形式) |
CI_REGISTRY | 8.10 | 0.5 | 如果啟用了Container Registry,則返回GitLab的Container Registry的地址 |
CI_REGISTRY_IMAGE | 8.10 | 0.5 | 如果為項目啟用了Container Registry,它將返回與特定項目相關(guān)聯(lián)的注冊表的地址 |
CI_REGISTRY_PASSWORD | 9.0 | all | 用于push containers到GitLab的Container Registry的密碼 |
CI_REGISTRY_USER | 9.0 | all | 用于push containers到GItLab的Container Registry的用戶名 |
CI_SERVER | all | all | 標記該job是在CI環(huán)境中執(zhí)行 |
CI_SERVER_NAME | all | all | 用于協(xié)調(diào)job的CI服務器名稱 |
CI_SERVER_REVISION | all | all | 用于調(diào)度job的GitLab修訂版 |
CI_SERVER_VERSION | all | all | 用于調(diào)度job的GItLab版本 |
ARTIFACT_DOWNLOAD_ATTEMPTS | 8.15 | 1.9 | 嘗試運行下載artifacts的job的次數(shù) |
GET_SOURCES_ATTEMPTS | 8.15 | 1.9 | 嘗試運行獲取源的job次數(shù) |
GITLAB_CI | all | all | 用于指示該job是在GItLab CI環(huán)境中運行 |
GITLAB_USER_ID | 8.12 | all | 開啟該job的用戶ID |
GITLAB_USER_EMAIL | 8.12 | all | 開啟該job的用戶郵箱 |
RESTORE_CACHE_ATTEMPTS | 8.15 | 1.9 | 嘗試運行存儲緩存的job的次數(shù) |
更多配置,可以參考官方參考文檔:CI/CD YAML syntax reference | GitLab文章來源地址http://www.zghlxwxcb.cn/news/detail-815023.html
到了這里,關(guān)于DevOps系列文章之 GitLab CI/CD的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!