《基于Docker的Jenkins持續交付實踐》要點:
本文介紹了基于Docker的Jenkins持續交付實踐,希望對您有用。如果有疑問,可以聯系我們。
講師介紹:葉峰
有容云資深前端開發工程師
主題簡介:
1.Jenkins pipeline基礎概念
2.Jenkins pipeline如何帶來工作便利
3.基于容器的Jenkins CI流程
4.Jenkins、Docker、Kubernetes整合的集成部署
傳統我們的項目開發模式是產品調研提出需求,開發團隊研究決定開發方案選型.然后開始一個周期的開發,模塊開發完成之后開始模塊間的聯調.聯調結束之后打包交付給測試團隊.測試團隊,系統測試或自動化測試,然后提交bug,開發團隊修復bug,周而復始.傳統的模式中,存在著較多的不確定因素.例如,開發環境、編譯環境、測試環境、生產環境,等不確定因素.人為介入打包中的不確定因素,缺乏單元測試和自動化測試的整合.從而導致的結果是,開發-測試-修復的周期較長,而且很多小的問題完全可以由單元測試進行覆蓋.
持續交付并不是某個特定的軟件,而是一個結果.這個結果要求團隊可以隨時的發布一個新的準確版本,而且要求在編譯發布的過程中進行自動化測試,通過自動化測試可以及時地發現并定位存在的bug,修復bug之后再進行快速的發布到測試環境,測試團隊直接進行測試.與傳統模式的區別在于持續交付可以提前發現bug的存在和快速修復而不必等到測試人員的介入之后才發現.持續交付分解出來就是“持續”和“交付”.
持續:持續要求任何時,候任何情況都能進行準確的發布,做到準確的發布需要注意以下幾個關鍵點.
1.持續應該是一個周期性的,可以是每天的某個時間點,也可以是某次代碼的提交,或者某次人為觸發.所以人工進行構建是不可能的,需要自動化的構建,自動化要求構建的任何一個流程都必須以腳本的形式運行,代碼檢出、代碼構建、各模塊代碼單元測試、集成測試、UI自動化測試等.
2.發布的程序版本不允許是各個模塊在開發環境編譯出一個版本作為交付,而要求在一個純凈的編譯環境中進行構建.
3.構建的過程應該要求最大可能的固化,例如操作系統的版本,構建環境的版本,相關的依賴等.
4.避免從網絡獲取相關的文件,這點以nodejs為開發或編譯的項目尤其重要,安裝node的依賴包總是一個漫長的過程,就算有國內的源,一般的項目也需要一兩分鐘的node依賴包,這不符合快速構建.
交付 :?在持續編譯的過程,使用自動化已經可以避免大多數的錯誤了.但是還是需要人為介入的系統測試,畢竟自動化的測試一般只能覆蓋到70%左右.
根據我們團隊內部推廣這種工作方式的效果來看,持續集成確實讓我們工作便利了許多, 每次代碼的構建和自動化測試讓我們及時發現存在的bug.好的工作模式也需要團隊成員的遵守,團隊成員應該積極的擁抱這種工作方式,團隊成員需要做好以下幾點.
1.使用版本工具例如git.git有強大的版本回溯,成員每次完成一個小的功能點進行代碼提交.合并到master分支,持續交付工具應該配置為代碼更新觸發.團隊內部應該等到持續交付流程結束之后,確認編譯、自動化測試通過之后方可進行下一個版本的提交,這樣容易定位bug.而不會導致這次bug影響團隊內其他成員的工作.
2.主分支的代碼bug不應該存留時間過長,避免團隊內其他成員合并代碼的時候引入其他問題.
3.測試驅動開發,任何一個新的功能開發都應該先寫好單元測試腳本,并積極更新自動化測試腳本.并且積極地擁抱測試,雖然你明白這個測試不通過的問題并不會引起很大的系統性問題 ,但是還是應該進行修復而不是想方設法的跳過這個自動化測試.
4.臨近下班的時候不要提交代碼,這主要是因為遵守第2點.
Docker已經越來越火,CICD和Devops也是Docker一個重要的場景.在持續交付中使用Docker有一下優點.
在持續集成方面,我們選擇Jenkins.Jenkins是一款開源軟件,擁有眾多優秀的插件,依靠這些插件,我們可以完成一些周期、繁瑣、復雜的任務.例如我們今天分享的持續發布,雖然Jenkins解決了我們繁瑣復雜周期性的操作,但是沒有解決我們在多種環境下編譯構建的需求.而這個場景正是Docker的強項.通過Jenkins的pipeline我們可以實現代碼檢出、單元測試、編譯、構建、發布、測試等流程的自動化,而最終通過Jenkins的Docker插件將產出物構建成鏡像,方便部署到Docker環境.
持續集成讓我們新的代碼源源不斷的構建成了鏡像,這些鏡像經歷了單元測試,自動化測試,但還沒有接受過測試團隊的嚴格測試.Jenkins是一個強大的持續集成工具,然而持續部署并不是Jenkins的強項,但是Jenkins擁有很多強大的插件.而且我們持續集成產出的是鏡像,所以持續的部署,我們只需要將鏡像運行起來,或者利用第三方的容器管理平臺提供的API進行部署.
1.本地部署應用到Docker.
本地部署到Docker容器可以使用Jenkins的docker插件,下面會介紹.
2.部署到遠程主機的Docker、Appsoar.
Docker和Appsoar都支持開啟API調用.通過現有的API我們可以運行我們生成鏡像版本.從而達到持續的部署最新版本.
3.部署到kubernetes.
kubernetes除了可以通過API調用還可以在jenkins中配置kubectl的方式創建或更新deployments.
Docker部署Jenkins的方式簡單方便,下面我們介紹用Docker的方式運行Jenkins.
解鎖的密碼在容器的log中可以查看,或者直接查看jenkins_home指定文件
下面我們創建一個的Jenkins的Pipeline完成簡單的cicd流程.
以下是偽代碼,僅提供思路
Jenkins pipeline的腳本語法是groovy的語法,其中docker 、Git是插件提供的能力.代碼的執行流程如下:
通過簡單的例子,可見Jenkins和Docker的結合給CICD帶來了足夠的便利和強大.我們需要準備的只是一個編譯的腳本,在編譯腳本中可以使用任何的環境和任何的版本.
Jenkins的任務兩個主要版本.
free style只是一個自動化的腳本,腳本類型為shell.所有的腳本在一臺機器上運行,需要的環境需要提前準備.配置不集中,混亂.但是一般情況下還是夠用的.
pipeline 是jenkins2的版本使用了一個基于groovy腳本的任務類型,通過一系列的stage將構建的不同部分組合成一個pipline.而且配合step可以完成異步操作.因為基于groovy可編程性更加強大,而且腳本可以存放在源碼中,腳本的更改不需要直接到jenkins中修改.
1.Jenkins的資料較少,官網可以查看的內容也不多,一般的需求Jenkins內置的pipeline-syntax里面就有常用的命令生成器.可以滿足大多數需求.
2.在pipeline腳本調試完成之后應該將腳本以文件的形式放在源碼目錄中,這樣子方便修改.和多分支需要編譯的情況下進行互相隔離.
3.應該多查找下相應的插件,而不是使用sh用執行腳本的方式來解決問題.
4.應該將jenkins_home目錄掛在出來,如果遇上了Jenkins崩潰了可以及時的恢復數據.
5.應該新建一個定時的pipeline用來清理生成的鏡像,減少硬盤資源的占用.
6.頁面新建的pipeline,在頁面刪除之后,jenkins_home/workspace中對應的項目文件并不會被刪除.
持續發布很多團隊想有這樣的工具達到這個效果,有些團隊覺得不需要.任何工具、流程都需要符合自身團隊的實際.從我開始參與團隊內的這個和持續發布有關的項目,查看了許多資料,結合團隊項目內的實踐.給出的一些經驗的和見解和大家一起分享,如有錯誤或者建議,歡迎大家及時溝通.
Q&A
Q1:請問Kubernetes怎么結合Jenkins做持續集成呢?
A1:部署到Kubernetes.Kubernetes除了可以通過API調用還可以在Jenkins中配置kubectl的方式創建或更新deployments.
Q2:必須通過pipeline才能實現Jenkins把代碼構建成Docker鏡像么?
A2:不一定,使用Docker主要是方便進行編譯環境的隔離,也可以配置好NFS,構建完成之后復制到固定的服務器上,這個我們一般叫制品庫.
Q3:Pipeline如何通過Docker容器部署應用到不同的節點上去?發布遇到問題如何回滾版本的?
A3:Jenkins的能力更多的是做持續集成(CI)的功能,部署和回滾都需要容器管理平臺并不是Jenkins的強項,特別是回滾單依靠Jenkins很難做到完美的方案.但是部署到不同的Docker的節點上,可以使用第三方的管理平臺,例如Appsoar和k8s提供的API能力,可以進行部署.Jenkins直接調用curl命令執行容器管理平臺提供的API.
Q4:pipeline的每個環節的報告如何快速獲取?比如代碼靜態檢查,工程構建,測試報告等等.
A4:?http://jenkins:8080/job/clearImages/86/wfapi/,通過Jenkins這個API,可以獲取一些狀態和時間信息,至于詳細的代碼靜態檢查,每種語言都有不同的語法檢查.需要自行配置.當然詳細的需要查看輸出日志.
Q5:關于測試驅動開發,在開發之前寫好的用例一定要是自動化的嗎?為什么?
A5:一個系統由若干的方法組成,單元測試就是測試你寫的方法是否符合你的業務要求.所以先寫合理的單元測試,只要你的方法通過了這個單元測試就表示你寫的這個方法是正確的,單元測試代碼是需要開發人員編寫的,每種語言有不同的單元測試框架例如Nodejs的mocha,Golang 的go test.自動化測試由測試人員編寫.單元測試應該需要脫離外部因素,不依賴數據庫、不依賴外部API.
Q6:怎么觸發工作流的?
A6:Jenkins pipeline 提供了三種方式(如果安裝了SCM的插件可能有其他的方式觸發),進入到pipeline的設置頁面中的分別有.wbhook(觸發遠程構建 (例如,使用腳本))、定時觸發(Build periodically)、代碼更新觸發(Poll SCM).
Q8:Jenkins的編譯環境是怎么處理的,實際用戶的編譯需求和環境都不一樣?
A8:用戶需要清楚你使用的編譯環境的基本情況,例如golang的編譯環境,容器中的GOPATH是在什么位置.你需要將你的代碼ln到什么目錄才能進行編譯,等這些細節都是需要用戶提前知曉.
Q9:Jenkins里的有用戶權限管理嗎,貴公司的CI/CD是怎么實現用戶隔離的,每個用戶只能看到自己的項目.
A9:Jenkins當中并沒有用戶權限.公司在研發的產品中,有一個虛擬的概念叫用戶組,對應的是k8s中的一個或多個namespaces.管理員將成員用戶添加到這個用戶組中,組內成員創建的資源(pipeline、集群、服務,等)在組內是可見,用戶組來進行邏輯概念上的隔離
Q10:貴公司Jenkins和Kubernetes是怎么結合使用的?是什么的部署形式?如何回滾?
A10:我看到很多朋友都提問了,Jenkins如何跨主機部署或者如何部署到Kubernetes集群,如何回滾.Jenkins對這方面的能力比較弱,僅僅能夠支持kube-api-server的調用而已,如果完全依靠Jenkins是很難完成需求,所以我們的產品當中有一個專門對接kubernetes的deploy的模塊,一個應用商店的模塊,一個封裝了Jenkins的uflow模塊,uflow模塊向應用商店獲取模板并根據當前編譯構建出來的鏡像tag號替換模板,并交付給deploy模塊創建.回滾和升級都由deploy模塊負責.這樣各自分開,各司其職.
Q11:多個PHP項目,在Docker 應用中,需要逐個拆分嗎?一個項目對應一個鏡像管理?還是使用文件夾映射的方式構建鏡像?
A11:多個項目服務是放在一個容器中還是分開容器中,這個并沒有強制的限定.但是建議還是分為多個容器進行部署.Docker的理念就是一個容器完成一個單獨的事情.
Q12:Jenkins PIpeline input指令可以復雜的參數化么?
A12:input是一個比較強大的指令,可以在pipeline的運行過程中確認操作,字符輸入,文件上傳等功能.詳細的可以看下jenkins的pipeline-syntax有使用說明和腳本的生成.
Q13:Jenkins自動觸發job到build docker image,自動觸發是怎么實現的,wedhook 定時觸發有沒遇到過問題?不能正常觸發的?
A13:自動觸發的原理的原理是,我們在pipeline中配置一個定時器,這個定時器是用cron表達式表示.例如你設置了 “* * * * * ”就表示每分鐘檢查一次,那么檢查什么呢,檢查每次提交的ID,例如git的commit ID .只要檢測到了這個ID和上一次的不一致就會觸發pipeline的構建.從目前使用并沒有出現過不能觸發的情況.如果出現了請檢查是否是配置的錯誤.
Q14:CD過程中,重造的輪子和開源組件是一個什么樣的比例?個人推崇哪個?
A14:自己重復造輪子和開源組件應該如何選擇,這個是很有意思的一個問題.因為開發者都說不要重復造輪子,這是因為很多輪子經過了很多項目考驗和眾多開發者提交代碼和fix的bug.這些項目肯定是比自己從頭開始造一個輪子更加有效率而且使用風險低,畢竟所有人都想完成工作上的任務早點下班.但從個人發展來說,有些輪子還是值得自己去制造一次的,這樣子你才會了解到這個組件的工作原理、底層的東西.所以我個人的推崇的是,假如你找到了合適接近完美的輪子那就直接用,如果找到了一個可用但總覺得用起來不太爽的組件,那你就把輪子造起來吧.
文章來自微信公眾號:DBAplus社群
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/4190.html