您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)Docker+rancher如何構(gòu)建環(huán)境容器化的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。
介 紹
隨著Docker項(xiàng)目及其相關(guān)生態(tài)系統(tǒng)逐漸成熟,容器已經(jīng)開始被更多企業(yè)用在了更大規(guī)模的項(xiàng)目中。因此,我們需要一套連貫的工作流程和流水線來簡(jiǎn)化大規(guī)模項(xiàng)目的部署。在本指南中,我們將從代碼開發(fā)、持續(xù)集成、持續(xù)部署以及零停機(jī)更新幾個(gè)方面進(jìn)行介紹。在大型組織中,這已是相當(dāng)標(biāo)準(zhǔn)的工作流;但在本系列文章中,我們會(huì)更著重于探討在容器時(shí)代,如何在基于Docker的環(huán)境中復(fù)制這些工作流。另外,我們還將詳細(xì)介紹如何利用Docker和Rancher自動(dòng)化處理這些工作流。在本指南中,我們提供了每個(gè)步驟的詳細(xì)示例,幫助你實(shí)現(xiàn)自己的CI系統(tǒng)。
我們希望你通過該指南,能夠提取到其中的一些想法,利用諸如Docker和Rancher這類工具來創(chuàng)建屬于你們企業(yè)的持續(xù)集成和持續(xù)部署流水線,并根據(jù)自己的實(shí)際情況和需求在這CI/CD流水線中也加入自定義的流程。
在我們開始之前,還有一些需要注意的事項(xiàng):因?yàn)镈ocker和Rancher的版本更迭都非???,可能會(huì)出現(xiàn)一些在不同版本的平臺(tái)上API和實(shí)現(xiàn)不一致的情況。作為參考,我們?cè)谥改现械墓ぷ鳝h(huán)境是:Golang 1.8,Docker 1.13.1+,Jenkins Version 2.32.2,docker-compose 1.11.1+ 以及Rancher 1.4.1+。
第一部分:持續(xù)集成
那么踏出第一步,我們先從流水線的入口開始,即構(gòu)建源代碼。在任何項(xiàng)目開始時(shí),構(gòu)建/編譯并不會(huì)是什么麻煩的問題,因?yàn)榇蠖鄶?shù)語言和工具都有定義良好且記錄詳細(xì)的編譯源代碼過程。但是隨著項(xiàng)目和團(tuán)隊(duì)在規(guī)模上的擴(kuò)大以及依賴關(guān)系的增加,在確保代碼質(zhì)量的同時(shí),如何為所有開發(fā)人員提供一致且穩(wěn)定的構(gòu)建,會(huì)逐漸成為一個(gè)更大的挑戰(zhàn)。在本節(jié)中,我們將會(huì)介紹一些常見的挑戰(zhàn)、最佳實(shí)踐以及如何通過Docker來實(shí)現(xiàn)持續(xù)集成。
擴(kuò)展構(gòu)建系統(tǒng)的挑戰(zhàn)
在分享最佳實(shí)踐之前,讓我們看看在維護(hù)構(gòu)建系統(tǒng)中常出現(xiàn)的一些挑戰(zhàn)。
首先,在擴(kuò)展項(xiàng)目時(shí)你會(huì)面臨的第一個(gè)問題就是Dependency Management(依賴管理)。開發(fā)人員會(huì)從庫中拉取代碼并和源代碼進(jìn)行集成,如此一來,跟蹤代碼所使用的每個(gè)庫的版本,確保項(xiàng)目所有部分都使用相同的版本,測(cè)試庫版本的升級(jí)并把通過測(cè)試的更新push到你全部的項(xiàng)目中,這些過程都變得非常重要。
其次,管理環(huán)境依賴是一個(gè)和依賴管理相關(guān)但又有一些不同的問題。它包括IDE和IDE配置、工具版本(如Maven版本、Python版本)和工具配置(如靜態(tài)分析規(guī)則文件、代碼格式化模版)。因?yàn)轫?xiàng)目的不同部分可能相互間有需求沖突,環(huán)境依賴管理會(huì)變得非常棘手。和代碼層面的依賴沖突不同,想要解決這些沖突往往是非常困難甚至是不可能的。比如,在最近的一個(gè)項(xiàng)目中,我們使用fabric進(jìn)行自動(dòng)化部署,使用s3cmd將工件上傳到Amazon S3。不幸的是,fabric的最新版本需要Python 2.7,而s3cmd需要使用Python 2.6。修復(fù)程序需要我們切換到s3cmd的測(cè)試版本或者使用舊版的fabric。
最后,對(duì)每個(gè)大型項(xiàng)目來說,它們主要面臨的是構(gòu)建時(shí)間問題。隨著項(xiàng)目范圍和復(fù)雜度增加,越來越多的語言添加了進(jìn)來。同時(shí),項(xiàng)目團(tuán)隊(duì)還需要為各種相互依賴的組件進(jìn)行測(cè)試。例如,如果你有一個(gè)共享數(shù)據(jù)庫,那么改變相同數(shù)據(jù)的測(cè)試是不能夠同時(shí)執(zhí)行的。此外,我們需要在測(cè)試執(zhí)行之前設(shè)置預(yù)期狀態(tài),并能在完成后自行清理。如此一來,所有這一切可能需要幾分鐘到幾個(gè)小時(shí)的時(shí)間進(jìn)行構(gòu)建,充分測(cè)試意味著會(huì)大大減慢開發(fā)速度,但如果跳過測(cè)試又有可能出現(xiàn)嚴(yán)重的問題。
解決方案和最佳實(shí)踐
為了解決所有這些問題,就需要我們有一個(gè)支持下列需求的構(gòu)建系統(tǒng):
可重復(fù)性
我們必須能夠在不同的開發(fā)機(jī)器和自動(dòng)構(gòu)建服務(wù)器上生成/創(chuàng)建出有同樣依賴關(guān)系的、相似(或相同)的構(gòu)建環(huán)境。
集中管理
我們必須能夠控制所有開發(fā)人員的構(gòu)建環(huán)境,并從中央代碼倉庫或服務(wù)器構(gòu)建服務(wù)器。這包括了設(shè)置構(gòu)建環(huán)境以及更新延時(shí)。
隔離
項(xiàng)目的各個(gè)子組件必須獨(dú)立構(gòu)建,而不是使用明確定義的共享依賴項(xiàng)。
并行化
我們必須能夠?yàn)樽咏M件提供并行化構(gòu)建。
為了滿足可重復(fù)性要求,我們必須使用集中式依賴管理。大多數(shù)現(xiàn)代語言和開發(fā)框架都支持自動(dòng)依賴管理。Maven廣泛用于Java和其他幾種語言,Python使用pip,Ruby使用Bundler。所有這些工具都有一個(gè)非常相似的樣式,你可以commit索引文件(pom,xml, requirements.txt或者gemfile)到你的源碼控制中。然后運(yùn)行該工具,把依賴下載到構(gòu)建機(jī)器上。我們可以在測(cè)試過它們后,集中管理索引文件,接著通過更新源碼控制中的索引來進(jìn)行更改。但是,管理環(huán)境依賴的問題依然存在,比如我們必須安裝正確版本的Maven、Python和Ruby。我們還需要確保這些工具由開發(fā)人員運(yùn)行。Maven能夠自動(dòng)檢查依賴項(xiàng)更新,但對(duì)于pip和Bundler,我們必須將構(gòu)建命令包裝在觸發(fā)依賴項(xiàng)更新運(yùn)行的腳本中。
對(duì)于設(shè)置依賴關(guān)系管理工具和腳本,大多數(shù)小型團(tuán)隊(duì)只使用文檔,并把任務(wù)交給了開發(fā)人員。然而這種方法在大型團(tuán)隊(duì)中并不完全適用,特別是當(dāng)依賴關(guān)系會(huì)隨時(shí)間發(fā)生變化時(shí)。更復(fù)雜的是,根據(jù)構(gòu)建機(jī)器的平臺(tái)和操作系統(tǒng)不同,這些工具的安裝命令都會(huì)發(fā)生變化。你可以使用編排工具(比如Puppet或Chef)來管理依賴項(xiàng)的安裝以及設(shè)置配置文件。Puppet和Cher都允許在源代碼控制中使用中央服務(wù)器或共享配置,來支持集中管理。這樣一來,你就可以提前對(duì)配置更改進(jìn)行測(cè)試,然后交給開發(fā)人員。但是,這些工具有一些缺點(diǎn):首先,安裝和配置Puppet或Chef會(huì)變得過于重要,而且它們的完整版本都不是免費(fèi)的。另外,每一種工具都有自己的語言來定義任務(wù),這就為IT團(tuán)隊(duì)和開發(fā)人員增加了另一項(xiàng)管理成本。還有一點(diǎn)是,編排工具不提供隔離,因此工具版本的沖突依舊是一個(gè)問題,而且執(zhí)行并行化測(cè)試的問題也依然沒有解決。
為了確保組件隔離并且縮短構(gòu)建時(shí)間,我們可以使用自動(dòng)虛擬化系統(tǒng),比如Vagrant。Vagrant可以創(chuàng)建并運(yùn)行虛擬機(jī),這些虛擬機(jī)能夠隔離各種組件的構(gòu)建,而且能支持并行構(gòu)建。當(dāng)準(zhǔn)備好集中管理時(shí),Vagrant配置文件可以提交到源碼控制中,并且交給開發(fā)人員。另外??梢詫?duì)虛擬機(jī)進(jìn)行測(cè)試,將其部署到Atlas,供所有開發(fā)人員下載。這樣還是會(huì)有缺點(diǎn),你需要進(jìn)一步的配置來設(shè)置Vagrant,而且在這個(gè)問題中,虛擬機(jī)是非常重要的解決方案。每個(gè)虛擬機(jī)運(yùn)行一個(gè)完整的操作系統(tǒng)和網(wǎng)絡(luò)堆棧,包含測(cè)試運(yùn)行或者編譯器。內(nèi)存和磁盤資源需要提前分配給每一臺(tái)虛擬機(jī)。
盡管存在一些警告和缺陷,但是使用依賴管理(Maven、pip、Bundler)、編排(Puppet、Chef)和虛擬化(Vagrant),我們可以構(gòu)建一個(gè)穩(wěn)定的、可測(cè)試的、集中管理的構(gòu)建系統(tǒng)。并非所有的項(xiàng)目都需要有完整的工具堆棧;不過,任何長(zhǎng)期運(yùn)行的大型項(xiàng)目都需要這種層面的自動(dòng)化。
利用Docker創(chuàng)建容器化的構(gòu)建系統(tǒng)
Docker出現(xiàn)之后,我們可以無需再花費(fèi)過多時(shí)間和資源來支持上文我們提到的這些工具,Docker及其工具生態(tài)系統(tǒng)就可以幫助我們滿足上述的需求。在本節(jié)中,我們將通過下面的步驟為應(yīng)用程序創(chuàng)建容器化構(gòu)建環(huán)境。
將你的構(gòu)建環(huán)境容器化
用Docker將你的應(yīng)用程序打包起來
使用Docker Compose創(chuàng)建構(gòu)建環(huán)境
我們使用一個(gè)叫做go-messenger的實(shí)例應(yīng)用程序來說明如何在構(gòu)建流水線中使用Docker,后面章節(jié)也會(huì)用到它。你可以從Github中獲取這個(gè)應(yīng)用程序:
https://github.com/usmanismail/go-messenger/tree/golang-1.8。
系統(tǒng)的主要數(shù)據(jù)流如下所示。該應(yīng)用程序有兩個(gè)組件:一個(gè)是用Golang便攜的RESTful認(rèn)證服務(wù)器,另一個(gè)是會(huì)話管理器,它接受來自客戶端的長(zhǎng)時(shí)運(yùn)行TCP連接并在客戶端之間路由消息。回到本文的目標(biāo),我們將重點(diǎn)介紹RESTful認(rèn)證服務(wù)(go-auth)。這個(gè)子系統(tǒng)包含了一組無狀態(tài)網(wǎng)絡(luò)服務(wù)器以及一個(gè)數(shù)據(jù)庫集群,用于存儲(chǔ)用戶信息。
將你的構(gòu)建環(huán)境容器化
建立構(gòu)建系統(tǒng)的第一步,是創(chuàng)建一個(gè)容器鏡像,其中包含了構(gòu)建項(xiàng)目所需的全部工具。我們鏡像的Docker文件如下圖所示。因?yàn)槲覀兊膽?yīng)用程序是用Go語言編寫的,所以使用的是官方的golang鏡像,并且安裝了govendor依賴管理工具。需要注意的是,如果你在自己的項(xiàng)目中使用的是Java語言,那么可以用Java基礎(chǔ)鏡像創(chuàng)建一個(gè)類似的“構(gòu)建容器”,并安裝Maven替代govendor。
然后我們添加了一個(gè)編譯腳本,將構(gòu)建和測(cè)試我們代碼的所有步驟集中到了一塊。下面所示的腳本使用了govendor restore下載依賴項(xiàng),通過go fmt命令標(biāo)準(zhǔn)化格式,用go test命令執(zhí)行測(cè)試,接著使用了go build來編譯項(xiàng)目。
為確保可重復(fù)性,我們可以使用Docker容器以及一切需要的工具,將組件構(gòu)建成一個(gè)單一的、版本化的容器鏡像。該鏡像可從Dockerhub上下載,也可以使用Dockerfile構(gòu)建(docker build -t go-builder:1.8)。到這為止,所有的開發(fā)人員(以及構(gòu)建環(huán)境的機(jī)器)都可以通過下面的命令,來使用容器構(gòu)建任何的go項(xiàng)目:
上面的命令中我們運(yùn)行了usman/go-builder鏡像的1.8版本,并使用-v將我們的源代碼安裝到了容器中,使用-e指定了SOURCE_PATH環(huán)境變量。如果想要在我們的示例項(xiàng)目中測(cè)試go-builder,你可以使用下面的命令運(yùn)行全部步驟,并在go-auth項(xiàng)目的根目錄中創(chuàng)建一個(gè)名為go-auth的可執(zhí)行文件。
將所有源從構(gòu)建工具中隔離開來后,產(chǎn)生的一個(gè)有趣的副產(chǎn)物是,我們可以輕松地更換構(gòu)建工具和配置。例如,在上面的命令中,我們使用了golang 1.8。把go builder:1.8改成go builder:1.5,你就可以測(cè)試使用golang 1.5時(shí)對(duì)項(xiàng)目的影響。為了集中管理所有開發(fā)人員使用的鏡像,我們可以將構(gòu)建容器(builder container)的最新測(cè)試版本部署到一個(gè)固定版本(即最新版本),并確保所有開發(fā)人員都使用了go-builder:latest構(gòu)建源代碼。同樣地,如果我們項(xiàng)目中不同部分使用了不同版本的構(gòu)建工具,我們可以使用不同的容器來構(gòu)建他們,而無需擔(dān)心在單個(gè)構(gòu)建環(huán)境中管理多個(gè)語言版本的問題。例如,我們可以使用支持各種python版本的官方python鏡像來減輕早期的python問題。
用Docker打包你的應(yīng)用程序
如果你想將可執(zhí)行文件打包到自己的容器中,那么需要先添加一個(gè)dockerfile文件,包含下面顯示的內(nèi)容,接著運(yùn)行“docker build -t go-auth”。在dockerfile中,我們將最后一步的二進(jìn)制輸出添加到一個(gè)新容器中,并將9000端口公開給應(yīng)用程序以便接受傳入的連接。我們還指定了運(yùn)行二進(jìn)制文件的入口點(diǎn),該入口點(diǎn)使用了給定的參數(shù)。由于Go的二進(jìn)制文件是自包含(self-contained)的,因此我們使用了原版的Ubuntu鏡像。不過如果你的項(xiàng)目需要運(yùn)行時(shí)(run time)依賴項(xiàng),那么也可以將它們打包到容器中。例如,如果你準(zhǔn)備生成一個(gè)war文件,你可以使用tomcat容器。
使用Docker Compose創(chuàng)建構(gòu)建環(huán)境
現(xiàn)在我們可以在集中管理的容器中重復(fù)構(gòu)建項(xiàng)目了,該容器隔離了各種組件,我們還可以擴(kuò)展構(gòu)建管道來運(yùn)行集成測(cè)試。這也充分展示了Docker在使用并行化時(shí)加速構(gòu)建的能力。而測(cè)試不能并行化的一個(gè)主要原因是共享數(shù)據(jù)存儲(chǔ)。對(duì)于集成測(cè)試來說尤為如此,因?yàn)槲覀兺ǔ2粫?huì)去模擬外部數(shù)據(jù)庫。我們的示例項(xiàng)目也有類似的問題,因?yàn)槲覀兪褂昧?a title="MySQL" target="_blank" href="http://kemok4.com/mysql/">MySQL數(shù)據(jù)庫來存儲(chǔ)用戶。我們想編寫一個(gè)測(cè)試,確保我們可以注冊(cè)新用戶。而第二次為同一用戶進(jìn)行注冊(cè)時(shí),我們期望會(huì)發(fā)生沖突錯(cuò)誤。這讓我們不得不對(duì)測(cè)試進(jìn)行序列化,這樣我們?cè)跍y(cè)試完成后就可以清除注冊(cè)用戶,然后再開始新的測(cè)試。
要想設(shè)置隔離的、并行的構(gòu)建,我們可以按如下的方式定義一個(gè)Docker Compose模板(docker-compose.yml)。我們定義了一個(gè)數(shù)據(jù)庫服務(wù),它使用MySQL官方鏡像以及需要的環(huán)境變量。然后我們使用自己創(chuàng)建的容器,創(chuàng)建一個(gè)GoAuth服務(wù)來打包應(yīng)用程序,并將其與數(shù)據(jù)庫容器連接起來。需要注意的是,這里我們使用了GO_AUTH_VERSION變量替換。如果在環(huán)境中指定了該變量,那么compose將使用它作為go-auth鏡像的標(biāo)記,否則會(huì)使用默認(rèn)值latest作為標(biāo)記。
有了這個(gè)docker-compose模板,我們可以通過執(zhí)行docker-compose up來運(yùn)行應(yīng)用程序環(huán)境。然后運(yùn)行下面的curl命令來模擬我們的集成測(cè)試。第一次應(yīng)該會(huì)返回200 OK,而第二次應(yīng)該返回409 Conflict。如果你是在Linux上運(yùn)行,則service_ip參數(shù)應(yīng)該是localhost,而如果你使用的是OSX,那么參數(shù)應(yīng)該是Docker虛擬機(jī)的IP。想要查找service_ip你可以運(yùn)行:
最后,在運(yùn)行完測(cè)試之后,我們可以運(yùn)行docker-compose rm來清理整個(gè)應(yīng)用程序環(huán)境。
如果想要運(yùn)行多個(gè)獨(dú)立版本的應(yīng)用程序,我們需要更新docker-compose模板來,將服務(wù)database1和goauth2以相同的配置添加到其對(duì)應(yīng)項(xiàng)中。唯一的變化是在Goauth2中,我們需要將9000:9000端口條目改變?yōu)?001:9000。這樣應(yīng)用程序公開的端口就不會(huì)發(fā)生沖突。完整的模板在這里?,F(xiàn)在運(yùn)行docker-compose時(shí),可以并行運(yùn)行兩個(gè)集成測(cè)試。像這樣的東西可以有效地用于為一個(gè)具有多個(gè)獨(dú)立子組件的項(xiàng)目加速構(gòu)建,例如,多模塊的Maven項(xiàng)目。
感謝各位的閱讀!關(guān)于“Docker+rancher如何構(gòu)建環(huán)境容器化”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。