您好,登錄后才能下訂單哦!
本篇內容主要講解“基于Jenkins和Kubernetes的CI工作流怎么實現”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“基于Jenkins和Kubernetes的CI工作流怎么實現”吧!
摘要
Jenkins作為最為流行的持續集成工具,在結合使用容器技術,Kubernetes 集群的基礎上,該如何發揮出新的能力, 在應用微服務化的基礎上,提供更好的CI方式,值得我們每一個開發人員去持續不斷的摸索。
Jenkins 和 Kubernetes
Jenkins作為最流行的持續集成工具,有著豐富的用戶群、強大的擴展能力、豐富的插件,是開發人員最為常見的CI工具。在Jenkins 加強其Pipeline功能后,更是可以通過豐富的step庫,實現各種復雜的流程。同時隨著Docker的流行,Jenkins內也增加了對Docker的支持,可以實現容器內流程的執行。
而Kubernetes隨著版本迭代的速度越來越快,在容器圈內的熱度也越來越高,同時每次版本發布,所新增的功能也不斷增加。做為當前主流的容器管理平臺,其強大的能力無需在此多做介紹。
應用容器化和應用微服務化設計思考
容器化不意味著微服務化,傳統單體應用也可以容器化,但是很難享受到容器化后帶來的好處。微服務化也不是一定要容器化,應用拆解為微服務后,一樣可以不利用容器而是通過傳統的運維來完成系統構建和部署。當微服務化和容器化相結合之后,就能充分利用各方優勢,帶來了彈性伸縮,簡化部署,易于擴展,技術兼容等優點。
我們在針對應用進行微服務化拆分的過程中,主要先考慮到的是功能點、控制對象、開發組的人員配置安排,產品路線圖規劃等。例如,針對現有開發組人員人數、分配和各自的技能熟練程度,就可以考慮到服務模塊數量的控制,安排好服務模塊開發小組;針對功能點和中遠期產品規劃,就可以將特定功能歸納到一個服務模塊中,并在版本開發迭代的過程中,通過擴展這個服務模塊的能力,來完成產品功能的開發,或者暫時將部分功能整合在一個模塊中,隨著功能增加或迭代開發,再進行進一步的模塊拆分或拆解。
對于模塊開發的要求,由于使用了容器技術,對于開發語言或特定框架的選型,可以交給具體的模塊開發人員。在團隊內,我們不做強制要求,但是做建議要求,避免出現過多的技術棧,導致后期的維護困難。在我們團隊內,就只集中在兩種后端開發語言的使用,相應的框架或主要的開發庫,也都有相應而且明確的選擇。對于模塊的API接口,使用REST,并且至少按照成熟度模型LEVEL2提供API。
容器環境下的編譯和單元測試
我們整個CI工作流的驅動,都是由Jenkins完成,并且使用了Jenkins Pipeline。第一,Pipeline可以更好的組合job內的Stage,重復利用模塊間相同的部分,并且隨著開發復雜度的增加來逐步增加擴展stage,實現更多所需的功能;第二,將Pipeline Groovy腳本來源設置為源代碼內,可以根據源代碼功能點來控制流程,同時也完成了對腳本的版本管理。
由于有容器這么個工具,我們各個模塊的編譯環境,單元測試環境,也都放到了容器中。各個模塊均可以安裝自身模塊的運行特性或環境要求,準備自身的編譯環境、單元測試環境、運行環境,因此,代碼庫內會分別留存相應的Dockerfile,通過不同的Dockerfile完成不同環境鏡像的準備。
同時,jenkins現在也可以通過Docker Pipeline插件,支持在容器內運行Step,因此我們利用其功能完成的實際的編譯和測試流程是這樣的:
1. 使用編譯環境的Dockerfile構建編譯環境鏡像。
2. 使用編譯環境鏡像啟動容器并在容器內完成編譯,完成編譯的中間產物也暫存在Workspace中。
3. 使用測試環境的Dockerfile構件單元測試環境鏡像。
4. 使用單元測試環境鏡像啟動容器并在容器內運行單元測試,單元測試腳本來源于代碼庫,同時也使用到編譯時生成的中間產物。
5. 使用發布Dockerfile構建實際發布鏡像并上傳鏡像庫。
其中由于編譯環境和單元測試環境不是經常變更,也可以抽出編譯環境鏡像準備和單元測試環境鏡像準備兩個步驟放到獨立的CI job中去,需要時手工觸發即可。
服務部署和升級
對于CI流程,在完成編譯和打包后,需要做的就是服務啟動和測試了。我們利用的是Kubernetes Deployment和Service,在每次CI流程完成編譯和打包后,通過拿到Build號,作為鏡像的Tag,完成鏡像的上傳歸檔;同時利用Tag,修改Kubernetes中已經創建的Deployment,利用Deployment的Rolling Update,完成升級。
對kubernetes服務模版和服務配置的擴展
我們在實際使用Kubernetes Deployment 升級的方式進行服務部署的過程中,發現其中還是存在很多不方便的地方。例如:Kubernetes內的同名問題,Kubernetes Deployment升級時的鏡像tag變更問題,等等各處需要隨著CI流程可能存在變更的地方。例如在有相同名字的Deployment存在的情況下,后來的Deployment會無法創建,這導致如果想以啟動新的Deployment的方式來測試某個版本,需要修改名稱,對于與Deployment相關的Service也一樣,在啟動新的命名后的Deployment,也需要啟動與其對應的Service用于暴露服務。對于Deployment升級所需的鏡像Tag修改,需要每次隨著CI生成了新的鏡像Tag而做變更,因而每次需要修改相應Yaml文件內的鏡像Tag,修改為實際CI流程中生成的值,然后再使用升級功能完成服務升級。
針對這些問題,我們使用了一套文本模板引擎,部署或升級用的Yaml文件本身寫成為模板,可能有變化或者需要根據CI流程變化的位置,使用模板標識占位,而具體的模板數據內容,則或者通過Jenkins的CI流程獲取,或者使用特定的配置文件讀取,或者從具體的輸入參數來獲取;同時,模板數據內容,也會在實際部署時,做為Kubernetes的Configmap設置到系統中,因此數據內容也可以通過Kubernetes使用Configmap的方式來用到環境變量或啟動命令中。通過文本模板引擎,將模板和數據合并后,生成的Yaml文件,再作為后續Kubernetes操作所使用的內容。
通過利用這種方式,我們把需要部署的內容分離成了模板和配置;模板一般在服務架構,使用的鏡像名,啟動方式或配置參數沒有大的變化的情況下保持不變,而通過不同配置的靈活使用,完成服務升級或拉起新部署,完成不同數據存儲使用的指向,完成對各模塊內部配置的修改。通過利用這種方式,我們的可修改的內容,從Configmap本身只能覆蓋到的環境變量或啟動命令這塊,擴展到了啟動名稱,Label,鏡像等Yaml文件內的各個可填值處,以此來解決同名,鏡像修改,Label增加或變更等各種使用Kubernetes時碰到的問題。
自動化測試
在通過Jenkins拉動完成編譯打包和服務升級部署后,就可以拉動自動化測試了。測試框架我們選擇了使用Robotframework。測試腳本通過Kubernetes Service獲取到服務的具體暴露端口,然后再根據測試腳本依次執行針對API的測試。測試腳本的來源,部分是從各模塊代碼庫中,由各模塊開發人員提交的針對自身模塊的api測試,部分是由測試人員完成撰寫提交的針對跨模塊的測試。針對自動化測試這塊,我們的完成度并不是很高,僅僅是搭建起了基本的運行框架,能夠與整個流程對接上。
版本發布
由于開發的產品本身就是由若干鏡像構成,因此產品發布,可以歸結為鏡像的發布。在測試通過后,可以簡單的利用鏡像復制能力,將測試通過的相關鏡像的版本,通過鏡像庫間的復制,由開發測試所用的內部鏡像庫,復制到外部發布鏡像庫,就可以完成版本發布,同時可以通過復制時的Tag控制,發布為指定的版本號。
總結
如上介紹,說明了我們在自身開發過程中建立CI流程的做法。對于整個流程的建立,我們并沒有太多需要特殊化處理的地方;對于各項工具的使用,也沒有太多突出之處;我們僅僅根據自身需求,建立了和開發過程適配的ci流。在此介紹我們的ci流程的建立,也是希望拋磚引玉,能從更多處獲得交流和向大家學習的機會。
Q&A
Q1:嘉賓分享的內容還是概括了些,有沒有具體例子?配圖說明的直觀內容?
A:基于K8s的CICD產品即將發布,會提供對應的Demo演示平臺,請及時關注,謝謝!
Q2:關于Jenkins和Docker集成的幾個插件可以分享一下嗎?
A:Docker Pipeline、Docker Plugin、Docker-build-step 這幾個插件。
Q3:請問有容云的鏡像復制大體思路是什么?目前我們是測試、預發布、發布共享一個倉庫。通過輔助模塊標簽實現的!
A:鏡像復制功能,簡單來說實現了不同項目間的鏡像克隆,根據我們鏡像倉庫的設計,對不同階段(開發,測試,可上線)的鏡像以不同項目分類,基于鏡像復制功能即可快速實現不同階段的產品發布,也就是鏡像發布,此功能可下載AppHouse版本進行試用。
Q4:貴公司同步的嗎?你們的配置文件是通過配置中?你們的配置文件是通過配置中心管理還是鏡像間的環境變量實現的?
A:不是實時同步的,而是通過了我們公司鏡像庫產品的鏡像復制能力實現的。目前開發流程中的產品運行配置是通過自身增強的配置文件能力實現的,配置會用來修改應用部署的Yaml文件,也會生成為Configmap。
Q5:有沒有一個簡單的Sample?可以上手跟著練習一下。
A:基于K8s的CICD產品即將發布,會提供對應的Demo演示平臺,請及時關注,謝謝!
Q6:此次內容的Step by step 示例,能提供一個Demo嗎?
A:基于K8s的CICD產品即將發布,會提供對應的Demo演示平臺,請及時關注,謝謝!
Q7:我的項目的版本二只是修改了幾個頁面,也是和第一次發布一樣的流程嗎?
A:是的,流程化就是代表著可重復和可自動化,而無需去關系具體的修改內容。
Q8:你們部署的K8s版本是哪個?K8s的調度服務只能覺得容器起在哪個節點上吧,Rc是2的話,構建任務運行在哪個容器中這個怎么調度,為什么我的都運行在一個容器里面?
A :我們目前使用的是Kubernetes1.5版本。本身構建任務不是跑在Kubernetes上的,而只是應用自身跑在Kubernetes上。
Q9:你們是類似于Openshift那種平臺式的嗎?還是需要開發人員自己部署?
A :本身講的是我們自身產品開發的流程,相關的產品會是類似平臺型產品,需要自行部署,而不是公有云產品。
Q10:兩個框架是開源的嗎?
A :是的,都是開源的。
Q11:K8s的Yaml的部署文件的模板怎么去替換占位符?舊版本的容器怎么處理?
A :使用了自身開發的一套文本模板引擎,其實類似Web框架中的模板引擎,完成模板和配置的合并,通過使用配置中的key-value,替換掉模板中key的占位符。另外由于是使用的K8s Deployment的Rolling Update,升級完成后舊版本的容器/Pod會由Kubernetes自行刪除。
Q12:開發測試、部署等各個階段的鏡像,方便共享一下嗎?
A :這些鏡像都是我們自身針對我們各應用模塊所準備的,對其他人并沒有什么用處,編譯環境用的鏡像不少就是官方鏡像,例如Golang:1.7, Python:2.7。
Q13:傳統單體應用如何容器化改造,可否分階段實施?
A : 可以的,容器化改造或微服務化改造有很多實施方法,例如逐漸重構拆解,或新增模塊進行微服務化和容器化,或開發新的模塊替代原有應用的功能點,等等。各團隊均可以選擇合適自身的流程來進行改造。
Q14:數據庫可以容器化嗎?
A :可通過將數據卷掛入容器的方式將數據庫容器化,但是現在實際項目中還很少見。
Q15:我們目前也是使用jenkins動態掛載容器來運行安卓編譯構建作業,但現在每次使用鏡像生成容器后因為要更新代碼,導致整體編譯時間比以前使用物理機方式要延長10多分鐘,我們的鏡像每天自動制作和下載,但因為代碼更新太快及并發太多,編譯時需要獨占物理機,所以機器占用也很多,大家有什么建議解決這個問題,謝謝!
A :容器化編譯就是將編譯環境封裝起來了,這種情況下一臺物理機同步跑多個Job也行,可以看看怎么提高對物理機的利用率。
Q16:請問項目中存在多個鏡像,是如何做關聯發布的?
A :我們是使用了Jenkins的Mutil Pipeline,另外由于我們的模塊的微服務拆解,對應同步發布鏡像的需求并不高。
Q17:有這樣一個場景,兩個服務有依賴關系,服務A依賴于服務B,如何保證服務A和B的啟動順序的?
A :良好的設計是使得A服務啟動后自行完成對B服務的檢測發現和調用,而不是強依賴其啟動順序。
Q18:Kubernetes的服務的模板和配置,這個模板怎么來的,是用戶自己編排?還是自己事先準備好的?配置數據是怎么存儲的?
A : 因為當前模板和配置只用來啟動我們自身開發的應用,因此這個模板是我們自己為我們的應用準備的。配置數據以文件的形式存儲,但同時在使用文本引擎做模板和配置合并時,也可以接受參數作為配置。
Q19:什么是CI和CD?
A : CI更多是偏向應用編譯、代碼檢查、單元測試等動作,CD是偏向于應用部署、運行流程,我們的開發過程在編譯打包完成后,實際也會將應用跑起來用于測試,也可以算是針對測試的CD。
Q20:使用容器打包Jenkins流程的主要收益是什么?
A : 由于不同程序對于編譯環境的依賴各有不同,原有使用Jenkins方法是在Jenkins Node上完成環境準備,現在可以利用容器完成環境準備,對于Jenkins Node的依賴可以進一步降低。同時環境變更也可以由開發人員自行控制。
Q21:多編譯環境是用的不同鏡像么?如何處理pipeline處理編譯環境的問題?
A : 是的。由于我們本身產品開發各個模塊有各個模塊的開發語言和框架,因此各模塊都要維護自身的編譯環境鏡像。使用Pipeline在進行編譯時,是通過使用鏡像運行容器然后在容器內編譯的方式來使用編譯環境的。
Q22:產品發布的產出為鏡像,如果有很多鏡像,最終會在鏡像上打上統一的Tag么代碼上的Tag什么時機打呢?
A : 我們是在產品發布時,進行鏡像復制時統一打發布Tag的,這時候從開發測試庫會復制到發布庫,利用了我們公司自身鏡像庫產品的鏡像復制能力。
Q23:請問Jenkins 也是部署在Docker里面的嗎?如果Jenkins在Docker里面怎么樣在Docker里面使用Docker執行CI?
A : 是的,我們也在摸索將Jenkins本身放到容器中運行。在這種情況下,Jenkins容器內使用Root權限,掛載Docker.Sock和Docker數據目錄到容器中就可以了。
Q24:使用Pipeline先構建編譯環境鏡像,再編譯,是否會導致整個流程需要很長時間?是否有優化方案?
A :編譯鏡像由于不會經常變動,因此這個鏡像的構建通常使用Cache就能直接完成。另外我們也把編譯環境鏡像打包這個步驟抽出來單獨作為Job執行了,這樣在實際編譯流程中就無需再進行編譯環境構建。
Q25:直接使用Jenkins的Docker插件和直接調用腳本,自己寫Docker命令,如何在靈活程度和方便程度上做權衡?
A :看個人或開發團隊的自行權衡吧,只是開發團隊內最好統一,便于進行相應維護。
Q26:Jenkins和Kubernetes的用戶是怎么管理的?我的期望是用戶只能看到自己得資源,別的用戶是沒有權限的。
A : 我們本身只是使用這兩種工具,在開發環境中不對外,所有不存在用戶管理的問題。在我們公司正在開發的CICD產品中,對這塊有我們自身理解基礎上的設計。
Q27:Jenkins的持續集成是怎么實現的?比如不同的源碼倉庫的提交觸發,如Github gitlab,版本號怎么控制的?
A : Jenkins的CI流程觸發可以有很多種,代碼提交觸發、定時觸發、手動觸發。版本號的控制也可以有很多方案,比如使用Job的編號、使用Git的Commit號、使用時間戳等等。
Q28:Jerkins 調用K8s API 用了什么插件么?
A :沒有直接使用Jenkins調用Kubernetes API。
Q29:Jenkins的Pipeline支持流水線執行,一般從頭開始執行,可以從流水線中任意一步執行嗎?
A : 因為我們團隊的Jenkinsfile都是直接放置在代碼庫內的,因此每次執行都是從頭完成流水線的執行。
Q30:容器化后發布也要通過Jenkins,感覺Docker的發布沒有Jenkins方便,除了容器化的可移植,還有什么原因值得推進項目容器化?
A : 應用容器化,其實更多的是看重應用在容器管理平臺上運行起來后所獲得的能力,例如在Kubernetes上運行后的水平擴展,服務發現,滾動升級,等等。
Q31:K8s Update需要制定新的鏡像才能做滾服更新(升級),如果只是更新了Configmap,有辦法做滾服更新嗎?
A : 我們的CI流程完成后,各模塊的鏡像Tag會發生變化,我們利用具體生成的Tag生成配置,然后部署的Yaml文件寫為模板,鏡像的具體Tag會根據每次CI流程生成的配置不同而組合為不同的Yaml文件,然后使用組合后的Yaml,即Tag已經變更為最新版本的Yaml文件進行應用的滾動升級。
Q32:Pipeline采用在鏡像里構建的方案,是怎么實現的?用Jenkins現成的插件 or 用Groovy腳本實現?
A :使用了Jenkins的Docker插件,同時使用方式是將相應命令寫在Groovy腳本里。
例如:stage('Build'){ docker.image('golang:1.7').inside { sh './script/build.sh' } }
到此,相信大家對“基于Jenkins和Kubernetes的CI工作流怎么實現”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。