【DevOps實踐】3. Jenkins流水線搭建golang項目持續(xù)集成環(huán)境

1. 摘要

Jenkins是一個自動化服務(wù)器,目前發(fā)展超過15年耐薯,比較成熟的CI工具(也可以CD)能夠?qū)崿F(xiàn)自動化集成發(fā)布灶泵。
Jenkins構(gòu)件任務(wù)一般有2種,一種是“構(gòu)建一個自由風(fēng)格的軟件項目”和“流水線”項目羊精。本文講解的是使用pipeline流水線搭建一個GO工程的持續(xù)集成任務(wù)的完整方法。

2. 實踐內(nèi)容

2.1 pipeline流水線簡介

本質(zhì)上囚玫,jenkins是一個自動化引擎喧锦,它支持許多自動模式。流水線向Jenkins添加了一組強大的工具抓督,支持用例燃少、簡單的持續(xù)集成到全面的持續(xù)交付流水線。 通過對一系列的發(fā)布任務(wù)建立標(biāo)準(zhǔn)的模板铃在,用戶可以利用更多流水線的特性阵具,比如:

代碼化: 流水線是在代碼中實現(xiàn)的,通常會存放到源代碼控制定铜,使團隊具有編輯怔昨、審查和更新他們項目的交付流水線的能力。

耐用性:流水線可以從Jenkins的master節(jié)點重啟后繼續(xù)運行宿稀。

可暫停的:流水線可以由人功輸入或批準(zhǔn)繼續(xù)執(zhí)行流水線趁舀。

解決復(fù)雜發(fā)布: 支持復(fù)雜的交付流程。例如循環(huán)祝沸、并行執(zhí)行矮烹。

可擴展性: 支持?jǐn)U展DSL和其他插件集成。

構(gòu)建一個可擴展是Jenkins的核心價值罩锐,流水線可以通過ShareLibrary的方式來擴展奉狈。

2.2 Jenkins環(huán)境準(zhǔn)備

2.2.1 配置Jenkins的SSH key

由于jenkins需要從gitlab上拉取代碼,通過ssh方式涩惑。所以需要在jenkins機器上安裝git仁期,并且將jenkins機器上生成的ssh密鑰的公鑰(id_rsa.pub中的內(nèi)容)添加到gitlab的ssh keys中。

配置username和Email竭恬,生成ssh密鑰

git config --global user.name "duncan.wang"
git config --global user.email "duncan.wang@artarva.com"
ssh-keygen -t rsa  -C "duncan.wang@artarva.com"

拷貝公鑰內(nèi)容填到gitlab服務(wù)器跛蛋。

2.2.2 配置GitLab connections

(1)配置GitLab connections連接到gitlab拉取代碼使用,配置證書痊硕,使用gitlab api token赊级。
token從gitlab中獲取,在個人設(shè)置中有Access Token一欄岔绸,創(chuàng)建一個token理逊。

(2)在jenkins的系統(tǒng)管理/憑據(jù)管理(manageCredentials)/全局憑證/添加憑證橡伞,如下:
把gitlab創(chuàng)建的Feed token填寫到API token的位置,描述增加點說明晋被,例如"GITLAB的授權(quán)信息"兑徘,ID不用設(shè)置,會被Jenkins系統(tǒng)自動更新出來羡洛。

(3)在Jenkins的系統(tǒng)管理處配置gitlab授權(quán)配置
授權(quán)憑證選擇剛才配置的GitLab API token即可挂脑。可以點擊“Test Connection”翘县,返回顯示為"Success"表示連接成功。

Test Connection谴分,顯示success則表示配置成功锈麸。

(4)配置Jenkins所在服務(wù)器拉取代碼的服務(wù)器私鑰訪問憑證
該憑證用于在下面章節(jié)的流水線配置拉取代碼時以私鑰訪問憑證形式訪問目標(biāo)環(huán)境。此處的私鑰“Private Key”為“2.2.1 配置Jenkins的SSH key”產(chǎn)生的rsa_privatekey牺蹄。

2.2.3 配置管道任務(wù)梳理

丟棄舊的構(gòu)建配置為只保留7天忘伞,10個構(gòu)建版本。


2.3 創(chuàng)建流水線任務(wù)

(1)輸入命名“preproduct-training-ip-demo”沙兰,選擇流水線風(fēng)格氓奈。


(2)配置Gitlab連接
選擇 2.2.2 配置GitLab connections 配置的“artarva”連接。


(3)設(shè)置流水線腳本

#!/usr/bin/env groovy

def git_address = "git@101.132.137.193:trainingipmanagement/training-ip-demo.git"
def git_auth = "10a4d4f3-1977-486c-945f-31cfcd8c04db"
def git_branch = "dev"


