作者:?jihong10102006
高效可靠的CI/CD流水線是一個(gè)IT組織實(shí)現(xiàn)軟件服務(wù)快速交付的基礎(chǔ),現(xiàn)如今大量企業(yè)采用jenkins集群來(lái)搭建其交付流水線。然而,如何管理大量Jenkins Slave的差異化?如何簡(jiǎn)單快速實(shí)現(xiàn)Jenkins能力的橫向擴(kuò)展?如何實(shí)現(xiàn)流水線的高可用?如何有效利用閑置的Jenkins Slave資源?上述這些問(wèn)題一直困攏著集群管理員,近兩年隨著虛擬化技術(shù)突飛猛進(jìn)的發(fā)展,Docker, Kubernetes 等現(xiàn)代化工具徹底顛覆了交付團(tuán)隊(duì)的交付流程,同時(shí)也為CI/CD流程水線的搭建與管理提供了全新思路。
Setup
目前流行的CI工具很多,鑒于本文討論CI/CD流水線在企業(yè)中的應(yīng)用,考慮到企業(yè)不會(huì)有意愿將源代碼的訪問(wèn)權(quán)開(kāi)放給第三方,像Travis CI等這些基于SaaS的CI工具自然被pass,由于Jenkins在CI領(lǐng)域的主導(dǎo)性地位,所以本文的CI工具只涉及Jenkins。另外,本文默認(rèn)您對(duì)Jenkins, Docker, Kubernetes 等工具有一些基礎(chǔ)的了解。
持續(xù)交付流水線簡(jiǎn)介
簡(jiǎn)單介紹一下持續(xù)交付流水線,如下圖所示,簡(jiǎn)單來(lái)說(shuō)流水線工作流程是這樣的,當(dāng)代碼庫(kù)有代碼變更的時(shí)候持續(xù)集成服務(wù)器(Jenkins)會(huì)監(jiān)聽(tīng)到代碼變更并自動(dòng)觸發(fā)第一個(gè)階段 — 持續(xù)集成階段,這個(gè)階段做的事情是自動(dòng)構(gòu)建,單元測(cè)試,靜態(tài)代碼分析以及生成報(bào)告。如果所有步驟都如預(yù)期成功通過(guò)的話會(huì)自動(dòng)進(jìn)入下一個(gè)階段 — 自動(dòng)化測(cè)試階段,在跑自動(dòng)化測(cè)試套件之前,首先要把成功通過(guò)第一階段的產(chǎn)出物(artifact), 如果選擇java做為開(kāi)發(fā)語(yǔ)言的話就是生成的war包,ruby的話就是gem文件,部署到測(cè)試服務(wù)器上,部署完成之后觸發(fā)自動(dòng)化測(cè)試套件,包括驗(yàn)收測(cè)試,容量測(cè)試,性能測(cè)試等會(huì)自動(dòng)執(zhí)行,如果所有測(cè)試用例都順利通過(guò)(有些公司還需要做一些手工測(cè)試如探索性測(cè)試等)的話,那么這個(gè)版本就會(huì)被標(biāo)記成一個(gè)可發(fā)布的侯選版本。一旦業(yè)務(wù)需要,就會(huì)通過(guò)一鍵部署的方式將相應(yīng)的侯選版本發(fā)布到生產(chǎn)環(huán)境上去。如果你想更多的了解持續(xù)交付相關(guān)的知識(shí)請(qǐng)閱讀David Farley and Jez Humble的名著《Continues Delivery》。
踐與痛點(diǎn)
上述這個(gè)過(guò)程實(shí)現(xiàn)起來(lái)需要這樣做,首先需要把上圖中各個(gè)階段的工作腳本化,說(shuō)具體一點(diǎn)就是需要寫一個(gè)構(gòu)建腳本來(lái)完成編譯,單元測(cè)試,靜態(tài)代碼分析,生成報(bào)告等步驟,從而完成持續(xù)集成階段的工作,然后是自動(dòng)化測(cè)試腳本,這個(gè)腳本可以觸發(fā)自動(dòng)化測(cè)試套件并生成相關(guān)報(bào)告,最后需要寫一個(gè)部署腳本,用于將持續(xù)集成階段的產(chǎn)出物部署到測(cè)試環(huán)境上(當(dāng)然最后的發(fā)布階段也會(huì)重用這個(gè)腳本),這里需要注意的是要確保部署都是可重復(fù)的,重復(fù)部署同一個(gè)產(chǎn)出物N次的效果與只部署一次的效果相同,也就是大家常說(shuō)的冪等。接下來(lái)就輪到Jenkins出場(chǎng)了,首先我們需要配置一下Jenkins來(lái)監(jiān)聽(tīng)代碼庫(kù)的變更,這就意味著只要有代碼遷入就會(huì)觸發(fā)相對(duì)應(yīng)的流水線,然后我們用Jenkins job或pipeline將這幾個(gè)階段的腳本串聯(lián)起來(lái)(下圖是以job為例),這樣一個(gè)簡(jiǎn)單的CI/CD流水線就搭建完成了。
如上圖所示,每一個(gè)Job負(fù)責(zé)運(yùn)行某一階段的腳本,可以簡(jiǎn)單類比為Job1運(yùn)行持續(xù)集成階段的腳本將源代碼從代碼庫(kù)中遷出,編譯,單元測(cè)試,靜態(tài)代碼分析以及生成報(bào)告,Job2首先將持續(xù)集成階段的產(chǎn)出物部署到測(cè)試環(huán)境并運(yùn)行自動(dòng)化測(cè)試套件,生成報(bào)告并標(biāo)記產(chǎn)出物,Job3用于按需發(fā)布。每個(gè)Job所運(yùn)行的腳本依賴的語(yǔ)言或運(yùn)行環(huán)境會(huì)有所不同,可以通過(guò)label方式選擇到相應(yīng)的Slave上運(yùn)行。
但在企業(yè)級(jí)大規(guī)模的應(yīng)用CI/CD流水線時(shí),由于企業(yè)中多團(tuán)隊(duì)多產(chǎn)品的存在,不同的團(tuán)隊(duì)會(huì)根據(jù)產(chǎn)品自身的特點(diǎn)來(lái)選擇不同的技術(shù)實(shí)現(xiàn)方式,這就意味著產(chǎn)品實(shí)現(xiàn)語(yǔ)言會(huì)有很多種,比如java, C#, ruby, python, nodejs …那么相對(duì)應(yīng)的CI/CD流水線就需要提供所有語(yǔ)言的編譯環(huán)境并安裝相關(guān)的依賴包,當(dāng)然為了減少依賴,避免沖突以及更好的管理這些編譯環(huán)境聰明的管理員會(huì)選擇讓每一個(gè)slave只能運(yùn)行特定編程語(yǔ)言的Job, 如下圖所示:
上圖這個(gè)Jenkins集群Maser只用來(lái)調(diào)度和收集log,所有的Job都會(huì)由Master根據(jù)不同的label導(dǎo)流到對(duì)應(yīng)的Slave上運(yùn)行。這種集群的實(shí)現(xiàn)方式是我們?cè)赩M時(shí)代不得已的選擇,雖然能解決大部分問(wèn)題,但也帶來(lái)了很多困擾。
單點(diǎn)依賴 Jenkins Master成為單點(diǎn),一旦Jenkins Master down機(jī),那將是災(zāi)難性的,整個(gè)CI/CD流水線都將處于不可用的狀態(tài)。不易維護(hù) 大量差異化的Jenkins Slave管理起來(lái)難度很大,由于差異化的存在,維護(hù)升級(jí)幾乎都需要手動(dòng)完成,人力成本投入很高。不易擴(kuò)展 舉個(gè)例子,我們發(fā)現(xiàn)流水線對(duì)Java7這個(gè)Slave發(fā)出的請(qǐng)求量比較大,經(jīng)常出現(xiàn)排隊(duì)現(xiàn)像。為了緩解這種情況,管理員需要增加一個(gè)可以編譯Java7應(yīng)用的Slave,那么管理員需要怎么做呢?首先需要準(zhǔn)備一臺(tái)VM,然后安裝java7以及所有依賴的軟件包,最后配置Slave相關(guān)信息label等并將新安裝好的Slave注冊(cè)到Master,基本上都需要人為干預(yù),擴(kuò)展起來(lái)非常不方便。資源浪費(fèi) 每一臺(tái)Jenkins Slave Server都是一臺(tái)實(shí)實(shí)在在運(yùn)行的VM, 當(dāng)Slave Sever空閑時(shí)也不能將它所占用的資源釋放,因?yàn)殡S時(shí)可能需要這個(gè)Slave完成相關(guān)的Job。解決痛點(diǎn)
下面我們來(lái)看一下虛擬化技術(shù)帶來(lái)了的福音,下圖是一個(gè)基于Kubernetes, Docker搭建起來(lái)的Jenkins集群,為了避免混淆我略去了Kubernetes集群中的Master node。我們看到Jenkins Mater以Docker container的形式運(yùn)行在Kubernetes一個(gè)Node上并將所有Jenkins相關(guān)數(shù)據(jù)存儲(chǔ)到一個(gè)volume中,Jenkins Slave也以Docker container的形式運(yùn)行在各個(gè)Node中,之所以用虛線來(lái)表現(xiàn)Slave是因?yàn)镾lave不是一直存在的,它會(huì)被動(dòng)態(tài)的按需創(chuàng)建并自動(dòng)刪除。簡(jiǎn)單介紹一下這種動(dòng)態(tài)創(chuàng)建注冊(cè)Slave的方式,它的工作流程是,當(dāng)Jenkins Master收到一個(gè)build的請(qǐng)求時(shí),會(huì)用按照l(shuí)abel的要求動(dòng)態(tài)的創(chuàng)建一個(gè)運(yùn)行在Docker container中的Jenkins Slave并注冊(cè)到Master上, 然后運(yùn)行相應(yīng)的Job,當(dāng)Job運(yùn)行完成后這個(gè)Slave會(huì)被注銷,所在的Docker container也會(huì)被自動(dòng)刪除。
這種基于Docker, Kubernetes搭建的CI/CD流水線給Jenkins集群帶來(lái)了諸多益處:
高可用 Jenkins Master被部署在Kubernetes集群上,一旦container運(yùn)行異常意外退出,那么Kubernetes會(huì)自動(dòng)用相同的Docker image幫我們從新起動(dòng)一個(gè)新的Jenkins,并將volume attach給新創(chuàng)建的Docker container,從而保證不會(huì)丟失任何數(shù)據(jù),實(shí)現(xiàn)了Jenkins集群的高可用性。自動(dòng)伸縮 由于每一次運(yùn)行Job時(shí),Jenkins Master都會(huì)動(dòng)態(tài)創(chuàng)建一個(gè)Jenkins slave,Job完成之后Slave會(huì)被注銷所在的Docker container也會(huì)被自動(dòng)刪除,所占用的資源就會(huì)被自動(dòng)釋放。也就是說(shuō)當(dāng)同時(shí)請(qǐng)求的Job數(shù)量越多,生成的Slave container就會(huì)越多,占用的資源也就越多,反之亦然,而且這種動(dòng)態(tài)伸縮是完全不需要人為干預(yù)的。完全隔離 由于每一次運(yùn)行Job都是在一個(gè)全新的Jenkins slave中運(yùn)行,避免了同時(shí)運(yùn)行的Job與Job之間發(fā)生沖突的可能性。容易維護(hù) 對(duì)比之前每一個(gè)Jenkins Slave是一臺(tái)固定VM的做法,以這種方式搭建的集群維護(hù)的不再是固定的VM而是創(chuàng)建動(dòng)態(tài)Slave所需要的Docker image,我們可以很容易通過(guò)Docker File來(lái)build適用于我們自已的Docker image并將它們存儲(chǔ)在私有的Docker registry中,非常易于維護(hù)。容易擴(kuò)展 當(dāng)我們發(fā)現(xiàn)Jenkins的Queue中存在大量等待執(zhí)行的Job是因?yàn)閗ubernetes集群的資源不足時(shí),能夠很容易的初始化一個(gè)kubernetes node并將它添加到集群中來(lái),實(shí)現(xiàn)橫向擴(kuò)展非常的方便。簡(jiǎn)單實(shí)現(xiàn)
下面我們來(lái)完成一個(gè)簡(jiǎn)單的實(shí)現(xiàn):
1、首先你需要安裝一個(gè)Kubernetes cluster,請(qǐng)參考https://kubernetes.io/docs/setup/ Kubernetes安裝完成之后,首先需要用下面兩條命令和文件部署一個(gè)Jenkins到Kubernetes集群:
代碼?
tip: 標(biāo)紅的部分很重要,開(kāi)放8080端口是用來(lái)訪問(wèn)Jenkins web portal用的;而動(dòng)態(tài)創(chuàng)建的Jenkins slave會(huì)默認(rèn)通過(guò)50000(可修改)端口與master建立連接。
檢查jenkins安裝運(yùn)行情況:
2、查看Jenkins log,用管理員密碼登錄Jenkins并安裝Kubernetes plugin。
3、 配置Kubernetes cloud
Manage Jenkins/Configure System/ Add a new cloud/ Kubernetes:
Add pod template/Kubernetes Pod Template:
點(diǎn)擊Save之后大功告成。
牛刀小試
下面我們來(lái)測(cè)試一下這個(gè)動(dòng)態(tài)注冊(cè)Slave的Jenkins集群是否工作正常,首先登錄Jenkins創(chuàng)建一個(gè)簡(jiǎn)單的free style job,指定這個(gè)Job只能在Label為“jnlp”的agent上運(yùn)行。點(diǎn)擊build now,你會(huì)發(fā)現(xiàn)奇跡發(fā)生了,原來(lái)沒(méi)有注冊(cè)任何Slave的Jenkins動(dòng)態(tài)的創(chuàng)建一個(gè)Slave并注冊(cè)到Master上,然后運(yùn)行相應(yīng)的Job,當(dāng)Job運(yùn)行結(jié)束后這個(gè)Slave被自動(dòng)清除了。
PS:這只是一個(gè)簡(jiǎn)單的實(shí)現(xiàn),在企業(yè)的實(shí)踐中,我們需要不同的build環(huán)境,需要我們基于jenkinsci/jnlp-slave這個(gè)Image構(gòu)建我們自己的Jenkins slave Image并保存到私有的Registry中,相對(duì)應(yīng)的Kubernetes需要從私有Registry拉取Image。
- 蜜度索驥:以跨模態(tài)檢索技術(shù)助力“企宣”向上生長(zhǎng)
- 密態(tài)計(jì)算技術(shù)助力農(nóng)村普惠金融 螞蟻密算、網(wǎng)商銀行項(xiàng)目入選大數(shù)據(jù)“星河”案例
- 專利糾紛升級(jí)!Netflix就虛擬機(jī)專利侵權(quán)起訴博通及VMware
- 兩大難題發(fā)布!華為啟動(dòng)2024奧林帕斯獎(jiǎng)全球征集
- 2025年工業(yè)軟件市場(chǎng)格局:7個(gè)關(guān)鍵統(tǒng)計(jì)數(shù)據(jù)與分析
- Commvault持續(xù)業(yè)務(wù)策略:應(yīng)對(duì)現(xiàn)代數(shù)據(jù)保護(hù)挑戰(zhàn)的新范式
- 2025年網(wǎng)絡(luò)安全主要趨勢(shì)
- 2025年值得關(guān)注的數(shù)據(jù)中心可持續(xù)發(fā)展趨勢(shì)
- 量子計(jì)算火熱,投資者又在大舉尋找“量子概念股”
- 從量子威脅到人工智能防御:2025年網(wǎng)絡(luò)安全將如何發(fā)展
- 后人工智能時(shí)代:2025年,在紛擾中重塑數(shù)據(jù)、洞察和行動(dòng)
免責(zé)聲明:本網(wǎng)站內(nèi)容主要來(lái)自原創(chuàng)、合作伙伴供稿和第三方自媒體作者投稿,凡在本網(wǎng)站出現(xiàn)的信息,均僅供參考。本網(wǎng)站將盡力確保所提供信息的準(zhǔn)確性及可靠性,但不保證有關(guān)資料的準(zhǔn)確性及可靠性,讀者在使用前請(qǐng)進(jìn)一步核實(shí),并對(duì)任何自主決定的行為負(fù)責(zé)。本網(wǎng)站對(duì)有關(guān)資料所引致的錯(cuò)誤、不確或遺漏,概不負(fù)任何法律責(zé)任。任何單位或個(gè)人認(rèn)為本網(wǎng)站中的網(wǎng)頁(yè)或鏈接內(nèi)容可能涉嫌侵犯其知識(shí)產(chǎn)權(quán)或存在不實(shí)內(nèi)容時(shí),應(yīng)及時(shí)向本網(wǎng)站提出書面權(quán)利通知或不實(shí)情況說(shuō)明,并提供身份證明、權(quán)屬證明及詳細(xì)侵權(quán)或不實(shí)情況證明。本網(wǎng)站在收到上述法律文件后,將會(huì)依法盡快聯(lián)系相關(guān)文章源頭核實(shí),溝通刪除相關(guān)內(nèi)容或斷開(kāi)相關(guān)鏈接。