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