pipeline {
    agent { node { label "master"}}

    stages {
        stage('1.拉取代碼'){
            steps {
             //checkout([$class: 'GitSCM', branches: [[name: '${Branch}']], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]])
                 git  branch: "${git_branch}", credentialsId: "${git_auth}", url: "${git_address}"
                     // }
            }
        }


        stage('3.編譯程序'){
            steps {
                sh """  
                    export GOPATH=/opt/GOPATH
                    export PATH=$PATH:\$GOPATH/bin
                    go build -o training-ip-demo main.go
            cp training-ip-demo /home/training-ip-management/training-ip-demo       
                """   
            }      
        }  
        
        stage('4.部署程序'){
            steps {
                script{
                    PROCESS_ID = sh(script: "ps aux|grep training-ip|grep -v grep|grep -v jenkins|awk \'{print \$2}\'", returnStdout: true).trim()
                    echo "${PROCESS_ID}"

                    if (PROCESS_ID != "") {
                        sh """
                             echo "Kill process: ${PROCESS_ID}"
                             sudo kill -9 ${PROCESS_ID}
                            """
                    }
                }

                sh """
                JENKINS_NODE_COOKIE=dontKillMe nohup /home/training-ip-management/training-ip-demo/training-ip-demo & 
                """
            }  
        }
    }

    post {
        always{
            script{
                println("流水線結(jié)束后鼎天,經(jīng)常做的事情")
            }
        }
            
        success{
            script{
                println("流水線成功后舀奶,要做的事情")
            }
            
        }
        failure{
            script{
                println("流水線失敗后,要做的事情")
            }
        }
            
        aborted{
            script{
                println("流水線取消后斋射,要做的事情")
            }
            
        }
    }
}

(4) 立即構(gòu)建
點擊“立即構(gòu)建”育勺,根據(jù)輸出結(jié)果排查問題后即可完成流水線工作,包含
拉取Gitlab版本罗岖,編輯代碼涧至,部署程序這3個主要步驟。
本樣例暫時不包含2.代碼靜態(tài)檢查的步驟桑包,后面其他文章再涉及南蓬。

截圖.png

2.4 典型問題解答

2.4.1 流水線配置的程序后臺部署運行正常后即被關(guān)閉

問題現(xiàn)象:
在普通的shell環(huán)境中,nohup哑了,并且& 某個程序后赘方,會拋到后臺執(zhí)行,在退出當(dāng)前shell環(huán)境后弱左,程序依然可以執(zhí)行蒜焊。但是在Jenkins的pipeline中,通過nohup科贬,且使用&之后泳梆,step結(jié)束后鳖悠,執(zhí)行的程序還是會退出,導(dǎo)致程序起不來优妙。

在pipeline中需要使用修改 JENKINS_NODE_COOKIE 的值來解決問題乘综,這樣后續(xù)結(jié)束的時候,后面的sh程序就不會被kill掉了套硼。
例如代碼:

        stage('4.部署程序'){
            steps {
                script{
                    PROCESS_ID = sh(script: "ps aux|grep training-ip|grep -v grep|grep -v jenkins|awk \'{print \$2}\'", returnStdout: true).trim()
                    echo "${PROCESS_ID}"

                    if (PROCESS_ID != "") {
                        sh """
                             echo "Kill process: ${PROCESS_ID}"
                             sudo kill -9 ${PROCESS_ID}
                            """
                    }
                }

                sh """
                JENKINS_NODE_COOKIE=dontKillMe nohup /home/training-ip-management/training-ip-demo/training-ip-demo & 
                """
            }  
        }

2.4.2 GO編譯命令不認識

問題現(xiàn)象:
Jenkins有如下輸出卡辰,表示go 命令找不到。

