持續(xù)集成是一種軟件開發(fā)實(shí)踐。在一個(gè)團(tuán)隊(duì)中開發(fā)人員經(jīng)常會(huì)對(duì)他們的工作進(jìn)行集成,這個(gè)頻率通常為每人每天至少集成一次,這也就意味著一個(gè)團(tuán)隊(duì)每天可能會(huì)面臨著多次集成。
在進(jìn)行集成時(shí),團(tuán)隊(duì)成員會(huì)通過自動(dòng)化地構(gòu)建,包括編譯、發(fā)布、自動(dòng)化測(cè)試,來(lái)驗(yàn)證。在這個(gè)過程中團(tuán)隊(duì)成員可以盡快地發(fā)現(xiàn)集成錯(cuò)誤,使團(tuán)隊(duì)能夠更快地開發(fā)內(nèi)聚的軟件。
基于此,一般的互聯(lián)網(wǎng)公司或者開發(fā)團(tuán)隊(duì)都會(huì)有自己的持續(xù)集成平臺(tái)或者工具,而開源的持續(xù)集成工具如 jenkins,teamcity,gitlab ci 等都提供了持續(xù)集成的功能。
但這些工具的使用一般都較為復(fù)雜,流程編排會(huì)比較長(zhǎng)。
而 Docker的存在使得持續(xù)集成擺脫了以往打通環(huán)境、資源申請(qǐng)、軟件部署等帶來(lái)的痛苦,可以更加快速方便地對(duì)既有工作成果進(jìn)行持續(xù)集成。
基于Docker的持續(xù)構(gòu)建
一般來(lái)講,用戶往往會(huì)選擇對(duì)代碼倉(cāng)庫(kù)的某一些特定分支進(jìn)行持續(xù)集成,從而快速地對(duì)當(dāng)前代碼進(jìn)行驗(yàn)證。
而在持續(xù)集成中,持續(xù)地對(duì)代碼進(jìn)行構(gòu)建是整個(gè)持續(xù)集成的基礎(chǔ)。
目前,大部分公司都是基于 mvn和 ant等編譯打包工具來(lái)實(shí)現(xiàn)內(nèi)部的編譯構(gòu)建服務(wù)。公司使用自己的 mvn等工具對(duì)倉(cāng)庫(kù)進(jìn)行編譯構(gòu)建不存在任何問題,但是編譯后的可執(zhí)行文件分發(fā)與運(yùn)行卻比較復(fù)雜。
常規(guī)的做法是通過 SCP腳本傳輸,或者內(nèi)部開發(fā) agent等工具用于可執(zhí)行文件的部署,但這增加了軟件開發(fā)部署的代價(jià),尤其對(duì)于中小型公司,就需要自己研發(fā)部署工具。而且:
- 在公有云平臺(tái)如果要提供一個(gè)持續(xù)集成的構(gòu)建服務(wù)給用戶,會(huì)面臨如何獲取用戶的可執(zhí)行文件并進(jìn)行運(yùn)行的問題;
-需要部署相關(guān)環(huán)境,比如一個(gè) tomcat應(yīng)用需要安裝 jdk以及環(huán)境變量,還有其他的用戶依賴組件等。
而一個(gè)基于 docker實(shí)現(xiàn)持續(xù)構(gòu)建的平臺(tái)可以很方便地解決上述問題:
- docker通過鏡像來(lái)進(jìn)行分發(fā),不僅擺脫了執(zhí)行文件分發(fā)的問題,也解決了環(huán)境問題(docker不依賴于具體環(huán)境);
- docker通過 dockerfile來(lái)進(jìn)行構(gòu)建,給了用戶很大的編譯自由,用戶可以很方便地安裝環(huán)境及相關(guān)軟件;
- docker運(yùn)行非??焖?,一臺(tái)宿主機(jī)可以運(yùn)行多個(gè) docker容器。
網(wǎng)易蜂巢的持續(xù)構(gòu)建實(shí)現(xiàn)
接下來(lái)介紹一下蜂巢的持續(xù)構(gòu)建實(shí)現(xiàn)以及具體的使用方法。
用戶可以把代碼托管在 github或者 gitlab等代碼倉(cāng)庫(kù),通過使用網(wǎng)易蜂巢的持續(xù)集成服務(wù),實(shí)時(shí)快速地對(duì)代碼進(jìn)行編譯和打包生成鏡像。對(duì)于鏡像的發(fā)布運(yùn)行,用戶可以在蜂巢部署鏡像,也可以從蜂巢鏡像倉(cāng)庫(kù)拉取鏡像到其他支持 docker的環(huán)境進(jìn)行部署。
持續(xù)構(gòu)建服務(wù)主要包括以下模塊:
- oauth2模塊。用戶 oauth2綁定,綁定用戶身份;
- hook模塊。hook服務(wù)用于監(jiān)聽用戶的代碼 commit;
- 構(gòu)建模塊。持續(xù)構(gòu)建服務(wù)基于 dockerfile,用于鏡像的構(gòu)建;
- 鏡像倉(cāng)庫(kù)。鏡像倉(cāng)庫(kù)用于鏡像的存儲(chǔ),分布式對(duì)象存儲(chǔ)解決文件的高可用;
- callback回調(diào),callback用于鏡像元信息的存儲(chǔ);
網(wǎng)易蜂巢持續(xù)構(gòu)建系統(tǒng)設(shè)計(jì)圖如下所示:
那么,如何實(shí)現(xiàn)整個(gè)構(gòu)建的流程?用戶可以登錄網(wǎng)易蜂巢,進(jìn)入鏡像倉(cāng)庫(kù)進(jìn)行以下操作:
第一步:創(chuàng)建鏡像倉(cāng)庫(kù)
Docker 基于鏡像來(lái)進(jìn)行分發(fā),創(chuàng)建鏡像倉(cāng)庫(kù)用來(lái)支持持續(xù)構(gòu)建。
鏡像倉(cāng)庫(kù)主要用于存儲(chǔ)鏡像,網(wǎng)易蜂巢鏡像倉(cāng)庫(kù)采用基于 nos的分布式對(duì)象存儲(chǔ),數(shù)據(jù)保持多副本,解決了磁盤壞掉導(dǎo)致用戶鏡像丟失的問題。
如下圖創(chuàng)建了一個(gè) testci 1的鏡像倉(cāng)庫(kù)用來(lái)支持持續(xù)集成。
第二步:設(shè)置代碼倉(cāng)庫(kù)和鏡像倉(cāng)庫(kù)的關(guān)系
通過 github的 api用戶可以獲取 github下的所有代碼倉(cāng)庫(kù)來(lái)進(jìn)行選擇,可以選擇在某個(gè)倉(cāng)庫(kù)的某一個(gè)分支或者 tag有提交的情況下觸發(fā)持續(xù)構(gòu)建。
如下圖,用戶選擇了基于 citest的 dev分支進(jìn)行持續(xù)構(gòu)建。
像這樣,用戶每次有 commit push到代碼倉(cāng)庫(kù)都會(huì)觸發(fā)相應(yīng)的持續(xù)構(gòu)建。
第三步:觸發(fā)持續(xù)構(gòu)建
在相應(yīng)的持續(xù)構(gòu)建分支進(jìn)行代碼提交,從而觸發(fā)持續(xù)構(gòu)建。
如下圖在代碼倉(cāng)庫(kù)中通過 git簡(jiǎn)單的增加了一個(gè) txt文件,并提交到 github。
第四步:代碼構(gòu)建
用戶把 commit代碼 push到倉(cāng)庫(kù)后, github/gitlab會(huì)回調(diào) hook服務(wù);hook服務(wù)獲取相應(yīng)的代碼 commit信息,進(jìn)行過濾后,把構(gòu)建任務(wù)下發(fā)到任務(wù)隊(duì)列,并在最后分發(fā)的持續(xù)構(gòu)建集群對(duì)鏡像執(zhí)行構(gòu)建;在構(gòu)建成功后把鏡像推送到 hub.c.163.com鏡像倉(cāng)庫(kù)。
如下圖的構(gòu)建日志清晰的展示了用戶的構(gòu)建過程。拉取用戶指定分支上的 commit,根據(jù)填寫的 Dockerfile路徑進(jìn)行鏡像構(gòu)建,最后生成鏡像并推送到鏡像倉(cāng)庫(kù)。
第五步:使用鏡像進(jìn)行部署
此時(shí),可以快速地選擇蜂巢的服務(wù)部署方式對(duì)鏡像進(jìn)行部署,也可以直接下載鏡像進(jìn)行部署,以便繼續(xù)對(duì)部署的容器進(jìn)行持續(xù)集成相關(guān)的測(cè)試。
如下圖采用 docker pull下載鏡像,通過 docker run 的方式運(yùn)行鏡像,然后進(jìn)行后續(xù)的集成測(cè)試。
上述就是整個(gè)持續(xù)構(gòu)建的基本流程,用戶可以快速地在蜂巢進(jìn)行代碼倉(cāng)庫(kù)構(gòu)建。
其實(shí),蜂巢在整個(gè)工程的開發(fā)過程中也遇到了相當(dāng)多的問題,如:
- 網(wǎng)絡(luò)問題。受限于 github,mvn倉(cāng)庫(kù)等網(wǎng)絡(luò)限制,導(dǎo)致代碼拉取、mvn構(gòu)建等速度相對(duì)較慢。
- 鏡像問題。鏡像獲取速度較慢,鏡像 push較慢。
- 單臺(tái)機(jī)器的性能受限。
在蜂巢團(tuán)隊(duì)的努力下,已經(jīng)很好地解決了這些難題。
- 針對(duì)問題1:蜂巢選擇了搭建代理、采用專線等方式解決了 github和 mvn倉(cāng)庫(kù)等網(wǎng)絡(luò)問題。
- 針對(duì)問題2:蜂巢周期性地同步官方鏡像。如果用戶的 dockerfile是基于官方的基礎(chǔ)鏡像則會(huì)被替換為蜂巢的官方鏡像從而加速下載過程。同時(shí),對(duì)于構(gòu)建機(jī)器會(huì)提供鏡像的緩存,加速構(gòu)建。鏡像 push較慢則在內(nèi)網(wǎng)部署鏡像倉(cāng)庫(kù),通過專線的方式加速整個(gè) push的過程。
- 針對(duì)問題3:構(gòu)建機(jī)器,采用集群化部署。通過 mq隊(duì)列進(jìn)行解耦,從而可以快速地進(jìn)行水平擴(kuò)展,提升構(gòu)建的能力。
作者:易庭,網(wǎng)易蜂巢開發(fā)工程師。