基于 Kubernetes 实践弹性的 CI/CD 系统
大家好,我是來(lái)自阿里云容器服務(wù)團(tuán)隊(duì)的華相。首先簡(jiǎn)單解釋一下何為 Kubernetes 來(lái)幫助大家理解。Kuberentes 是一個(gè)生產(chǎn)可用的容器編排系統(tǒng)。Kuberentes 一方面在集群中把所有 Node 資源做一個(gè)資源池,然后它調(diào)度的單元是 Pod,當(dāng)然 Pod 里面可以有多個(gè)容器。 就像一個(gè)人左手抓著 ECS 資源或計(jì)算資源,右手抓容器,然后把它們兩個(gè)匹配起來(lái),這樣它就可以作為一個(gè)容器的編排系統(tǒng)。
而?Cloudnative 這個(gè)概念現(xiàn)在會(huì)經(jīng)常被大家提起,很多人迷惑 Cloudnative 又與 Kuberentes 有什么關(guān)聯(lián)?我們又該如何判斷一個(gè)應(yīng)用是 Cloudnative 呢?我認(rèn)為有以下三個(gè)判斷標(biāo)準(zhǔn):
第一,它能夠給資源做池化;
第二,應(yīng)用可以快速接入池的網(wǎng)絡(luò)。在 Kuberentes 里面有一層自己的獨(dú)立網(wǎng)絡(luò),然后只需要知道我要去訪問(wèn)哪個(gè)服務(wù)名就可以,就是各種服務(wù)發(fā)現(xiàn)的一些功能,它可以通過(guò) service mesh 去做一個(gè)快速地訪問(wèn);
第三是有故障轉(zhuǎn)移功能,如果一個(gè)池子里面有一臺(tái)主機(jī),或者某一個(gè)節(jié)點(diǎn) down 掉了,然后整個(gè)應(yīng)用就不可用了,這肯定不算是 Cloudnative 的應(yīng)用。
比較這三點(diǎn)就可以發(fā)現(xiàn) Kuberentes 做的非常好。首先我們看一個(gè)資源池的概念,Kuberentes 一個(gè)大的集群就是一個(gè)資源池,我們?cè)僖膊挥萌リP(guān)心說(shuō)我這個(gè)應(yīng)用要跑在哪臺(tái)主機(jī)上了,我只要把我們部署的 yaml 文件往 Kuberentes 上發(fā)布就可以了,它會(huì)自動(dòng)做這些調(diào)度,并且它可以快速地接入我們整個(gè)應(yīng)用的網(wǎng)絡(luò),然后故障轉(zhuǎn)移也是自動(dòng)。接下來(lái)我就來(lái)分享如何基于 Kuberentes 實(shí)現(xiàn)一個(gè)彈性的 CI/CD 系統(tǒng)。
CI/CD?的現(xiàn)狀
首先了解一下 CI/CD 的現(xiàn)狀。CI/CD 這個(gè)概念實(shí)際上已經(jīng)提出很多年了,但是隨著技術(shù)地演進(jìn)和新工具地不斷推出,它在整個(gè)流程和實(shí)現(xiàn)方式上逐漸豐富。而我們通常最早接觸 CI/CD 就是代碼提交,隨之觸發(fā)一個(gè)事件,然后在某個(gè) CI/CD 系統(tǒng)上做自動(dòng)構(gòu)建。
下圖可以反映目前 CI/CD 的現(xiàn)狀:
另外還有 Gitlab CI,它主要特點(diǎn)是與 Gitlab 代碼管理工具結(jié)合地比較好。Jenkins 2.0 開(kāi)始引入 pipeline as code 特性,pipeline as code 可以幫我們自動(dòng)生成一個(gè) jenkins file。
在 Jenkins 1.0 時(shí),如果我們想要配置一條流水線,需要先登錄 Jenkins 建一個(gè)項(xiàng)目,然后在里面寫(xiě)一些 shell。這樣雖然能達(dá)到同樣的效果,但是它有一個(gè)最大的弊端,就是可復(fù)制性和遷移性不好。而且它與 Devops 有天然地割裂,比如一般是由運(yùn)維人員來(lái)管理 Jenkins 系統(tǒng),開(kāi)發(fā)人員編寫(xiě)代碼,但是這個(gè)代碼怎么去構(gòu)建,發(fā)布到哪里,開(kāi)發(fā)人員完全不知道。這就造成了開(kāi)發(fā)和運(yùn)維地割裂。但 pipeline as code 方式出現(xiàn)了之后,jenkins file 與代碼源碼可以放在同樣的倉(cāng)庫(kù)里面。
首先它有一個(gè)非常大的好處是發(fā)布的流程也可以納入版本管理,這樣對(duì)一個(gè)錯(cuò)誤就可追溯。這是一個(gè)非常大地改動(dòng),但是實(shí)際上我們?cè)谂c客戶(hù)溝通中發(fā)現(xiàn),雖然很多人在 Jenkins 上都已經(jīng)升到 2.0 系列了,但是它們的用法還是完全在 1.0 系列,很多用戶(hù)都沒(méi)有把 jenkins file 這種方式用起來(lái)。另外一個(gè)就是對(duì)容器地支持,大概 2016 年左右,那時(shí)對(duì)容器的支持是非常弱的,在容器里面運(yùn)行 Jenkins,同時(shí)構(gòu)建的產(chǎn)物也是 Docker 會(huì)非常麻煩。?
但是, Drone 對(duì)容器的支持力度就非常好。首先它完全用 Docker 方式來(lái)運(yùn)行,就是說(shuō)你的構(gòu)建環(huán)境也在一個(gè)容器里,你需要構(gòu)建一個(gè) Docker build 鏡像,然后在推送出去的時(shí)候,它也在容器里面運(yùn)行,然后它需要一個(gè) privilege 權(quán)限。它這種方式有幾個(gè)特別好的地方,首先它不會(huì)對(duì)宿主機(jī)產(chǎn)生任何殘留,比如說(shuō)你這個(gè)容器一銷(xiāo)毀,構(gòu)建中產(chǎn)生的一些中間文件完全都跟著銷(xiāo)毀了,但是你如果用 Jenkins 的話,隨著用的時(shí)間越來(lái)越久會(huì)沉淀出很多臨時(shí)文件,它占的空間會(huì)越來(lái)越大。你需要定期做一些清理,而且清理過(guò)程中你又不能直接一鍵清空,所以這是很麻煩的過(guò)程。
然后插件的管理 Jenkins 還有一個(gè)特別讓人頭疼的地方,就是它的插件升級(jí)。首先你在 Jenkins 登錄進(jìn)去,然后就做插件升級(jí)。如果說(shuō)我想臨時(shí)在一個(gè)新的環(huán)境里面,起一個(gè) Jenkins 先測(cè)試一下或做一些調(diào)試可能每新建一個(gè)環(huán)境,都需要把這些插件升級(jí)一次。而且剛才我們說(shuō)的在 Jenkins 里面做的所有配置,也都需要重新配置一遍,這是一個(gè)非常繁瑣的一個(gè)過(guò)程。
但是 Drone 這個(gè)工具它有一個(gè)特別好的地方,就是所有的插件都是 Docker 容器,比如說(shuō)你在 pipeline 里用這個(gè)插件,你只要聲明用這個(gè)插件就可以了,你不用去自己管理把插件下載到哪里,然后怎么安裝,它這個(gè)一切都是全自動(dòng),只要說(shuō)你網(wǎng)絡(luò)能把插件容器鏡像訪問(wèn)到就可以了,這非常便利。
然后關(guān)于生態(tài)的構(gòu)建,Jenkins 的最大的優(yōu)勢(shì)就是它的插件非常多,就是你想用的各種東西都有,而且它基礎(chǔ)的底座非常好,你的插件可以實(shí)現(xiàn)的能力非常的強(qiáng)。比如說(shuō) pipeline 就是這種方式,它從 1.0 到 2.0 雖然有了,但是它完全是通過(guò)插件來(lái)實(shí)現(xiàn)的。但是現(xiàn)在 Jenkins 的發(fā)展又開(kāi)始有點(diǎn)第二春的感覺(jué)。他開(kāi)始對(duì) Kuberentes 的支持力度明顯的加大了很多,首先從 JenkinsX 開(kāi)始,它融合了一些 Kuberentes 生態(tài)相關(guān)的一些工具,比如 Harbor、Helm 它可以非常便利地在 Kuberentes 集群上來(lái)做一些構(gòu)建,并且把一些做服務(wù)的固化的一些編排文件放到 Helm 里面。
另外,現(xiàn)在它有一個(gè)新的子項(xiàng)目叫 config as code,也就是說(shuō)他把所有 Jenkin 里面做了一些配置,都可以輸出成一個(gè) code 的形式,就是對(duì)整個(gè) Jenkins 的遷移,或者說(shuō)復(fù)制都是一個(gè)很便利的改進(jìn)。
講了那么多,實(shí)際上最后我們選擇的東西還是 Jenkins,因?yàn)樽钪匾氖巧鷳B(tài)的構(gòu)建,他們已經(jīng)很好了。今天我們要講的在做一個(gè)彈性在 CI/CD 這個(gè) Jenkins 上已經(jīng)有這個(gè)插件了,但是在 Drone 的社區(qū)里面,有人提這個(gè)事,但是現(xiàn)在還沒(méi)有看到。
CI/CD 工具的選擇
接下來(lái),我們看一下 CI/CD 這些工具的選擇和他們的發(fā)展。首先最老牌的肯定是?Jenkins。實(shí)際上在容器技術(shù)興起之前,CI/CD 簡(jiǎn)直約等于?Jenkins。但是在出現(xiàn)容器技術(shù)之后,很多新生 CI/CD 的工具也應(yīng)運(yùn)而生,比如說(shuō)圖中?Drone?工具,它是一個(gè)完全基于容器來(lái)實(shí)現(xiàn)的 CI/CD 工具。它與容器地結(jié)合地非常好,并且它的構(gòu)建過(guò)程是完全在容器中實(shí)現(xiàn)的。
第三個(gè)是?Gitlab CI,它主要特點(diǎn)是與?Gitlab 代碼管理工具結(jié)合地比較好。Jenkins?2.0 時(shí)開(kāi)始引入 pipeline as code?特性,什么叫?pipeline as code?pipeline as code 可以幫我們自動(dòng)生成一個(gè)?jenkins file。在 Jenkins 1.0 時(shí),如果我們想要配置一條流水線,需要先登錄?Jenkins,然后建一個(gè)項(xiàng)目,然后在里面寫(xiě)一些 shell。這樣雖然能達(dá)到同樣的效果,但是它有一個(gè)最大的弊端,就是可復(fù)制性和遷移性不好。而且它與?Devops?有天然地割裂,比如一般是運(yùn)維人員來(lái)管理?Jenkins?這個(gè)系統(tǒng)。開(kāi)發(fā)人員編寫(xiě)代碼,但是這個(gè)代碼怎么去構(gòu)建,發(fā)布到哪里,他是完全不知道的,是運(yùn)維人員在Jenkins 里面配的。這個(gè)就造成了開(kāi)發(fā)和運(yùn)維地割裂。但?pipeline as code?這種方式出現(xiàn)了之后,我們可以把?jenkins file?跟代碼源碼放在同樣的倉(cāng)庫(kù)里面。
首先它有一個(gè)非常大的好處就是我們發(fā)布的流程也可以納入版本管理,這樣對(duì)一個(gè)錯(cuò)誤就可追溯。這是一個(gè)非常大地改動(dòng),但是實(shí)際上我們?cè)谂c客戶(hù)溝通中發(fā)現(xiàn),雖然很多人在?Jenkins?上都已經(jīng)升到 2.0 系列了,但是它們的用法還是完全在 1.0 系列,很多用戶(hù)都沒(méi)有把?jenkins file?這種方式用起來(lái)。另外一個(gè)就是對(duì)容器地支持,大概?2016 年左右,那時(shí)對(duì)容器的支持是非常弱的,在容器里面運(yùn)行 Jenkins,同時(shí)構(gòu)建的產(chǎn)物也是 Doker 會(huì)非常麻煩。?
但是, Drone 對(duì)容器的支持力度就非常好。首先它完全用?Doker?方式來(lái)運(yùn)行,就是說(shuō)你的構(gòu)建環(huán)境也在一個(gè)容器里,你需要構(gòu)建一個(gè)?Doker build?鏡像,然后在推送出去的時(shí)候,它也在容器里面運(yùn)行,然后它需要一個(gè)?privilege?權(quán)限。它這種方式有幾個(gè)特別好的地方,首先它不會(huì)對(duì)宿主機(jī)產(chǎn)生任何殘留,比如說(shuō)你這個(gè)容器一銷(xiāo)毀,構(gòu)建中產(chǎn)生的一些中間文件完全都跟著銷(xiāo)毀了,但是你如果用?Jenkins?的話,隨著用的時(shí)間越來(lái)越久會(huì)沉淀出很多臨時(shí)文件,它占的空間會(huì)越來(lái)越大。你需要定期做一些清理,而且清理過(guò)程中你又不能直接一鍵清空,所以這是很麻煩的過(guò)程。然后插件的管理 Jenkins 還有一個(gè)特別讓人頭疼的地方,就是它的插件升級(jí)。首先你在 Jenkins 登錄進(jìn)去,然后就做插件升級(jí)。如果說(shuō)我想臨時(shí)在一個(gè)新的環(huán)境里面,起一個(gè) Jenkins 先測(cè)試一下或做一些調(diào)試可能每新建一個(gè)環(huán)境,都需要把這些插件升級(jí)一次。而且剛才我們說(shuō)的在 Jenkins 里面做的所有配置,也都需要重新配置一遍,這是一個(gè)非常繁瑣的一個(gè)過(guò)程。
但是 Drone 這個(gè)工具它有一個(gè)特別好的地方,就是所有的插件都是 Doker?容器,比如說(shuō)你在 pipeline?里用這個(gè)插件,你只要聲明用這個(gè)插件就可以了,你不用去自己管理把插件下載到哪里,然后怎么安裝,它這個(gè)一切都是全自動(dòng),只要說(shuō)你網(wǎng)絡(luò)能把插件容器鏡像訪問(wèn)到就可以了,這非常便利。
然后關(guān)于生態(tài)的構(gòu)建,Jenkins 的最大的優(yōu)勢(shì)就是它的插件非常多,就是你想用的各種東西都有,而且它基礎(chǔ)的底座非常好,你的插件可以實(shí)現(xiàn)的能力非常的強(qiáng)。比如說(shuō) pipeline?就是這種方式,它從 1.0 到?2.0?雖然有了,但是它完全是通過(guò)插件來(lái)實(shí)現(xiàn)的。但是現(xiàn)在 Jenkins 的發(fā)展又開(kāi)始有點(diǎn)第二春的感覺(jué)。他開(kāi)始對(duì) Kuberentes 的支持力度明顯的加大了很多,首先從 JenkinsX?開(kāi)始,它融合了一些 Kuberentes 生態(tài)相關(guān)的一些工具,比如 Harbor、Helm?它可以非常便利地在 Kuberentes 集群上來(lái)做一些構(gòu)建,并且把一些做服務(wù)的固化的一些編排文件放到 Helm?里面。
另外,現(xiàn)在它有一個(gè)新的子項(xiàng)目叫 config as code,也就是說(shuō)他把所有 Jenkin?里面做了一些配置,都可以輸出成一個(gè) code 的形式,就是對(duì)整個(gè) Jenkins 的遷移,或者說(shuō)復(fù)制都是一個(gè)很便利的改進(jìn)。
講了那么多,實(shí)際上最后我們選擇的東西還是 Jenkins,因?yàn)樽钪匾氖巧鷳B(tài)的構(gòu)建,他們已經(jīng)很好了。今天我們要講的在做一個(gè)彈性在 CI/CD 這個(gè) Jenkins 上已經(jīng)有這個(gè)插件了,但是在 Drone?的社區(qū)里面,有人提這個(gè)事,但是現(xiàn)在還沒(méi)有看到。
?
CI/CD的系統(tǒng)業(yè)務(wù)場(chǎng)景
然后我們看一下 CI/CD 它的系統(tǒng)的業(yè)務(wù)場(chǎng)景,它有一個(gè)比較典型的場(chǎng)景與特點(diǎn),首先它面向開(kāi)發(fā)人員,這是比較少見(jiàn)的,因?yàn)殚_(kāi)發(fā)人員一般都比較挑剔一點(diǎn)。所以你要是這個(gè)系統(tǒng)做的不夠穩(wěn)健了,或者說(shuō)響應(yīng)時(shí)間比較長(zhǎng)一點(diǎn)的話,會(huì)被經(jīng)常吐槽。
然后就是有時(shí)效性要求,因?yàn)槲覀兇a寫(xiě)完之后,往上提交,我們都不希望在這個(gè)代碼的構(gòu)建中一直排隊(duì),我們希望馬上就開(kāi)始進(jìn)行構(gòu)建,并且資源足夠豐富。另外一個(gè)就是它的資源占用的波峰波谷是非常明顯的。就因?yàn)殚_(kāi)發(fā)人員不可能時(shí)時(shí)刻刻都在提交代碼,有的人可能一天提交幾次,有的人會(huì)提交很多次。
因?yàn)槲抑翱催^(guò)有一個(gè)分享,有一個(gè)人畫(huà)了一條反映自家公司構(gòu)建任務(wù)的曲線。他們公司大概是每天下午三、四點(diǎn)的時(shí)候代碼提交量最高,其他時(shí)間都比較平緩。這說(shuō)明他們公司三、四點(diǎn)的時(shí)候,程序員提交代碼開(kāi)始劃水了。然后隨著 CI/CD 資源地需求越來(lái)越高,構(gòu)建集群是一個(gè)必須要做的一件事情。就是提高負(fù)載能力,縮短任務(wù)的排隊(duì)時(shí)間。當(dāng)然真正的集群有一個(gè)讓人覺(jué)得很不太好的地方,就是它的 Master 實(shí)際上只有一個(gè),當(dāng)然這個(gè)也可以通過(guò)插件來(lái)做改進(jìn)。
容器可以給我們 CI/CD 系統(tǒng)來(lái)注入新的能力,就是環(huán)境隔離的能力。我們可以通過(guò) Kubernetes 來(lái)為 CI/CD 系統(tǒng)注入更多的能力,然后矛盾點(diǎn)就出現(xiàn)了。開(kāi)發(fā)人員總是希望 CI/CD 系統(tǒng)能夠快速地響應(yīng)代碼提交的一個(gè)事件,但是每個(gè)公司資源都不可能是無(wú)限的。因?yàn)榫拖裆厦嫣岬降?#xff0c;如果每天下午三、四點(diǎn)的時(shí)候是一個(gè)代碼提交的高峰,這個(gè)時(shí)候可能需要 30 或 40 臺(tái)機(jī)器才能滿足構(gòu)建的任務(wù)。但是我不可能每天就開(kāi)著 30 或 40 臺(tái)機(jī)器在這里,就為了每天下午三、四點(diǎn),可能會(huì)構(gòu)建一、兩個(gè)小時(shí)。
Kubernetes 可以為 jenkins 注入新的能力,讓 CI/CD 系統(tǒng)實(shí)現(xiàn)彈性的能力。我們期望的目標(biāo)是什么呢?有構(gòu)建任務(wù)的時(shí)候,可以自動(dòng)為我們資源增加新的機(jī)器也好,或增加新的運(yùn)計(jì)算能力也好,反正就是當(dāng)我需要的時(shí)候,可以幫我自動(dòng)地做一個(gè)資源擴(kuò)張,但是同時(shí)也在我不需要的時(shí)候,可以自動(dòng)把這些資源釋放掉。
我們期望的目標(biāo)就是這樣,Kuberentes 就可以為 Jenkins 來(lái)做這樣的能力。Kuberentes 作為一個(gè)容器編排的系統(tǒng),它所能提供的能力,它可以快速地彈出一些新的實(shí)例,并且把它們自動(dòng)調(diào)度到空閑的機(jī)器上,做一個(gè)資源池,在資源池里面做一個(gè)調(diào)度,并且他執(zhí)行完任務(wù)之后,它可以做一個(gè)回收。而且如果把這 Jenkins Master 也部署在 Kuberentes 之上,它可以對(duì) Master 做一個(gè)故障轉(zhuǎn)移,就是說(shuō)如果我們系統(tǒng)可以容忍的話,Master 就算掛了,我可以快速把它調(diào)到另外一臺(tái)機(jī)器上,這個(gè)響應(yīng)時(shí)間不會(huì)很長(zhǎng)。
Kuberentes-plugin
這里面也是用一個(gè)插件來(lái)實(shí)現(xiàn),這個(gè)插件名字比較直接叫 Kuberentes-plugin,它這個(gè)插件所能提供的能力就是說(shuō),他直接管理一個(gè) Kuberentes 集群,它在 Jenkins 里面安裝之后,它可以監(jiān)聽(tīng) Jenkins 的構(gòu)建任務(wù)。有構(gòu)建任務(wù),在等待資源的時(shí)候,它就可以向 Kuberenetes 去申請(qǐng)一個(gè)新的資源,申請(qǐng)一個(gè)新的 Pod 去做自動(dòng)地構(gòu)建完之后,它就會(huì)自動(dòng)的清理。
先簡(jiǎn)單介紹一下它的能力,因?yàn)檫@個(gè)插件安裝完之后,它對(duì) pipeline 的語(yǔ)法也有一個(gè)改造,一會(huì)我們來(lái)看一下實(shí)例。但是就算到了這一步,還是不行的。首先,Kuberentes 的集群規(guī)劃還是一個(gè)問(wèn)題。比說(shuō)我有個(gè)集群有 30 個(gè)節(jié)點(diǎn),真正的 master 部署在這上面,然后裝了那些插件,做了一個(gè)管理之后,我們可以發(fā)現(xiàn)來(lái)了一個(gè)新的任務(wù),它就起一個(gè)新的 Pod,把這個(gè)構(gòu)建任務(wù)給執(zhí)行制定完。
執(zhí)行完之后,這 Pod 自動(dòng)銷(xiāo)毀不占集群的資源。 平時(shí)我們可以在這集群上做一些別的任務(wù),但這個(gè)終究還是有一點(diǎn)不好,就是我們這個(gè)集群到底規(guī)劃多大,并且這個(gè)集群我們平時(shí)不做構(gòu)建任務(wù)的時(shí)候,可以在上面做一些別的任務(wù)。但是如果正在做任務(wù),突然來(lái)了一些構(gòu)建任務(wù),它可能會(huì)出現(xiàn)資源的沖突問(wèn)題。
?
Kubernetes Autoscaler
總的來(lái)說(shuō),還是有一些不完美的地方,那么我們可以利用 Kuberentes 一些比較沒(méi)那么常見(jiàn)的特性,來(lái)解決我們剛才說(shuō)的這個(gè)問(wèn)題。這兩個(gè)東西一個(gè)是叫 Autoscaler,一個(gè)叫 Virtual node。我們先看一下 Autoscaler,Autoscaler 是一個(gè) Kubernetes 官方的一個(gè)組件。在 Kuberentes 的 group 下面支持三種能力:
?
- Cluster Autoscaler,可以對(duì)集群節(jié)點(diǎn)做自動(dòng)伸縮;
- Vertical Pod Autoscaler,對(duì)集群的 Pod 豎直方向的資源伸縮。因?yàn)?Kuberentes 本身里面就帶著 HPA 可以做水平方向的 Pod 伸縮、節(jié)點(diǎn)數(shù)量的伸縮;這個(gè)特性還不是生產(chǎn)可用的特性;
- Addone Resizer,是 Kuberentes 上那些 addone 比如說(shuō) Ingress Controler、 DNS 可以根據(jù) Node 的數(shù)量來(lái)對(duì)資源的分配做調(diào)整。
Cluster autoscaler
我要講的是 Cluster autoscaler,是對(duì)集群 node 節(jié)點(diǎn)數(shù)量做一個(gè)擴(kuò)縮容。 首先我們看一下,這個(gè)是在阿里云我們?nèi)萜鞣?wù)上所實(shí)現(xiàn)的 Autoscaler 的一個(gè)方式。我們看一下這個(gè)圖,這個(gè)是 HPA 和 Autoscler 做結(jié)合使用的一個(gè)場(chǎng)景。
HPA 監(jiān)聽(tīng)監(jiān)控的事件時(shí)發(fā)現(xiàn)資源使用率上升到一定程度了之后,HPA 會(huì)自動(dòng)通知 workload,來(lái)彈出一個(gè)新的 Pod,彈出一個(gè)新的 Pod,可能這時(shí)候集群資源就已經(jīng)不夠了,所以這個(gè) Pod 可能就會(huì) pending 在這里。它就會(huì)觸發(fā) Autoscaler 的事件,Autoscaler 就會(huì)根據(jù)我們之前配置好的 ESS 這個(gè)模板來(lái)去彈出來(lái)一臺(tái)新的 Node,然后自動(dòng)地把 Node 加入到我們集群里面。 它是利用了 ESS 定制的模板功能,并且它可以支持多種的 Node 實(shí)例的類(lèi)型,可以支持普通實(shí)例,支持 gpu,還有搶占式實(shí)例。
?
Virtual node
然后第二種是 Virtual node,Virtual node 實(shí)現(xiàn)方式是基于微軟開(kāi)源的 Virtual Kubelet 這個(gè)項(xiàng)目。它做了一個(gè)虛擬的 Kubelet,然后向 Kubernetes 集群里面去注冊(cè)上面。但如果不太好理解的話,可以想象一下 MySQL proxy ,然后他把自己偽裝成一個(gè)MySQL server,然后后端可能管理著非常多的 MySQL server,并且它可以幫你自動(dòng)的做一些 SQL 查詢(xún)的路由或者拼接。
Virtual kubelet 做的也是類(lèi)似的工作,就是說(shuō)它本身向著 Kubernetes 注冊(cè)說(shuō)我是一個(gè)節(jié)點(diǎn),但實(shí)際上它后端管理的可能是整個(gè)公有云上的非常多的資源,他可能對(duì)接公有云的一些 ECI 或者說(shuō)對(duì)接的這些 VPC,這是一個(gè)它的大體的示意圖。
在阿里云上他們對(duì)接的是阿里云的 ECI 做一個(gè)彈性的容器實(shí)例,它響應(yīng)時(shí)間就非常快,因?yàn)樗恍枰?Node 去加入到集群里面,它是大概能夠到一分鐘一百個(gè) Pod 左右這種性能。而且我們可以在 Pod 上聲明這種資源的使用情況,這是一個(gè)非常快的響應(yīng)速度時(shí)間。
然后剛才說(shuō)我們利用這兩種方式,就可以對(duì)我們 CI/CD 彈性的系統(tǒng)做出新的改造,我們不用非常早規(guī)劃好我們集群的規(guī)模,我們可以讓集群規(guī)模在需要的時(shí)候自動(dòng)的做一些伸縮的動(dòng)作。但是你做了這些動(dòng)作之后,我們做了這些把真正的放在容器里面的這些動(dòng)作之后,引入了一些新的門(mén)檻:docker-outside-of-docker 和 docker in docker。
我們?cè)?Docker 中運(yùn)行 Jenkins 時(shí),通常有兩種方式,一個(gè)是把宿主機(jī)的 docker.sock 掛載到容器里面,讓 Jenkins 通過(guò)這個(gè)文件來(lái)和本機(jī)的 docker daemon 做一個(gè)通信,然后它在這里面做 docker build 構(gòu)建鏡像,或者把這些鏡像 push 到遠(yuǎn)程的倉(cāng)庫(kù)里面,所以它中間產(chǎn)生的所有鏡像都會(huì)堆積在本機(jī)上,這是一個(gè)問(wèn)題。
在一些 serverless 的那些場(chǎng)景上使用,它就會(huì)有一些限制,因?yàn)?serverless 本身就不允許把 socket 文件給掛在進(jìn)去。另外一個(gè)就是 docker in docker 這種方式,它的優(yōu)點(diǎn)就在于在容器里面它啟動(dòng)一個(gè)新的 Docker daemon,它所有的中間產(chǎn)物、構(gòu)建產(chǎn)物隨著容器都一起銷(xiāo)毀,但是它有問(wèn)題,它就是需要 privilege 的權(quán)限。
很多時(shí)候我們是盡量不要用它。另外一個(gè)就是說(shuō)你做 docker build 的時(shí)候能在宿主機(jī)上做的時(shí)候,它如果有已經(jīng)有鏡像了,它會(huì)直接就使用這個(gè)鏡像,但是你用 docker in docker 這種方式來(lái)使用的,它每次都會(huì)重新拉進(jìn)項(xiàng),拉鏡像也是需要一定時(shí)間,這個(gè)取決于我們各個(gè)使用場(chǎng)景來(lái)判斷。
新的構(gòu)建工具——Kaniko
這時(shí)又引入了一個(gè)谷歌開(kāi)源的新工具——Kaniko。它做的東西是 docker in docker 的方式。它有一個(gè)非常大的好處就是不依賴(lài) Docker,而且所以它不需要 privilege 權(quán)限就可以在容器里面用用戶(hù)態(tài)的模式,來(lái)完全構(gòu)建 docker image。用戶(hù)態(tài)執(zhí)行 Dockerfile 的命令,它把這個(gè)鏡像完全構(gòu)建出來(lái)。
這算是一個(gè)比較期望的彈性的 CI/CD 系統(tǒng)。然后這個(gè)時(shí)候就是說(shuō)從真正的節(jié)點(diǎn)到底層的計(jì)算資源全部是彈性擴(kuò)縮的,而且滿足交付的需求,可以非常精細(xì)化地管理我們的資源。
Demo 演示
然后我們可以看一下 Demo 演示:
https://github.com/hymian/webdemo?這里是我準(zhǔn)備好的一個(gè)例子,重點(diǎn)在這個(gè) Jenkinsfile 文件,里面定義了agent 的 pod template,包含兩個(gè)容器,一個(gè)用來(lái)做 golang 的 build,一個(gè)用來(lái)做 image 的 build。
然后我們現(xiàn)在構(gòu)建它。開(kāi)始構(gòu)建了,剛開(kāi)始的,因?yàn)槭乾F(xiàn)在我們?cè)谶@環(huán)境里面只有一個(gè),只有一個(gè) master,所以他就是沒(méi)有不會(huì)有構(gòu)建節(jié)點(diǎn)。大家可以看到,它現(xiàn)在新啟動(dòng)了一個(gè) Pod,這個(gè) Pod 是作為節(jié)點(diǎn)加進(jìn)來(lái)的,但是因?yàn)槲以谶@個(gè) Pod 模板里面定義了一個(gè) label,所以它沒(méi)有這個(gè)節(jié)點(diǎn),所以它 Pod 狀態(tài)是 pending 的。所以我們?cè)跇?gòu)建日志里面顯示的這個(gè)是 agent 節(jié)點(diǎn)是離線的。?
但是我們?cè)谶@個(gè)集群里面定義了一個(gè)彈性伸縮的一個(gè)東西,當(dāng)沒(méi)有節(jié)點(diǎn)的時(shí)候,它會(huì)自動(dòng)做一個(gè)新節(jié)點(diǎn)分配加入,可以看到有一個(gè)節(jié)點(diǎn)正在加入,這個(gè)我就可以稍等一下。就是說(shuō)這段時(shí)間可能會(huì)有個(gè)一分鐘兩分鐘的時(shí)間。
這個(gè)是異常,是因?yàn)檫@個(gè)節(jié)點(diǎn)正在向集群加入,所以它顯示是異常,這是我們從命令行看一下,好,已經(jīng)是四個(gè)節(jié)點(diǎn)了,加了一個(gè)節(jié)點(diǎn),這時(shí)候我們看 Pod,這時(shí)候在 agent 正在創(chuàng)建,這時(shí)候大家可能有一個(gè)小的細(xì)節(jié),大家可以看一下,就是 0/3 是顯示 Pod,它有三個(gè)容器,但是我剛才在這個(gè)里面定義的,它實(shí)際上是 Pod 里面只有兩個(gè)容器,這就是我們剛才 PPT 上寫(xiě)的一個(gè)地方。?
JNLP 那個(gè)容器,是 plugin 自動(dòng)注入的一個(gè)容器,它通過(guò)這個(gè)容器實(shí)時(shí)的向 master 匯報(bào)構(gòu)建的一個(gè)中間的狀態(tài),我把它的日志給發(fā)送出去。這個(gè)是 agent 的節(jié)點(diǎn)在初始化的一個(gè)過(guò)程一個(gè)事情這時(shí)候 slave節(jié)點(diǎn)已經(jīng)在運(yùn)行了。我這邊已經(jīng)輸出完了,構(gòu)建完成。我的分享內(nèi)容就這些,謝謝大家。
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的基于 Kubernetes 实践弹性的 CI/CD 系统的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 手把手教你数据不足时如何做深度学习NLP
- 下一篇: Flutter Exception降到万