[Pipeline] { (3.編譯程序)[](https://jenkins.artarva.com/job/preproduct-training-ip-demo/5/console#) [Pipeline] sh[](https://jenkins.artarva.com/job/preproduct-training-ip-demo/5/console#) + export GOPATH=/opt/GOPATH
+ GOPATH=/opt/GOPATH
+ export PATH=/usr/local/bin:/usr/local/java/jdk1.8.0_212//bin:/usr/local/java/jdk1.8.0_212//jre/bin:/usr/local/mycat/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/GOPATH/bin
+ PATH=/usr/local/bin:/usr/local/java/jdk1.8.0_212//bin:/usr/local/java/jdk1.8.0_212//jre/bin:/usr/local/mycat/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/GOPATH/bin
+ go build -o training-ip-demo main.go
/var/lib/jenkins/workspace/preproduct-training-ip-demo@tmp/durable-86459043/script.sh: line 4: go: command not found</pre>

運行的對應(yīng)流水線腳本為:

        stage('3.編譯程序'){
            steps {
                sh """  
                    export GOPATH=/opt/GOPATH
                    export PATH=$PATH:\$GOPATH/bin
                    go build -o training-ip-demo main.go
            sudo cp training-ip-demo /home/training-ip-management/training-ip-demo       
                """   
            }      
        } 

問題分析:
JENKINS下邪意,默認采用Jenkins賬號運行九妈。該賬號下的PATH并沒有包含GO的環(huán)境,上面腳本的路徑也寫錯了雾鬼。改為如下即可成功運行萌朱。
運行成功的對應(yīng)流水線腳本為:

        stage('3.編譯程序'){
            steps {
                sh """  
                    export GOROOT=/opt/module/go
                    export PATH=$PATH:\$GOROOT/bin
                    go build -o training-ip-demo main.go
            sudo cp training-ip-demo /home/training-ip-management/training-ip-demo       
                """   
            }      
        } 

關(guān)于Jenkins pipeline單引號憋他、雙引號和轉(zhuǎn)義字符的說明參考 https://blog.csdn.net/nklinsirui/article/details/100539935 這篇文章于置。

3.參考

(1)Jenkins持續(xù)集成Go項目
https://www.pianshen.com/article/8603599995/

(2)Jenkins流水線(pipeline)實戰(zhàn)之:golang項目
https://blog.csdn.net/qq_36270681/article/details/105449608
【說明】
[1]安裝插件,按照次更新了鏡像
jenkins Publish over SSH 的配置與使用
https://www.cnblogs.com/yechen2019/p/11529755.html
[2] 流水線失敗吧恃,不用又憨。
[3] GIT相關(guān)命令
https://www.jenkins.io/doc/pipeline/steps/git/
[4] SHELL相關(guān)命令
https://www.jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script
[5] jenkins全局變量
https://wiki.jenkins.io/display/JENKINS/Building+a+software+project#Buildingasoftwareproject-JenkinsSetEnvironmentVariables
https://jenkins.artarva.com/env-vars.html/
[6]官方groovy語法
http://docs.groovy-lang.org/latest/html/documentation/core-operators.html#_conditional_operators

(3)使用Docker+Jenkins實現(xiàn)Go語言項目的持續(xù)集成
https://juejin.cn/post/6844904152829542413
【說明】自由風(fēng)格構(gòu)件成功GO項目翠霍,不是流水線

(4)使用Docker+Jenkins實現(xiàn)Go語言項目的持續(xù)集成
https://juejin.cn/post/6844904152829542413
【說明】自由風(fēng)格構(gòu)件成功GO項目,不是流水線

(5)搭建jenkins+gitlab持續(xù)集成環(huán)境
https://jingyan.baidu.com/article/5552ef47fbb9b3518ffbc983.html
【說明】構(gòu)建項目部分未使用蠢莺。

(6)Jenkins集成Gitlab配置提交流水線
https://blog.csdn.net/valada/article/details/104272152

(7)基于GitLab CI搭建Golang自動構(gòu)建環(huán)境
https://segmentfault.com/a/1190000019525332
【說明】將直接在GitLab上部署自動化構(gòu)件環(huán)境的寒匙。

(8)Jenkins中使用GitLab的配置
https://www.cnblogs.com/gongxr/p/9257434.html

(9)JENKINS插件查詢的地方
https://plugins.jenkins.io/
https://blog.csdn.net/valada/article/details/104272154

(10)Jenkins中pipeline后臺進程起不來的問題
https://shanhy.blog.csdn.net/article/details/79637311
【說明】有效,采用JENKINS_NODE_COOKIE=dontKillMe解決躏将。

(11)Jenkins pipeline中優(yōu)雅的執(zhí)行shell/python/groovy腳本
http://www.reibang.com/p/2cdc8efedf2f

(12)Jenkins pipeline單引號蒋情、雙引號和轉(zhuǎn)義字符
https://blog.csdn.net/nklinsirui/article/details/100539935

(13)Jenkins實踐
http://www.idevops.site/jenkins/

(14)版本控制系統(tǒng)集成
http://www.idevops.site/jenkins/pipelineintegrated/chapter03/

(15)Groovy 語法教程
https://www.w3cschool.cn/groovy/
【說明】
<1> DEF 是在 Groovy 用來定義標(biāo)識符的關(guān)鍵字。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末耸携,一起剝皮案震驚了整個濱河市棵癣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌夺衍,老刑警劉巖狈谊,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異沟沙,居然都是意外死亡河劝,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門矛紫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赎瞎,“玉大人,你說我怎么就攤上這事颊咬∥裆” “怎么了牡辽?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長敞临。 經(jīng)常有香客問我态辛,道長,這世上最難降的妖魔是什么挺尿? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任奏黑,我火速辦了婚禮,結(jié)果婚禮上编矾,老公的妹妹穿的比我還像新娘熟史。我一直安慰自己,他們只是感情好窄俏,可當(dāng)我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布蹂匹。 她就那樣靜靜地躺著,像睡著了一般裆操。 火紅的嫁衣襯著肌膚如雪怒详。 梳的紋絲不亂的頭發(fā)上炉媒,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天踪区,我揣著相機與錄音,去河邊找鬼吊骤。 笑死缎岗,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的白粉。 我是一名探鬼主播传泊,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼鸭巴!你這毒婦竟也來了眷细?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤鹃祖,失蹤者是張志新(化名)和其女友劉穎溪椎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恬口,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡校读,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了祖能。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歉秫。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖养铸,靈堂內(nèi)的尸體忽然破棺而出雁芙,到底是詐尸還是另有隱情轧膘,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布却特,位于F島的核電站扶供,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏裂明。R本人自食惡果不足惜椿浓,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闽晦。 院中可真熱鬧扳碍,春花似錦、人聲如沸仙蛉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荠瘪。三九已至夯巷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間哀墓,已是汗流浹背趁餐。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留篮绰,地道東北人后雷。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像吠各,于是被迫代替她去往敵國和親臀突。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容