概述
1. CI/CD
CI(持續整合)指開發人員一天內進行多次合併和提交程式碼操作,並透過自動化測試,完成構建
CD(持續部署)指每次程式碼更改都會自動部署到對應環境
CI/CD 結合在一起,可以加快開發團隊交付成果的效率,減少時間成本
2. Gitlab-CI/CD
gitlab-ci 是 gitlab8.0 之後自帶的一個持續整合系統,中心思想是每一次 push 到 gitlab 就會觸發一次指令碼執行,指令碼內容包括測試、編譯、部署等一系列內容
gitlab-ci 的指令碼需要 gitlab-runner 來執行,程式碼 push 之後,webhook 檢查到程式碼變化,就會觸發 gitlab-ci,分配到各個 Runner 來執行相應的指令碼
gitlab-ce
1. 安裝 gitlab-ce
gitlab 有 ce 和 ee 兩個版本,ce 是社群版,開源免費,ee 是企業版,需要付費
下面以 Ubuntu18.04.6 為例,安裝 gitlab-ce
安裝依賴軟體
sudo apt-get update
sudo apt-get install -y curl openssh-server ca-certificates tzdata perl
新增 gitlab 軟體源映象
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
安裝 gitlab-ce
sudo apt-get install gitlab-ce
如果命令列能看到 Gitlab 的 Logo 列印,就說明安裝成功了
開啟 gitlab 配置檔案
vim /etc/gitlab/gitlab.rb
為了能在瀏覽器訪問 gitlab,還需要配置 gitlab 的訪問地址和埠
# ip:port 改成自己的,也可以用域名
external_url 'http://192.168.66.100:82'
過載配置並重啟
gitlab-ctl recofigure
gitlab-ctl restart
在瀏覽器輸入 http://192.168.66.100:82
即可訪問 gitlab,當然了,前提是你的埠要放開
初始使用者名稱為 root,初始密碼記錄在 /etc/gitlab/initial_root_password
檔案,密碼有效期為 24 小時,建議登入後儘快修改密碼
登入以後,就可以建立專案了,其餘的基本的 git 操作這裡就不贅述了
2. 其他問題
gitlab-ctl recofigure
過程,有可能出現卡在 ruby_block[wait for logrotate service socket] action run
的情況,解決辦法如下:
-
ctrl + c 強行結束
-
執行
systemctl restart gitlab-runsvdir
-
再次執行
gitlab-ctl recofigure
安裝結束以後,訪問 web 端報 502,最可能的原因是埠被佔用了,需要修改埠
vim /etc/gitlab/gitlab.rb
# 修改為沒有被使用的埠即可
puma['port'] = 9091
gitlab-runner
1. 安裝 gitlab-runner
下面以 Ubuntu18.04.6 為例,安裝 gitlab-runner
新增 gitlab 軟體源映象
curl https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
安裝 gitlab-runner
sudo apt-get install gitlab-runner
2. gitlab-runner 註冊
首先獲取 gitlab-ci 的 token:專案主頁->Setting->CI/CD->Runners Expand
使用命令註冊 gitlab-runner
gitlab-runner register
按照步驟輸入:
- GitLab instance URL:如上圖所示 URL
- registration token:如上圖所示 Token
- description:關於該 Runner 的描述
- tags:用於標記該 Runner,後續需要使用這個 tag 來指定 gitlab-runner
- optional maintenance note:沒搞懂有啥用,隨意寫
- Enter an executor:選擇執行器,gitlab-runner 提供了許多執行器,可用在不同場景中執行構建,這裡選擇 shell
完成以後,重新整理頁面,即可在 Runners Expand 看到新增了一個 Runner
3. 簡單示例
下面我們簡單測試一下 Runner 是否能正常執行,隨意新建一個 SpringBoot 專案
在根目錄下建立一個 .gitlab-ci.yml 檔案,這裡只是簡單輸出一段語句
stages:
- deploy
deploy-job:
tags:
- prod
stage: deploy
script:
- echo "hello world!!!"
push 到 gitlab 後,會發現指令碼已經自動執行了,綠勾代表執行成功
點選綠勾,在下方 Pipeline 點選 deploy-job 可以檢視執行過程
pipeline 語法
1. job & script
.gitlab-ci.yml 檔案中可以定義一個或多個作業(job),每個作業獨立執行,必須有唯一的名稱(不能使用關鍵字)以及包含一個 script,這裡定義了三個作業 build、test、deploy,script 可以是 shell 命令
build:
script:
- echo "build"
test:
script:
- echo "test"
deploy:
script:
- echo "deploy"
- echo "finish"
2. before_script & after_script
before_script 用於定義一個命令,在每個作業執行之前執行,before_script 失敗將導致整個作業失敗,其他作業不再執行,如果在作業中定義了 before_script,則該作業不會執行全域性的 before_script
after_script 用於定義一個命令,在每個作業執行之後執行,作業失敗不影響 after_script 的執行,如果在作業中定義了 after_script,則該作業不會執行全域性的 after_script
before_script:
- echo "before script"
build:
before_script:
- echo "before script in buildjob"
script:
- echo "build"
after_script:
- echo "before script in buildjob"
test:
script:
- echo "test"
deploy:
script:
- echo "deploy"
- echo "finish"
after_script:
- echo "after script"
3. stages & stage
用於定義作業可以使用的階段,並且是全域性定義的,同一階段的作業並行執行,不同階段按順序執行
before_script:
- echo "before script"
stages:
- build
- test
- deploy
build:
before_script:
- echo "before script in buildjob"
stage: build
script:
- echo "build"
after_script:
- echo "before script in buildjob"
test:
stage: test
script:
- echo "test"
deploy:
stage: deploy
script:
- echo "deploy"
- sleep 5
after_script:
- echo "after script"
4. .pre & .post
.pre 始終是整個 pipeline 的第一個執行階段,.post 始終是整個 pipeline 的最後一個執行階段,無法修改,使用者自定義的 stage 則在這兩者之間,如果一個 pipeline 僅包含 .pre 和 .post,則不會建立 pipeline
before_script:
- echo "before script"
stages:
- build
- test
- deploy
codescan:
stage: .pre
script:
- echo "codescan"
build:
before_script:
- echo "before script in buildjob"
stage: build
script:
- echo "build"
after_script:
- echo "before script in buildjob"
test:
stage: test
script:
- echo "test"
deploy:
stage: deploy
script:
- echo "deploy"
- sleep 5
after_script:
- echo "after script"
5. variables
定義變數,可以定義 pipeline 變數、job 變數,job 變數優先順序最高
before_script:
- echo "before script"
variables:
DOMAIN: example.com
stages:
- build
- test
- deploy
codescan:
stage: .pre
script:
- echo "codescan"
build:
before_script:
- echo "before script in buildjob"
stage: build
script:
- echo "build"
- echo "$DOMAIN"
after_script:
- echo "before script in buildjob"
test:
stage: test
script:
- echo "test"
deploy:
stage: deploy
script:
- echo "deploy"
- sleep 5
after_script:
- echo "after script"
6. tags
用於指定特定的 job 在特定的 runner 執行,如果 job 不指定 tags,則預設在共享的 runner 執行
windows_job:
stages:
- build
tags:
-windows
script:
- echo "windows job"
linux_job:
stages:
- build
tags:
-linux
script:
- echo "linux job"
7. allow_failure
allow_failure 表示是否允許作業失敗,預設值 false 不允許失敗,改為 true 後,如果該作業失敗也不會被阻塞
job1:
stage: test
script:
- "..."
allow_failure: true
8. when
when 用於控制作業執行:
- on_success:前面階段的所有作業成功才執行該作業,預設 on_success
- on_failure:前面階段出現失敗時執行
- always:總是執行作業
- manual:手動執行作業
- delayed:延遲執行作業
job1:
stage: test
script:
- "..."
when: delayed # 表示延遲30s執行
start_in: "30"
9. retry
配置作業失敗後重試作業的次數
job1:
stage: test
script:
- "..."
retry: 2
也可以精確匹配到某一錯誤,即出現某一錯誤時才重試
job1:
stage: test
script:
- "..."
retry:
max: 2
when:
- script_failure # 指令碼失敗時重試
10. timeout
作業級別的超時可以超過專案級別的超時,但不能超過 Runner 特定的超時
job1:
stage: test
script:
- "..."
timeout: 3h
11. parallel
配置要並行執行的作業的例項數,此值必須大於等於 2 並小於等於 50,這將建立 N 個並行執行的同一作業例項
job1:
stage: test
script:
- "..."
parallel: 5
12. rules
rules 允許按順序評估單個規則,直到匹配為止:
-
if:如果條件匹配,多條件匹配可以使用 && ||
variables: DOMAIN: example.com job1: stage: test script: - "..." rules: # DOMAIN值匹配,則手動執行,否則 - if: '$DOMAIN == "example.com"' when: manual - if: '$DOMAIN == "example2.com"' when: delayed start_in: '5' - when: on_success
-
changes:指定檔案發生變化
job1: stage: test script: - "..." rules: - changes: - fimeName # 檔名 when: manual - when: on_success
-
exists:指定檔案存在
job1: stage: test script: - "..." rules: - exists: - fimeName # 檔名 when: manual - when: on_success
13. workflow-rules
workfolw 關鍵字適用於整個管道,並確定是否建立管道
variables:
DOMAIN: example.com
workflow:
rules:
- if: '$DOMAIN == "example.com"'
when: always # 預設always,可以設定never
- when: never
14. cache
儲存編譯專案時所需的執行時依賴項,指定專案工作空間中需要在 job 之間快取的檔案或目錄
全域性 cache 定義在 job 之外,針對所有 job 生效,job 中的 cache 優於全域性
cache:
paths: # 在全域性定義快取
- my/files
job:
script: "..."
cache:
key: job # 為快取設定唯一key,會為該job分配一個獨立的cache
paths: # 在job中定義快取,快取target目錄下的所有.jar檔案,該快取將覆蓋全域性快取
- target/*.jar
# policy: pull # pull:不下載快取,push不上傳快取,預設會在job執行之前下載快取,並在結束之後上傳快取
15. artifacts
用於指定作業成功或失敗時應附加到作業的檔案或目錄的列表,可在 Gitlab UI 中下載
build:
script:
- mvn package
artifacts:
name: "$ARTIFACTS_NAME" # 指定所建立的製品名稱,預設為artifacts,下載為artifacts.zip
paths:
- target/*.jar
when: always # 製品建立條件,on_success:作業成功時創造製品,on_failure:作業失敗時建立制品,always:總是建立制品
expire_in: 1 week # 製品有效期,從儲存到gitlab開始算起,預設30天
16. dependencies
獲取當前階段之前的製品
build:
stage: build
script:
- mvn package
artifacts:
name "$ARTIFACTS_NAME"
paths:
- target/*.jar
deploy:
dependencies:
- build
stage: deploy
script:
- ... # 部署製品
17. needs
可以讓作業無需按照階段順序執行,下述的例子表示:deploy-a 在 build-a 完成之後就可以執行,deploy-b 在 build-b 完成之後就可以執行
stages:
- build
- deploy
build-a:
stage: build
script:
- ...
build-b:
stage: build
script:
- ...
deploy-a:
stage: deploy
script:
- ...
needs: ["build-a"]
deploy-b:
stage: deploy
script:
- ...
needs: ["build-b"]
18. include
可以引入外部 yaml 檔案,使用合併功能可以自定義和覆蓋本地定義的 CI/CD 配置
local
引入同一儲存庫的檔案,使用相對於根目錄的完整路徑進行引用,必須保證走到同一分支
假設有 ci/localci.yml 檔案
stages:
- deploy
deploy-job:
stage: deploy
script: ...
在 .gitlab-ci.yml 引入 ci/localci.yml 檔案,如果存在相同名稱的作業,它們的配置會進行合併,並且原檔案 .gitlab-ci.yml 的配置優先生效
include:
local: "ci/localci.yaml"
stages:
- build
- test
- deploy
build-job:
stage: build
script: ...
test-job:
stage: test
script: ...
file
引入其他專案的 yaml 配置
include:
project: demo/demo-java-service
ref: master
file: .gitlab-ci.yml
template
引入官方提供的模板,可以訪問 https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates 檢視有哪些模板
include:
template: Auto-DevOps.gitlab-ci.yml
remote
引入遠端檔案
include:
remote: "https://gitlab.com/awesome-project/raw/master/.gitlab-ci-template.yml"
19. extends
繼承作業配置,相同配置覆蓋,不同則繼承
.tests:
script: mvn test
stage: test
only:
refs:
- tags
test-job:
extends: .tests
script: mvn clean test
only:
variables:
- $RSPEC
最終得到的作業配置如下
test-job:
stage: test
script: mvn clean test
only:
variables:
- $RSPEC
refs:
- tags
20. trigger
當 gitlab 從 trigger 定義建立的作業啟動時,將建立一個下游管道,允許建立多專案管道和子管道:
-
多專案管道:跨多個專案設定流水線,以便一個專案的管道可以觸發另一個專案的管道
stagging: variables: ENVIROMENT: stagging # 該變數會傳遞給下游管道,如果上下游定義了相同名稱的變數,上游變數將優先 stage: deploy trigger: project: demo/demo-java-service # 指定下游專案的完整路徑 branch: master # 指定專案的分支名稱 strategy: depend # 將自身狀態從觸發的管道合併到源作業
-
父子管道:同一專案的管道可以觸發一組同時執行的子管道
子管道 ci/child.yml
stages: - build child-build-job: stage: build script: ...
父管道
stages: - deploy stagging: stage: deploy trigger: include: ci/child.yml strategy: depend21
21. image
首先註冊一個工作型別為 docker 的 runner,只要使用該型別的 runner,所有執行操作都會在容器中執行
gitlab-runner register \
--non-interactive \
--executor "docker" \
--docker-image alpine:latest \ # 預設使用該映象
--url "http://192.168.1.200:30088/" \
--registration-token "JRzzw2j1Ji6aBjwvkxAv" \
--description "docker-runner" \
--tag-list "docker" \
--run-untagged="true" \
--locked="false" \
--access-level="not_protected"
預設註冊 runner 會指定一個基礎映象,如果全域性指定 image 則所有作業使用該映象建立容器並執行,如果全域性未指定 image,則檢視 job 中是否有指定,有則按照 job 指定的映象建立容器並執行,否則使用預設映象
image: maven:3.6.3-jdk-8 # 全域性定義
...
deploy-job:
stage: deploy
tags:
- docker
script: ...
image: maven:3.6.3-jdk-8 # 區域性定義
22. services
工作期間執行的另一個 Docker 服務映象,將其 link 到 image 定義的 Docker 映象,這樣可以在構建期間訪問該服務映象
...
services:
- name: mysql:latest
alias: mysql
build-job:
stage: build
tags:
- docker
script: ...
image: maven:3.6.3-jdk-8 # 區域性定義
23. environment
可用於在 gitlab ui 追蹤作業執行情況,
deploy-job:
stage: deploy
tags:
- docker
script: ...
environment:
name: production # 應用名稱
url: http://www.baidu.com # 應用地址