本文將會對Gitlab CI進行簡要介紹,包括Gitlab Runner,Gitlab CI中的相關概念以及.gitlab-ci.yml的經常使用配置。html
GitLab CI 是GitLab內置的進行持續集成的工具,只須要在倉庫根目錄下建立.gitlab-ci.yml 文件,並配置GitLab Runner;每次提交的時候,gitlab將自動識別到.gitlab-ci.yml文件,而且使用Gitlab Runner執行該腳本。vue
GitLab-Runner就是一個用來執行.gitlab-ci.yml 腳本的工具。能夠理解成,Runner就像認真工做的工人,GitLab-CI就是管理工人的中心,全部工人都要在GitLab-CI裏面註冊,而且代表本身是爲哪一個項目服務。當相應的項目發生變化時,GitLab-CI就會通知相應的工人執行對應的腳本。git
GitLab-Runner能夠分類兩種類型:Shared Runner(共享型)和Specific Runner(指定型)。web
以Linux爲例:docker
# For Debian/Ubuntu
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.deb.sh | sudo bash
# For RHEL/CentOS
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.rpm.sh | sudo bash複製代碼
其餘系統請參考官網文檔:docs.gitlab.com/runner/inst…shell
▍獲取Runner註冊Token 安裝好Runner以後,須要向Gitlab進行註冊,註冊Runner須要GitLab-CI的url和token。可根據需求註冊選擇所需類型Runner。npm
獲取Shared Runner註冊Token: 使用管理員用戶登陸,進入Admin Area -> OverView -> Runners界面。 獲取Specific Runner註冊Token: 進行項目倉庫 -> settings -> CI/CD界面 ▍註冊Runner 執行gitlab-ci-multi-runner register命令進行Runner註冊,期間會用到前期獲取的url及token;註冊完成以後,GitLab-CI就會多出一條Runner記錄: 更多系統註冊,請參考閱讀官方文檔:docs.gitlab.com/runner/regi…json
每一個推送到 Gitlab 的提交都會產生一個與該提交關聯的管道(pipeline),若一次推送包含了多個提交,則管道與最後那個提交相關聯,管道(pipeline)就是一個分紅不一樣階段(stage)的做業(job)的集合。api
階段是對批量的做業的一個邏輯上的劃分,每一個 GitLab CI/CD 都必須包含至少一個 Stage。多個 Stage 是按照順序執行的,若是其中任何一個 Stage 失敗,則後續的 Stage 不會被執行,整個 CI 過程被認爲失敗。 以圖中所示爲例,整個 CI 環節包含三個 Stage:build、test 和deploy。數組
下圖是Gitlab對階段和階段狀態的展現:
做業就是運行器(Runner)要執行的指令集合,Job 能夠被關聯到一個 Stage。當一個 Stage 執行的時候,與其關聯的全部 Job 都會被執行。在有足夠運行器的前提下,同一階段的全部做業會併發執行。做業狀態與階段狀態是同樣的,實際上,階段的狀態就是繼承自做業的。
做業必須包含script(由Runner執行的shell腳本),隨着項目愈來愈大,Job 愈來愈多,Job 中包含的重複邏輯可能會讓配置文件臃腫不堪。.gitlab-ci.yml 中提供了 before_script 和 after_script 兩個全局配置項。這兩個配置項在全部 Job 的 script 執行前和執行後調用。
Job 的執行過程當中每每會產生一些數據,默認狀況下 GitLab Runner 會保存 Job 生成的這些數據,而後在下一個 Job 執行以前(甚至不侷限於當次 CI/CD)將這些數據恢復。這樣即使是不一樣的 Job 運行在不一樣的 Runner 上,它也能看到彼今生成的數據。
在瞭解了 Job 配置的 script、before_script、after_script 和 cache 之後,能夠將整個 Job 的執行流程用一張圖歸納:
從7.12版本開始,GitLab CI使用YAML文件(.gitlab-ci.yml)來管理項目配置。該文件存放於項目倉庫的根目錄,而且包含了你的項目如何被編譯的描述語句。YAML文件使用一系列約束敘述定義了Job啓動時所要作的事情。
Job是.gitlab-ci.yml文件中最基本的元素,由一系列參數定義了任務啓動時所要作的事情,用戶能夠建立任意個任務;每一個任務必須有一個獨一無二的名字,但有一些保留keywords不能用於Job名稱,image,services,stages,types,before_script,after_script,variables,cache。
Job被定義爲頂級元素,而且至少包括一條script語句,若是一個 Job 沒有顯式地關聯某個 Stage,則會被默認關聯到 test Stage。
示例:
job1:
# 關聯到bulid階段
stage: build
# 所需執行的腳本
script:
- execute-script-for-job1複製代碼
下面是關於配置CI/CD管道的經常使用參數詳細說明。
▍stages 用於定義全部做業(job)可使用的全局階段,gitlab-ci.yml容許靈活定義多個階段,stages元素的順序定義了做業執行的順序。Job關聯的stage名相同時,該多個Job將並行執行(在擁有足夠Runner狀況下)。下一個階段的job將會在前一個階段的job都完成的狀況下執行。
若是文件中沒有定義 stages,那麼則默認包含 build、test 和 deploy 三個 stage。Stage 中並不能直接配置任何具體的執行邏輯,具體的執行邏輯應該在 Job 中配置。
示例:
stages:
- build
- test
- deploy複製代碼
▍stage 階段是根據每一個Job定義的,而且依賴於全局定義的階段。它容許將做業(Job)分組到不一樣的階段。
示例:
stages:
- build
- test
- deploy
job 1:
stage: build
script: make build dependencies
job 2:
stage: build
script: make build artifacts
job 3:
stage: test
script: make test
job 4:
stage: deploy
script: make deploy複製代碼
▍script script是一段由Runner執行的shell腳本。
示例:
job:
script: "bundle exec rspec"複製代碼
這個參數也可使用數組包涵好幾條命令:
job:
script:
- uname -a
- bundle exec rspec複製代碼
有些時候,script命令須要被單引號或者雙引號所包裹。舉個例子,命令中包涵冒號的時候,該命令須要被引號所包裹,這樣YAML解析器才知道該命令語句不是「key: value」
語法的一部分。當命令中包涵如下字符時須要注意打引號:: { } [ ] , & * #? | - < > = ! % @
▍image and services 這兩個選項容許開發者指定任務運行時所需的自定義的docker鏡像和服務。
示例:
#爲每一個做業定義不一樣的映像和服務
test:2.1:
image: ruby:2.1
services:
- postgres:9.3
script:
- bundle exec rake spec
test:2.2:
image: ruby:2.2
services:
- postgres:9.4
script:
- bundle exec rake spec複製代碼
▍before_script和after_script before_script是用於定義一些在全部任務執行前所需執行的命令, 包括部署工做,能夠接受一個數組或者多行字符串。after_script用於定義全部job執行事後須要執行的命令,能夠接受一個數組或者多行字符串。
示例:
#定義全局 before_script:
default:
before_script:
- global before script
#覆蓋全局before_script
job:
before_script:
- execute this instead of global before script
script:
- my command
after_script:
- execute this after my script複製代碼
▍only and except
如下是這兩個參數的幾條用法規則:
值 | 描述 |
---|---|
branches | 當一個分支被push上來 |
tags | 當一個打了tag的分支被push上來 |
api | 當一個pipline被piplines api所觸發調起,詳見piplines api(docs.gitlab.com/ce/api/pipe… |
external | 當使用了GitLab之外的CI服務 |
pipelines | 針對多項目觸發器而言,當使用CI_JOB_TOKEN並使用gitlab所提供的api建立多個pipelines的時候 |
pushes | 當pipeline被用戶的git push操做所觸發的時候 |
schedules | 針對預約好的pipline而言(每日構建一類~,具體請看docs.gitlab.com/ce/user/pro…) |
triggers | 用token建立piplines的時候 |
web | 在GitLab頁面上Pipelines標籤頁下,你按了run pipline的時候 |
下面的例子,job將會只在issue-開頭的refs下執行,反之則其餘全部分支被跳過:
job:
# use regexp
only:
- /^issue-.*$/
# use special keyword
except:
- branches複製代碼
更多配置詳情,請參考官網文檔: docs.gitlab.com/ee/ci/yaml/…
驗證.gitlab-ci.yml GitLab CI的每一個實例都有一個名爲Lint的嵌入式調試工具,它能夠驗證.gitlab-ci.yml文件的內容,進入項目倉庫->CI/CD->CI Lint,示例以下:
# image: docker:latest
# services:
# variables:
# DOCKER_DRIVER: overlay
# 定義執行 Job 的步驟
stages:
- lint # 執行格式校驗
- build # build 成 Image
- push # push 到 Image 倉庫
- deploy # 執行步驟(拷貝運行文件到測試機,並運行)
- clearup # 清除 runner 本地的Image
# 每次執行 Job 以前(登陸到咱們本身的 Image 倉庫)
before_script:
- docker info
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" "$CI_REGISTRY" --password-stdin
# 每次執行 Job 以後(退出)
after_script:
- docker logout
# 第一步:執行 code lint 檢測
linting:
# 基於提早準備好的 Image 進行
image: *******:8081/sit-develop-tool/siteslinter:1.0.7
# 執行的是上面定義的哪一步
stage: lint
# 執行這一步以前作什麼
before_script:
- ls -a
- cat .eslintrc.js
- cat .gitignore
# 執行這一步以後作什麼
after_script:
- ls -a
- cat .eslintrc.js
- cat .gitignore
# 執行 Eslint 檢測
script:
- /home/app/.npm-global/bin/eslint -c .eslintrc.js --ext .js,.vue --color --ignore-path .gitignore .
# 這個 Job 運行在哪一個 Gitlab Runner 上
tags:
- NODE2
# 除了...都運行此 Job
except:
- develop
- master
- tags
# 第二步:將代碼 build 成 Image (在 Runner 上)
building:
stage: build
script:
# build (後面 tag 取 commit id 的 0-7 位)
- docker build --no-cache -t $CI_REGISTRY_IMAGE:${CI_COMMIT_SHA:0:7} .
tags:
- NODE2
# 只在...時運行此 Job
only:
refs:
- develop
# build 生產環境
building-prod:
stage: build
script:
- cat nuxt.config.js
- docker build --no-cache -t $CI_REGISTRY_IMAGE:${CI_COMMIT_SHA:0:7} .
tags:
- NODE2
# 只有下 Tag 時執行
only:
- tags
# 全部 branch 有變更時都不執行
except:
- branches
# 第三步:將 Image push 到 Image 倉庫(在 Gitlab 上)
pushing:
stage: push
script:
- docker push $CI_REGISTRY_IMAGE:${CI_COMMIT_SHA:0:7}
tags:
- NODE2
only:
refs:
- develop
- tags
# 第四步:將 sh 文件 copy 到測試機並執行(文件中會在測試機上將 Image run 成 container)
deploying:
image: ******/sit-develop-tool/tool-ansible:1.0.1
before_script:
- 'echo "Start to deploying..."'
stage: deploy
# 使用 ansible 工具, 將 lib 文件夾和 start.sh 文件 copy 到測試機並運行
# inventory 文件中會記錄登陸到測試機的信息(ip, account, psw)
script:
- |
ansible '*' -i `pwd`/inventory -m shell -a "mkdir -p /srv/dmz-proxy/" -b
ansible '*' -i `pwd`/inventory -m copy -a "src=lib dest=/srv/dmz-proxy/ owner=root group=root" -b
ansible '*' -i `pwd`/inventory -m copy -a "src=start.sh dest=/srv/dmz-proxy/ owner=root group=root" -b
ansible "*" -i `pwd`/inventory -m shell -a "chmod 777 /srv/dmz-proxy/start.sh"
# 執行 start.sh 並傳入 Image name
ansible "*" -i `pwd`/inventory -m shell \
-a "cd /srv/dmz-proxy/ && bash start.sh $CI_REGISTRY_IMAGE:${CI_COMMIT_SHA:0:7}" \
-b
ansible "*" -i `pwd`/inventory -m shell -a "cd /srv/dmz-proxy/ && rm -rf start.sh*" -b
# 定義此做業完成部署的環境名稱
environment:
name: production
tags:
- NODE2
only:
refs:
- develop
deploying-prod:
image: ******/sit-develop-tool/tool-kubectl-deployment:1.0.2
stage: deploy
script:
- sed -i "s/GITLAB_REGISTRY_IMAGE/******:${CI_COMMIT_SHA:0:7}/g" deployments/WevService-deploy.yml
- cat deployments/WevService-deploy.yml
- kubectl delete secret regcred || true
- kubectl create secret generic regcred --from-file=.dockerconfigjson=/root/.docker/config.json --type=kubernetes.io/dockerconfigjson
- kubectl apply -f deployments/ --record
- kubectl get services -o wide
- kubectl get pods -o wide
environment:
name: production
tags:
- NODE2
only:
- tags
except:
- branches
# 第五步:清除 Runner 上的 Image
clearing:
image: docker:latest
stage: clearup
script:
- docker rmi $CI_REGISTRY_IMAGE:${CI_COMMIT_SHA:0:7}
- docker rm $(docker ps -a -q) || true
tags:
- NODE2
only:
refs:
- develop
clearing-prod:
image: docker:latest
stage: clearup
script:
- docker images --filter=reference='*******' | grep " [months]* ago" | awk '{print $3}' | xargs docker image rm
- docker images
tags:
- NODE2
only:
- tags
except:
- branches複製代碼
本文由博客一文多發平臺 OpenWrite 發佈!