1. 流水線入門
工廠的流水線如下:
官方文檔 的流水線如下:
為什么叫做流水線?其實和工廠產(chǎn)品的生產(chǎn)線類似,pipeline 是從源碼到發(fā)布到線上環(huán)境。
關(guān)于流水線,需要知道的幾個點:
-
重要的功能插件,幫助 Jenkins 定義了一套工作流框架;
-
Pipeline 的實現(xiàn)方式是一套 Groovy DSL( 領(lǐng)域?qū)S谜Z言 ),所有的發(fā)布流程都可以表述為一段 Groovy 腳本;
-
將 WebUI 上需要定義的任務(wù),以腳本代碼的方式表述出來;
-
幫助jenkins實現(xiàn)持續(xù)集成 CI(Continue Integration)和持續(xù)部署 CD(Continue Deliver)的重要手段;
?? 流水線基礎(chǔ)語法
官方文檔
兩種語法類型:
- Scripted Pipeline,腳本式流水線,最初支持的類型
- Declarative Pipeline,聲明式流水線,為 Pipeline plugin 在 2.5 版本之后新增的一種腳本類型,后續(xù) Open Blue Ocean 所支持的類型。與原先的 Scripted Pipeline 一樣,都可以用來編寫腳本。Declarative Pipeline 是后續(xù) Open Blue Ocean 所支持的類型,寫法簡單,支持內(nèi)嵌 Scripted Pipeline 代碼
注意:為與 BlueOcean 腳本編輯器兼容,通常建議使用 Declarative Pipeline 的方式進(jìn)行編寫,從 jenkins 社區(qū)的動向來看,很明顯這種語法結(jié)構(gòu)也會是未來的趨勢。
?? 腳本示例
json
腳本
pipeline {
agent {label '172.21.51.68'}
environment {
PROJECT = 'myblog'
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
sh 'make'
}
}
stage('Test'){
steps {
sh 'make check'
junit 'reports/**/*.xml'
}
}
stage('Deploy') {
steps {
sh 'make publish'
}
}
}
post {
success {
echo 'Congratulations!'
}
failure {
echo 'Oh no!'
}
always {
echo 'I will always say Hello again!'
}
}
}
?? 腳本解釋
-
checkout
步驟為檢出代碼;scm
是一個特殊變量,指示checkout
步驟克隆觸發(fā)此 Pipeline 運行的特定修訂 -
agent:指明使用哪個 agent 節(jié)點來執(zhí)行任務(wù),定義于 pipeline 頂層或者 stage 內(nèi)部
-
any,可以使用任意可用的 agent 來執(zhí)行
-
label,在提供了標(biāo)簽的 Jenkins 環(huán)境中可用的代理上執(zhí)行流水線或階段。例如:
agent { label 'my-defined-label' }
,最常見的使用方式 -
none,當(dāng)在
pipeline
塊的頂部沒有全局代理,該參數(shù)將會被分配到整個流水線的運行中并且每個stage
部分都需要包含他自己的agent
部分。比如:agent none
-
docker, 使用給定的容器執(zhí)行流水線或階段。 在指定的節(jié)點中,通過運行容器來執(zhí)行任務(wù)
-
agent {
docker {
image 'maven:3-alpine'
label 'my-defined-label'
args '-v /tmp:/tmp'
}
}
-
options:允許從流水線內(nèi)部配置特定于流水線的選項。
- buildDiscarder,為最近的流水線運行的特定數(shù)量保存組件和控制臺輸出。例如:
options { buildDiscarder(logRotator(numToKeepStr: '10')) }
- disableConcurrentBuilds,不允許同時執(zhí)行流水線。 可被用來防止同時訪問共享資源等。 例如:
options { disableConcurrentBuilds() }
- timeout,設(shè)置流水線運行的超時時間, 在此之后,Jenkins將中止流水線。例如:
options { timeout(time: 1, unit: 'HOURS') }
- retry,在失敗時, 重新嘗試整個流水線的指定次數(shù)。 For example:
options { retry(3) }
- buildDiscarder,為最近的流水線運行的特定數(shù)量保存組件和控制臺輸出。例如:
-
environment:指令制定一個 鍵-值對序列,該序列將被定義為所有步驟的環(huán)境變量
-
stages:包含一系列一個或多個 stage 指令,
stages
部分是流水線描述的大部分 “work” 的位置。 建議stages
至少包含一個 stage 指令用于連續(xù)交付過程的每個離散部分,比如構(gòu)建、測試和部署。
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
-
steps:在給定的
stage
指令中執(zhí)行的定義了一系列的一個或多個 steps。 -
post:定義一個或多個 steps ,這些階段根據(jù)流水線或階段的完成情況而運行
post
支持以下 post-condition 塊中的其中之一:always
、changed
、failure
、success
、unstable
和aborted
。- always,無論流水線或階段的完成狀態(tài)如何,都允許在
post
部分運行該步驟 - changed,當(dāng)前流水線或階段的完成狀態(tài)與它之前的運行不同時,才允許在
post
部分運行該步驟 - failure,當(dāng)前流水線或階段的完成狀態(tài)為 “failure”,才允許在
post
部分運行該步驟,通常 web UI 是紅色 - success,當(dāng)前流水線或階段的完成狀態(tài)為 “success”,才允許在
post
部分運行該步驟,通常 web UI 是藍(lán)色或綠色 - unstable,當(dāng)前流水線或階段的完成狀態(tài)為 “unstable”,才允許在
post
部分運行該步驟,通常由于測試失敗,代碼違規(guī)等造成。通常 web UI 是黃色 - aborted,只有當(dāng)前流水線或階段的完成狀態(tài)為 “aborted”,才允許在
post
部分運行該步驟,通常由于流水線被手動的aborted。通常 web UI 是灰色
- always,無論流水線或階段的完成狀態(tài)如何,都允許在
創(chuàng)建 pipeline 示意:新建任務(wù) -> 流水線
jenkins/pipelines/p1.yaml
pipeline {
agent {label '172.21.51.68'}
environment {
PROJECT = 'myblog'
}
stages {
stage('printenv') {
steps {
echo 'Hello World'
sh 'printenv'
}
}
stage('check') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'gitlab-user', url: 'http://gitlab.luffy.com/root/myblog.git']]])
}
}
stage('build-image') {
steps {
sh 'docker build . -t myblog:latest -f Dockerfile'
}
}
stage('send-msg') {
steps {
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=4778abd23dbdbaf66fc6f413e6ab9c0103a039b0054201344a22a5692cdcc54e' \
-H 'Content-Type: application/json' \
-d '{"msgtype": "text",
"text": {
"content": "我就是我, 是不一樣的煙火"
}
}'
"""
}
}
}
}
點擊 “立即構(gòu)建”,同樣的,我們可以配置觸發(fā)器,使用 webhook 的方式接收項目的 push 事件
- 構(gòu)建觸發(fā)器選擇
Build when a change is pushed to GitLab.
- 生成
Secret token
- 配置
gitlab
,創(chuàng)建webhook
,發(fā)送test push events
測試
?? Blue Ocean
官方文檔
關(guān)于 Blue Ocean 我們需要知道的幾點:
- 是一個插件, 旨在為 Pipeline 提供豐富的體驗 ;
- 連續(xù)交付(CD)Pipeline 的復(fù)雜可視化,允許快速和直觀地了解 Pipeline 的狀態(tài);
- 目前支持的類型僅針對于 Pipeline,尚不能替代 Jenkins 經(jīng)典版UI
思考:文章來源地址http://www.zghlxwxcb.cn/news/detail-785754.html
- 每個項目都把大量的 pipeline 腳本寫在 Jenkins 端,對于誰去維護(hù)及維護(hù)成本是一個問題
- 沒法做版本控制
2. Jenkinsfile實踐
Jenkins Pipeline 提供了一套可擴(kuò)展的工具,用于將 “簡單到復(fù)雜” 的交付流程實現(xiàn)為 “持續(xù)交付即代碼”。
Jenkins Pipeline 的定義通常被寫入到一個文本文件(稱為 Jenkinsfile
)中,該文件可以被放入項目的源代碼控制庫中。
?? 演示一
演示1:使用 Jenkinsfile 管理 pipeline
- 在項目中新建 Jenkinsfile 文件,拷貝已有 script 內(nèi)容
- 配置 pipeline 任務(wù),流水線定義為 Pipeline Script from SCM
- 執(zhí)行 push 代碼測試
Jenkinsfile:jenkins/pipelines/p2.yaml
pipeline {
agent {label '172.21.51.68'}
environment {
PROJECT = 'myblog'
}
stages {
stage('printenv') {
steps {
echo 'Hello World'
sh 'printenv'
}
}
stage('check') {
steps {
checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'gitlab-user', url: 'http://gitlab.luffy.com/root/myblog.git']]])
}
}
stage('build-image') {
steps {
sh 'docker build . -t myblog:latest -f Dockerfile'
}
}
stage('send-msg') {
steps {
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=4778abd23dbdbaf66fc6f413e6ab9c0103a039b0054201344a22a5692cdcc54e' \
-H 'Content-Type: application/json' \
-d '{"msgtype": "text",
"text": {
"content": "我就是我, 是不一樣的煙火"
}
}'
"""
}
}
}
}
?? 演示二
演示2:優(yōu)化及豐富流水線內(nèi)容
-
優(yōu)化代碼檢出階段
由于目前已經(jīng)配置了使用 git 倉庫地址,且使用 SCM 來檢測項目,因此代碼檢出階段完全沒有必要再去指定一次
-
構(gòu)建鏡像的 tag 使用 git 的 commit id
-
增加 post 階段的消息通知,豐富通知內(nèi)容
-
配置 webhook,實現(xiàn) myblog 代碼推送后,觸發(fā) Jenkinsfile 任務(wù)執(zhí)行
jenkins/pipelines/p3.yaml
pipeline {
agent { label '172.21.51.68'}
stages {
stage('printenv') {
steps {
echo 'Hello World'
sh 'printenv'
}
}
stage('check') {
steps {
checkout scm
}
}
stage('build-image') {
steps {
retry(2) { sh 'docker build . -t myblog:${GIT_COMMIT}'}
}
}
}
post {
success {
echo 'Congratulations!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=4778abd23dbdbaf66fc6f413e6ab9c0103a039b0054201344a22a5692cdcc54e' \
-H 'Content-Type: application/json' \
-d '{"msgtype": "text",
"text": {
"content": "????構(gòu)建成功????\n 關(guān)鍵字:luffy\n 項目名稱: ${JOB_BASE_NAME}\n Commit Id: ${GIT_COMMIT}\n 構(gòu)建地址:${RUN_DISPLAY_URL}"
}
}'
"""
}
failure {
echo 'Oh no!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=4778abd23dbdbaf66fc6f413e6ab9c0103a039b0054201344a22a5692cdcc54e' \
-H 'Content-Type: application/json' \
-d '{"msgtype": "text",
"text": {
"content": "???構(gòu)建失敗???\n 關(guān)鍵字:luffy\n 項目名稱: ${JOB_BASE_NAME}\n Commit Id: ${GIT_COMMIT}\n 構(gòu)建地址:${RUN_DISPLAY_URL}"
}
}'
"""
}
always {
echo 'I will always say Hello again!'
}
}
}
?? 演示三
演示3:使用 k8s 部署服務(wù)
-
新建 deploy 目錄,將 k8s 所需的文件放到 deploy 目錄中
-
將鏡像地址改成模板,在 pipeline 中使用新構(gòu)建的鏡像進(jìn)行替換
-
執(zhí)行
kubectl apply -f deploy
應(yīng)用更改,需要配置 kubectl 認(rèn)證
$ scp -r k8s-master:/root/.kube /root
jenkins/pipelines/p4.yaml
pipeline {
agent { label '172.21.51.68'}
environment {
IMAGE_REPO = "172.21.51.143:5000/myblog"
}
stages {
stage('printenv') {
steps {
echo 'Hello World'
sh 'printenv'
}
}
stage('check') {
steps {
checkout scm
}
}
stage('build-image') {
steps {
retry(2) { sh 'docker build . -t ${IMAGE_REPO}:${GIT_COMMIT}'}
}
}
stage('push-image') {
steps {
retry(2) { sh 'docker push ${IMAGE_REPO}:${GIT_COMMIT}'}
}
}
stage('deploy') {
steps {
sh "sed -i 's#{{IMAGE_URL}}#${IMAGE_REPO}:${GIT_COMMIT}#g' manifests/*"
timeout(time: 1, unit: 'MINUTES') {
sh "kubectl apply -f manifests/"
}
}
}
}
post {
success {
echo 'Congratulations!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=4778abd23dbdbaf66fc6f413e6ab9c0103a039b0054201344a22a5692cdcc54e' \
-H 'Content-Type: application/json' \
-d '{"msgtype": "text",
"text": {
"content": "????構(gòu)建成功????\n 關(guān)鍵字:myblog\n 項目名稱: ${JOB_BASE_NAME}\n Commit Id: ${GIT_COMMIT}\n 構(gòu)建地址:${RUN_DISPLAY_URL}"
}
}'
"""
}
failure {
echo 'Oh no!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=4778abd23dbdbaf66fc6f413e6ab9c0103a039b0054201344a22a5692cdcc54e' \
-H 'Content-Type: application/json' \
-d '{"msgtype": "text",
"text": {
"content": "???構(gòu)建失敗???\n 關(guān)鍵字:luffy\n 項目名稱: ${JOB_BASE_NAME}\n Commit Id: ${GIT_COMMIT}\n 構(gòu)建地址:${RUN_DISPLAY_URL}"
}
}'
"""
}
always {
echo 'I will always say Hello again!'
}
}
}
?? 演示四
演示4:使用憑據(jù)管理敏感信息
上述 Jenkinsfile 中存在的問題是敏感信息使用明文,暴漏在代碼中,如何管理流水線中的敏感信息(包含賬號密碼),之前我們在對接 gitlab 的時候,需要賬號密碼,已經(jīng)使用過憑據(jù)來管理這類敏感信息,同樣的,我們可以使用憑據(jù)來存儲釘釘?shù)?token 信息,那么,創(chuàng)建好憑據(jù)后,如何在 Jenkinsfile 中獲取已有憑據(jù)的內(nèi)容?
Jenkins 的聲明式流水線語法有一個 credentials()
輔助方法(在 environment 指令中使用),它支持 secret 文本,帶密碼的用戶名,以及 secret 文件憑據(jù)。
下面的流水線代碼片段展示了如何創(chuàng)建一個使用帶密碼的用戶名憑據(jù)的環(huán)境變量的流水線。
在該示例中,帶密碼的用戶名憑據(jù)被分配了環(huán)境變量,用來使你的組織或團(tuán)隊以一個公用賬戶訪問 Bitbucket 倉庫;這些憑據(jù)已在 Jenkins 中配置了憑據(jù) ID jenkins-bitbucket-common-creds
。
當(dāng)在 environment
指令中設(shè)置憑據(jù)環(huán)境變量時:
environment {
BITBUCKET_COMMON_CREDS = credentials('jenkins-bitbucket-common-creds')
}
這實際設(shè)置了下面的三個環(huán)境變量:
-
BITBUCKET_COMMON_CREDS
- 包含一個以冒號分隔的用戶名和密碼,格式為username:password
。 -
BITBUCKET_COMMON_CREDS_USR
- 附加的一個僅包含用戶名部分的變量。 -
BITBUCKET_COMMON_CREDS_PSW
- 附加的一個僅包含密碼部分的變量。
pipeline {
agent {
// 此處定義 agent 的細(xì)節(jié)
}
environment {
//頂層流水線塊中使用的 environment 指令將適用于流水線中的所有步驟。
BITBUCKET_COMMON_CREDS = credentials('jenkins-bitbucket-common-creds')
}
stages {
stage('Example stage 1') {
//在一個 stage 中定義的 environment 指令只會將給定的環(huán)境變量應(yīng)用于 stage 中的步驟。
environment {
BITBUCKET_COMMON_CREDS = credentials('another-credential-id')
}
steps {
//
}
}
stage('Example stage 2') {
steps {
//
}
}
}
}
因此對 Jenkinsfile 做改造:jenkins/pipelines/p5.yaml
pipeline {
agent { label '172.21.51.68'}
environment {
IMAGE_REPO = "172.21.51.143:5000/myblog"
DINGTALK_CREDS = credentials('dingTalk')
}
stages {
stage('printenv') {
steps {
echo 'Hello World'
sh 'printenv'
}
}
stage('check') {
steps {
checkout scm
}
}
stage('build-image') {
steps {
retry(2) { sh 'docker build . -t ${IMAGE_REPO}:${GIT_COMMIT}'}
}
}
stage('push-image') {
steps {
retry(2) { sh 'docker push ${IMAGE_REPO}:${GIT_COMMIT}'}
}
}
stage('deploy') {
steps {
sh "sed -i 's#{{IMAGE_URL}}#${IMAGE_REPO}:${GIT_COMMIT}#g' manifests/*"
timeout(time: 1, unit: 'MINUTES') {
sh "kubectl apply -f manifests/"
}
}
}
}
post {
success {
echo 'Congratulations!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{"msgtype": "text",
"text": {
"content": "????構(gòu)建成功????\n 關(guān)鍵字:luffy\n 項目名稱: ${JOB_BASE_NAME}\n Commit Id: ${GIT_COMMIT}\n 構(gòu)建地址:${RUN_DISPLAY_URL}"
}
}'
"""
}
failure {
echo 'Oh no!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{"msgtype": "text",
"text": {
"content": "???構(gòu)建失敗???\n 關(guān)鍵字:luffy\n 項目名稱: ${JOB_BASE_NAME}\n Commit Id: ${GIT_COMMIT}\n 構(gòu)建地址:${RUN_DISPLAY_URL}"
}
}'
"""
}
always {
echo 'I will always say Hello again!'
}
}
}
?? 總結(jié)
上面我們已經(jīng)通過 Jenkinsfile 完成了最簡單的項目的構(gòu)建和部署,那么我們來思考目前的方式:
目前都是在項目的單一分支下進(jìn)行操作,企業(yè)內(nèi)一般會使用 feature、develop、release、master 等多個分支來管理整個代碼提交流程,如何根據(jù)不同的分支來做構(gòu)建?
構(gòu)建視圖中如何區(qū)分不同的分支?
如何不配置 webhook 的方式實現(xiàn)構(gòu)建?
如何根據(jù)不同的分支選擇發(fā)布到不同的環(huán)境(開發(fā)、測試、生產(chǎn))?
3. 多分支流水線實踐
官方示例
我們簡化一下流程,假如使用 develop 分支作為開發(fā)分支,master 分支作為集成測試分支,看一下如何使用多分支流水線來管理。
?? 演示一
演示1:多分支流水線的使用
(1)提交develop分支:
$ git checkout -b develop
$ git push --set-upstream origin develop
(2)禁用 pipeline 項目
(3)Jenkins 端創(chuàng)建多分支流水線項目
- 增加 git 分支源
- 發(fā)現(xiàn)標(biāo)簽
- 根據(jù)名稱過濾,
develop|master|v.*
- 高級克隆,設(shè)置淺克隆
保存后,會自動檢索項目中所有存在 Jenkinsfile 文件的分支和標(biāo)簽,若匹配我們設(shè)置的過濾正則表達(dá)式,則會添加到多分支的構(gòu)建視圖中。所有添加到視圖中的分支和標(biāo)簽,會默認(rèn)執(zhí)行一次構(gòu)建任務(wù)。
?? 演示二
演示2:美化消息通知內(nèi)容
- 添加構(gòu)建階段記錄
- 使用 markdown 格式,添加構(gòu)建分支消息
jenkins/pipelines/p6.yaml
pipeline {
agent { label '172.21.51.68'}
environment {
IMAGE_REPO = "172.21.51.143:5000/myblog"
DINGTALK_CREDS = credentials('dingTalk')
TAB_STR = "\n \n "
}
stages {
stage('printenv') {
steps {
script{
sh "git log --oneline -n 1 > gitlog.file"
env.GIT_LOG = readFile("gitlog.file").trim()
}
sh 'printenv'
}
}
stage('checkout') {
steps {
checkout scm
script{
env.BUILD_TASKS = env.STAGE_NAME + "√..." + env.TAB_STR
}
}
}
stage('build-image') {
steps {
retry(2) { sh 'docker build . -t ${IMAGE_REPO}:${GIT_COMMIT}'}
script{
env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
}
}
}
stage('push-image') {
steps {
retry(2) { sh 'docker push ${IMAGE_REPO}:${GIT_COMMIT}'}
script{
env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
}
}
}
stage('deploy') {
steps {
sh "sed -i 's#{{IMAGE_URL}}#${IMAGE_REPO}:${GIT_COMMIT}#g' manifests/*"
timeout(time: 1, unit: 'MINUTES') {
sh "kubectl apply -f manifests/"
}
script{
env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
}
}
}
}
post {
success {
echo 'Congratulations!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "markdown",
"markdown": {
"title":"myblog",
"text": "???? 構(gòu)建成功 ???? \n**項目名稱**:luffy \n**Git log**: ${GIT_LOG} \n**構(gòu)建分支**: ${GIT_BRANCH} \n**構(gòu)建地址**:${RUN_DISPLAY_URL} \n**構(gòu)建任務(wù)**:${BUILD_TASKS}"
}
}'
"""
}
failure {
echo 'Oh no!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "markdown",
"markdown": {
"title":"myblog",
"text": "??? 構(gòu)建失敗 ??? \n**項目名稱**:luffy \n**Git log**: ${GIT_LOG} \n**構(gòu)建分支**: ${GIT_BRANCH} \n**構(gòu)建地址**:${RUN_DISPLAY_URL} \n**構(gòu)建任務(wù)**:${BUILD_TASKS}"
}
}'
"""
}
always {
echo 'I will always say Hello again!'
}
}
}
?? 演示三
演示3:通知 gitlab 構(gòu)建狀態(tài)
Jenkins 端做了構(gòu)建,可以通過 gitlab 通過的 api 將構(gòu)建狀態(tài)通知過去,作為開發(fā)人員發(fā)起 Merge Request 或者合并 Merge Request 的依據(jù)之一。
注意一定要指定 gitLabConnection('gitlab')
,不然沒法認(rèn)證到 Gitlab 端
jenkins/pipelines/p7.yaml
pipeline {
agent { label '172.21.51.68'}
options {
buildDiscarder(logRotator(numToKeepStr: '10'))
disableConcurrentBuilds()
timeout(time: 20, unit: 'MINUTES')
gitLabConnection('gitlab')
}
environment {
IMAGE_REPO = "172.21.51.143:5000/demo/myblog"
DINGTALK_CREDS = credentials('dingTalk')
TAB_STR = "\n \n "
}
stages {
stage('printenv') {
steps {
script{
sh "git log --oneline -n 1 > gitlog.file"
env.GIT_LOG = readFile("gitlog.file").trim()
}
sh 'printenv'
}
}
stage('checkout') {
steps {
checkout scm
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script{
env.BUILD_TASKS = env.STAGE_NAME + "√..." + env.TAB_STR
}
}
}
stage('build-image') {
steps {
retry(2) { sh 'docker build . -t ${IMAGE_REPO}:${GIT_COMMIT}'}
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script{
env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
}
}
}
stage('push-image') {
steps {
retry(2) { sh 'docker push ${IMAGE_REPO}:${GIT_COMMIT}'}
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script{
env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
}
}
}
stage('deploy') {
steps {
sh "sed -i 's#{{IMAGE_URL}}#${IMAGE_REPO}:${GIT_COMMIT}#g' manifests/*"
timeout(time: 1, unit: 'MINUTES') {
sh "kubectl apply -f manifests/"
}
updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
script{
env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
}
}
}
}
post {
success {
echo 'Congratulations!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "markdown",
"markdown": {
"title":"myblog",
"text": "???? 構(gòu)建成功 ???? \n**項目名稱**:luffy \n**Git log**: ${GIT_LOG} \n**構(gòu)建分支**: ${BRANCH_NAME} \n**構(gòu)建地址**:${RUN_DISPLAY_URL} \n**構(gòu)建任務(wù)**:${BUILD_TASKS}"
}
}'
"""
}
failure {
echo 'Oh no!'
sh """
curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
-H 'Content-Type: application/json' \
-d '{
"msgtype": "markdown",
"markdown": {
"title":"myblog",
"text": "??? 構(gòu)建失敗 ??? \n**項目名稱**:luffy \n**Git log**: ${GIT_LOG} \n**構(gòu)建分支**: ${BRANCH_NAME} \n**構(gòu)建地址**:${RUN_DISPLAY_URL} \n**構(gòu)建任務(wù)**:${BUILD_TASKS}"
}
}'
"""
}
always {
echo 'I will always say Hello again!'
}
}
}
我們可以訪問 gitlab,然后找到 commit 記錄,查看同步狀態(tài):
提交 merge request,也可以查看到相關(guān)的任務(wù)狀態(tài),可以作為項目 owner 合并代碼的依據(jù)之一:
?? 總結(jié)
優(yōu)勢:文章來源:http://www.zghlxwxcb.cn/news/detail-785754.html
- 根據(jù)分支展示,視圖人性化
- 自動檢測各分支的變更
思考:
- Jenkins 的 slave 端,沒有任務(wù)的時候處于閑置狀態(tài),slave 節(jié)點多的話造成資源浪費
- 是否可以利用 kubernetes 的 Pod 來啟動 slave,動態(tài) slave pod 來執(zhí)行構(gòu)建任務(wù)
到了這里,關(guān)于基于K8s的DevOps平臺實踐(二)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!