明源云创CI/CD技术演进
源寶導(dǎo)讀:在敏捷迭代的過程中需要能夠快速的把開發(fā)的代碼集成打包部署到各個(gè)環(huán)節(jié)對(duì)應(yīng)的環(huán)境中。為了高效穩(wěn)定的完成這個(gè)工作,我們引入了DevOps實(shí)踐理論,并形成了配套的CI/CD工具。本文將介紹云創(chuàng)的CI/CD工具如何演進(jìn)的過程。
一 、傳統(tǒng)構(gòu)建
? ? 在最開始階段,訴求很簡(jiǎn)單。將gitlab的代碼自動(dòng)部署到測(cè)試,預(yù)發(fā)布環(huán)境。當(dāng)時(shí)市面上這類工具也不多,基本掃一遍大部分都是用jenkins。自然而然也就選用了jenkins,畢竟有問題google,baidu起來也容易找到答案。
? ? 由于這個(gè)時(shí)期面對(duì)的是php和開發(fā)同學(xué)在本地編譯好的js。對(duì)于Jenkins的應(yīng)用就十分簡(jiǎn)單,在界面給配置倉(cāng)庫(kù)和分支再用ssh工具給rsync到對(duì)應(yīng)的服務(wù)器。后續(xù)再就是再加裝一些插件做下sonar掃描,做一些參數(shù)配置構(gòu)建。基本上都還是一些十分基礎(chǔ)的使用也就不在占用過多篇幅了。
二 、流水線
? ? 隨著云創(chuàng)開始推動(dòng)DevOps,原有的構(gòu)建方式想覆蓋代碼到制品交付的全過程有比較大的難度。為了DevOps的推進(jìn)工作,必須引入具備pipeline能力的工具。
2.1、Jenkins2-流水線執(zhí)行器
? ? DevOps越來越火,市面上也出現(xiàn)很多CI/CD工具,同時(shí)jenkins也推出了2.0版本。我們對(duì)一些工具也做了一些嘗試(gitlab-ci,drone),有很多工具的理念確實(shí)很好,最終我們還是選擇了jenkins2.0來實(shí)現(xiàn)我們的pipeline。主要如下幾個(gè)原因:
定義方式:Jenkins支持腳本式的定義流水線,其他的都是聲明式。這樣看Jenkins的靈活度更高
生態(tài):Jenkins社區(qū)有幾千個(gè)插件提供了各種各樣的能力,其他工具都需要自己想辦法實(shí)現(xiàn)這些能力。
門檻:Jenkins文檔豐富并且我們也一直在使用,相對(duì)來說門檻是最低的。
成熟度:Jenkins已經(jīng)發(fā)展了十多年完全具備生產(chǎn)可用的條件,其他產(chǎn)品都還沒到生產(chǎn)就緒狀態(tài)。
2.2、基于Kubernetes的動(dòng)態(tài)構(gòu)建環(huán)境
? ? 隨著團(tuán)隊(duì)對(duì)于質(zhì)量的要求逐漸變高(單測(cè),sonar,api測(cè)試,等等),開發(fā)語言也不再只是解釋型語言,前端專業(yè)線也有源碼直接在線完成編譯打包的訴求等等一系列原因。構(gòu)建所需要的環(huán)境開始成為我們需要考慮的問題了,基于過往認(rèn)知我們列出了下列方案:
在jenkins的master節(jié)點(diǎn)安裝所有需要的工具以及語言環(huán)境 。
常備幾臺(tái)ecs作為slave節(jié)點(diǎn),每臺(tái)負(fù)責(zé)一到兩種語言的構(gòu)建任務(wù)。
利用docker插件在啟動(dòng)構(gòu)建任務(wù)時(shí)拉取準(zhǔn)備好的環(huán)境鏡像運(yùn)行容器進(jìn)行構(gòu)建。
? ? 這幾個(gè)方案都面臨環(huán)境的管理的問題,都需要在鏡像或者機(jī)器里面準(zhǔn)備好 sonar,各種語言的單元測(cè)試環(huán)境,api測(cè)試工具這些,每一次步驟的改變或者工具的版本升級(jí)都可能需要去折騰一遍鏡像或者機(jī)器。這會(huì)給后期帶來高昂的維護(hù)成本,所以必須找到更好的方案。在Jenkins插件倉(cāng)庫(kù)中發(fā)現(xiàn)了解題思路kubernetes-plugin。kubernetes-plugin可以在構(gòu)建開始時(shí)調(diào)用K8S的接口創(chuàng)建一個(gè)POD作為slave來進(jìn)行構(gòu)建任務(wù),POD是一組容器的集合這一組容器能共享網(wǎng)絡(luò)和文件。利用kubernetes-plugin有了下圖的設(shè)計(jì):
? ? 在定義pipeline的時(shí)候按照需求把需要的鏡像組合一下。這樣只需要維護(hù)一些環(huán)境很單一的鏡像即可,新增步驟或者改變工具或環(huán)境版本只是加多一個(gè)鏡像或者改一個(gè)鏡像tag。
? ? 在每次任務(wù)啟動(dòng),都會(huì)在集群節(jié)點(diǎn)啟動(dòng)一個(gè) Slave 的 Pod 容器組進(jìn)行任務(wù)構(gòu)建,構(gòu)建完成后容器自動(dòng)銷毀。
2.3、利用shared library實(shí)現(xiàn)參數(shù)化定義流水線
? ? 基于上面的動(dòng)態(tài)環(huán)境的方案,我們嘗試開始定義了幾條流水線我們意識(shí)到了問題,需要寫大量的groovy腳本并且業(yè)務(wù)團(tuán)隊(duì)很難自己寫好這些腳本,這樣流水線的落地會(huì)變的很艱難。需要尋找一個(gè)好的辦法來解決這些問題,shared library可以很好的解決這個(gè)問題。
? ? 所有的job的定義都是一樣的,都是加載shared library并運(yùn)行,shared library根據(jù)參數(shù)給出的信息來運(yùn)行流水線。
? ? 這樣就不需要每個(gè)項(xiàng)目維護(hù)一個(gè)腳本而是維護(hù)一些簡(jiǎn)單的參數(shù)即可,所有項(xiàng)目共用shared library如果有些調(diào)整也能夠統(tǒng)一調(diào)整。
? ? 采用了這種模式,云擎實(shí)現(xiàn)流水線管理只管理參數(shù),不需要跟jenkins深度耦合。
? ? 基于jenkins2.0和Kubernetes我們實(shí)現(xiàn)了可以動(dòng)態(tài)生成構(gòu)建環(huán)境,能快速接入新任務(wù)并且能夠統(tǒng)一調(diào)整的pipeline構(gòu)建系統(tǒng)。
三 、低成本高并發(fā)的彈性構(gòu)建
? ? Pipeline全面推廣并且所有業(yè)務(wù)團(tuán)隊(duì)接入云擎使用特性分支的開發(fā)方式,每次特性合并觸發(fā)構(gòu)建會(huì)同時(shí)觸發(fā)多個(gè)倉(cāng)庫(kù)進(jìn)行構(gòu)建,這樣一下給構(gòu)建用的集群帶來了極大的壓力發(fā)生多次崩潰。只能先控制并發(fā)構(gòu)建的數(shù)量,然后立馬開始進(jìn)行優(yōu)化。
3.1、Kubernetes節(jié)點(diǎn)自動(dòng)伸縮
? ? 第一個(gè)嘗試的方案是對(duì)構(gòu)建集群配置節(jié)點(diǎn)自動(dòng)伸縮。
? ? 節(jié)點(diǎn)自動(dòng)伸縮組件是基于 kubernetes 資源調(diào)度的分配情況進(jìn)行伸縮判斷的,節(jié)點(diǎn)中資源的分配是通過資源請(qǐng)求(Request)進(jìn)行計(jì)算的。當(dāng) Pod 由于資源請(qǐng)求(Request)無法滿足并進(jìn)入等待(Pending)狀態(tài)時(shí),節(jié)點(diǎn)自動(dòng)伸縮組件會(huì)根據(jù)配置的彈性伸縮組配置信息中的資源規(guī)格以及約束配置,計(jì)算所需的節(jié)點(diǎn)數(shù)目,如果可以滿足伸縮條件,則會(huì)觸發(fā)伸縮組的節(jié)點(diǎn)加入。當(dāng)一個(gè)節(jié)點(diǎn)在彈性伸縮組中且節(jié)點(diǎn)上 Pod 的資源請(qǐng)求低于閾值時(shí),節(jié)點(diǎn)自動(dòng)伸縮組件會(huì)將節(jié)點(diǎn)進(jìn)行縮容。因此只需要資源請(qǐng)求(Request)的正確、合理設(shè)置,開啟自動(dòng)伸縮功能就具備了節(jié)點(diǎn)自動(dòng)伸縮的能力。
? ? 下圖只是設(shè)置集群縮容的閾值:
? ? 設(shè)置好節(jié)點(diǎn)自動(dòng)伸縮,問題并沒有很好的解決,因?yàn)樾碌墓?jié)點(diǎn)就緒需要時(shí)間比較長(zhǎng)(分鐘級(jí)別接近十分鐘),當(dāng)新節(jié)點(diǎn)準(zhǔn)備就緒的時(shí)候已經(jīng)有一部分構(gòu)建完成了,后續(xù)的構(gòu)建任務(wù)可以直接在原有的節(jié)點(diǎn)執(zhí)行。實(shí)際上結(jié)果就是節(jié)點(diǎn)擴(kuò)充出來了卻不在需要這些節(jié)點(diǎn)了。
3.2、Serverless
? ? 流水線構(gòu)建屬于高度動(dòng)態(tài)的行為,為了動(dòng)態(tài)的構(gòu)建操作而維護(hù)一個(gè)固定的計(jì)算資源池對(duì)成本是不利的,但是沒有固定的計(jì)算資源又會(huì)導(dǎo)致響應(yīng)延遲。有沒有好的辦法能兼顧呢?serverless-kubernetes集群解君愁。
? ? 在介紹serverless-kubernetes集群之前,有必要先了解一個(gè)項(xiàng)目Virtual Kubelet。
? ? Virtual Kubelet的作用很簡(jiǎn)單,就是將各大公有云廠商提供的容器服務(wù)與K8S的apiserver打通,實(shí)現(xiàn)通過K8S的api編排云廠商的無服務(wù)器容器服務(wù)(如:AWS的Fargate,Azure的ACI,阿里的ECI等)。原理上就是向K8S的apiserver注冊(cè)一個(gè)偽造的kubelet(相當(dāng)于加入一個(gè)節(jié)點(diǎn))接收apiserver調(diào)度過來的pod,只不過真實(shí)的kubelet接收到負(fù)載之后是在自身管理的node上進(jìn)行啟動(dòng)pod等操作,Virtual Kubelet接收到負(fù)載后調(diào)用注冊(cè)的api。下圖是Virtual Kubelet官網(wǎng)的架構(gòu)描述:
? ? 阿里云提供兩種形態(tài)的Virtual Kubelet應(yīng)用,一種是對(duì)真實(shí)節(jié)點(diǎn)的集群加入一個(gè)Virtual Kubelet進(jìn)行擴(kuò)展,一種是完全無真實(shí)節(jié)點(diǎn)node在托管的master節(jié)點(diǎn)下面掛載Virtual Kubelet實(shí)現(xiàn)serverless-kubernetes集群。
? ? Serverless 集群中只有 pod 運(yùn)行時(shí)才會(huì)收費(fèi)精確到秒,這意味著我們不需要準(zhǔn)備固定的計(jì)算資源等待構(gòu)建任務(wù)。同時(shí)又提供了可以快速啟動(dòng)容器的能力,這就解決了響應(yīng)延遲的問題。
? ? Serverless也有一個(gè)限制導(dǎo)致我們并不能直接使用,為了安全ECI是不允許運(yùn)行的容器掛載宿主機(jī)的docker.sock。這樣之前將宿主機(jī)的docker.sock掛載到容器內(nèi)再使用docker build命令構(gòu)建docker鏡像的方式就行不通了。這一點(diǎn)導(dǎo)致利用Serverless進(jìn)行構(gòu)建的想法一直沒有落地,直到我們找到了google開源的鏡像構(gòu)建工具kaniko,kaniko的構(gòu)建方式和工作原理與docker build十分類似,只不過不需要docker.sock和root權(quán)限,并且支持更多的參數(shù)使用起來更方便。搞定docker鏡像構(gòu)建的問題后,立馬全面應(yīng)用了serverless集群進(jìn)行構(gòu)建。
? ? 為了使用Kaniko也費(fèi)了一番功夫,這里就不詳細(xì)描述踩過的坑了,有需要的可以找我們直接要可用的方法即可。
3.3 、slave啟動(dòng)速度優(yōu)化
? ? Serverless應(yīng)用之后,雖然成本問題和并發(fā)問題都很好的解決了。不過新的問題出現(xiàn)了,單次構(gòu)建的耗時(shí)比較長(zhǎng),經(jīng)過分析發(fā)現(xiàn)主要耗時(shí)在啟動(dòng)slave的時(shí)候拉取鏡像比較耗時(shí)(平均約三分鐘),因?yàn)镋CI是沒有持久化存儲(chǔ)。在釘釘上跟ECI的產(chǎn)品經(jīng)理提出了我們的訴求,希望ECI能夠提供把鏡像持久化的功能避免每次都要花費(fèi)大量時(shí)間拉取鏡像。
? ? 給ECI團(tuán)隊(duì)提出了訴求之后等待了三個(gè)月,他們終于給出了一個(gè)解決方案—鏡像緩存(imc)同步在K8S這邊提供了對(duì)應(yīng)的CRD。鏡像緩存的工作原理就是在ECI實(shí)例啟動(dòng)時(shí)掛載一個(gè)包含用戶定義的鏡像的磁盤,ECI實(shí)例就可以在本地直接使用鏡像啟動(dòng)容器。
? ? 定義緩存鏡像例子:
apiVersion: eci.alibabacloud.com/v1 kind: ImageCachemetadata name: imagecache-jenkinsspec images: - registry-vpc.cn-hangzhou.aliyuncs.com/example-jnlp:kaniko - ...... - ...... imageCacheSize: 20? ? 將該功能實(shí)裝之后,之前需要耗時(shí)約三分鐘拉取鏡像的動(dòng)作現(xiàn)在變成命中緩存啟動(dòng)容器,整個(gè)slave啟動(dòng)時(shí)間從之前的三分鐘以上優(yōu)化到半分鐘到一分鐘完成。
? ? 在嘗試Serverless的方案時(shí)還遇到了一些阻礙性的問題,我們將問題反饋到阿里產(chǎn)品團(tuán)隊(duì)后都及時(shí)得到了解決,目前來說只需要使用最新版本的Serverless集群按照我們的方案已經(jīng)不存在這些問題了,所以這里也就不再浪費(fèi)篇幅了。
四、未來展望
? ? 完成這個(gè)優(yōu)化之后,整套構(gòu)建方案中需要解決的大問題都被解決掉了,實(shí)現(xiàn)了一個(gè)生產(chǎn)可用低成本高并發(fā)能力的構(gòu)建系統(tǒng)。之后主要是增強(qiáng)功能提高系統(tǒng)可用性兩個(gè)方向進(jìn)行優(yōu)化:
云擎整合多個(gè)jenkins-master節(jié)點(diǎn)統(tǒng)一管理,構(gòu)建任務(wù)按照標(biāo)簽匹配master運(yùn)行并保持至少有2臺(tái)master可以匹配。
云擎具備自動(dòng)創(chuàng)建master以及構(gòu)建用serverless-k8s集群的能力。
優(yōu)化shared library,可以更加靈活的定義每一個(gè)流水線步驟。
------ END ------
作者簡(jiǎn)介
尹同學(xué):?運(yùn)維負(fù)責(zé)人,目前負(fù)責(zé)明源云SaaS產(chǎn)品的后臺(tái)運(yùn)維工作。
也許您還想看
云客大數(shù)據(jù)架構(gòu)實(shí)踐
云客大數(shù)據(jù)管理保障體系
回歸統(tǒng)計(jì)在DMP中的實(shí)戰(zhàn)應(yīng)用
k8s中流量分離以及資源隔離實(shí)戰(zhàn)
研發(fā)協(xié)同平臺(tái)持續(xù)集成Jenkins作業(yè)設(shè)計(jì)演進(jìn)
總結(jié)
以上是生活随笔為你收集整理的明源云创CI/CD技术演进的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 5G发展是绵绵秋雨 应循序渐进
- 下一篇: Blazor带我重玩前端(五)