持續集成與持續部署寶典Part 2:創建持續集成流水線

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

在本系列文章中,我們將探討在容器時代如何在基于Docker的環境中創建連貫的工作流程和流水線來簡化大規模項目的部署。另外,我們還將詳細介紹如何利用Docker和Rancher自動化處理這些工作流。

在上文《將構建環境容器化》中,我們開始了構建持續集成流水線的第一步工作——構建系統(Build System)的創建。我們分析了【Build】這一環節的常見的三大挑戰——依賴管理、管理環境依賴、復雜項目的漫長構建時間,以及如何用傳統工具與方法解決這些問題。接著,我們分享了如何利用Docker創建容器化的構建系統以更輕松地解決那些傳統挑戰,包括如何將構建環境容器化、如何使用Docker打包應用程序、如何使用Docker Compose創建構建環境,最終創造一個可重復的、集中管理的、良好隔離的、并行化的構建系統。

現在我們已經將【Build】系統創建好了,那么在本文中,我們將為示例的應用創建一個持續集成流水線。這樣我們既可以確保遵循最佳實踐,又可以確保彼此沖突的那些變化不會相互作用、引發問題。不過,在我們為代碼建立持續集成之前,我們先花一點時間討論如何將代碼劃分到分支中。

分支模式

在我們實現持續集成流水線的自動化時,一個需要考慮的重點是團隊遵循的開發模式。這個模式通常由團隊如何使用版本控制系統來決定。由于我們的應用程序托管在git倉庫中,因此我們使用git-flow模型進行分支、版本化以及發布我們的應用程序。它是基于git倉庫上最常用的模型之一。簡而言之,該模型的思想是維護兩個分支:一個開發(者)分支,一個主分支。每當我們想開發新功能時,就會從開發分支創建出新的分支,并在功能開發完成時,將它合并回來。所有功能分支都有開發人員單獨管理。一旦將代碼提交到開發分支,CI服務器將負責確保分支始終能夠編譯、通過自動化測試并且可以在服務器上進行QA測試和評審。當我們準備進行發布時,可以從開發分支創建一個發布,并將其合并到主分支中。被發布的特定的commit hash也會使用版本號進行標記。被標記好的發布項接著就可以被推送到Staging/Beta或者生產環境中。

下面我們將使用git-flow工具來幫助管理我們的git分支。安裝git-flow請參考這里的說明:https://github.com/nvie/gitflow/wiki/Installation。安裝好git-flow,你就可以通過下面所示的git flow init命令配置你的倉庫。Git flow會問一些問題,我們建議你使用默認的設置即可。執行過git-flow命令后,它將創建一個開發分支(如果原先沒有開發分支的話),并將其檢出作為工作分支。

現在,我們使用git flow輸入git flow feature start [feature-name]命令創建一個新功能。通常做法是用ticket/issue id用作功能的名稱。比如,如果你使用的是Jira處理ticket,那么ticket id(例如,MSP-123)就可以作為功能名稱。你還會發現當你使用git-flow創建新功能時,它將自動切換到功能分支。

到了這一步,你可以去完成該功能所需的全部內容,然后運行自動化測試套件以確保一切正常運轉。一旦你準備好發布工作,只需告訴git-flow去完成這一功能即可。根據你對該功能的實際需要,你想要進行多少次提交都可以。在我的這個示例中,從我們的目的來看,我們只需更新README文件,并通過輸入“git flow feature finish MSP-123”來完成更新。

需要注意的是,git flow合并了開發分支的功能,刪除了功能分支并且返回到了開發分支。此時,你可以將開發分支推送到遠程倉庫(git push origin develop:develop)。 當你提交了開發分支,CI服務器就會接管持續集成流水線。對于更大的團隊來說,一種更合適的模式是在完成功能之前將功能分支推送到遠程,讓它們經評審(review)后,使用pull request來合并到開發分支中。

使用Jenkins創建CI流水線

在這一節,我們假設你已啟動并運行了一個Jenkins集群。如果沒有的話,你可以在這里使用官方的Jenkins鏡像:https://hub.docker.com/_/jenkins/ ,在這里可以看到更多關于建立可擴展Jenkins集群的內容:https://rancher.com/deploying-a-scalable-jenkins-cluster-with-docker-and-rancher/ 。在你有了運行的Jenkins集群后,我們需要在Jenkins服務器上安裝下面的插件和依賴項:

Jenkins Plugins 2.32.2+

  • Git Parameter Plugin 0.8.0+

  • Parameterized Trigger Plugin 2.33+

  • Copy Artifact Plugin 1.38.1+

  • Build Pipeline Plugin 1.5.6+

  • Mask Passwords Plugin 2.9+

    Docker 1.13.1+

    Docker Compose 1.11.1+

安裝好需要的插件后,我們就可以在【Build流水線】中創建最初的三個任務:編譯、打包和集成測試。這些將作為我們持續集成和部署系統的起點。

構建應用

序列中的第一個任務將會在每次提交后從源碼控制中檢出最新的代碼并且確保其可編譯。它還會運行單元測試。如果要在我們的示例項目中設置第一個任務,選擇New Item->Freestyle Project。進入項目配置視圖中,選擇General選項卡以及“The project is parameterized”選項。添加一個叫做GO_AUTH_VERSION的git參數,將參數類型設置為Branch(分支)或者Tag(標記)。接下來選擇Advanced配置參數,使用Tag Filter設置獲取匹配“v”的所有標記(比如v2.0)。將Default Value設置成develop(開發分支)。這將有助于從Git獲取版本標簽列表,并為該任務填充選項菜單。如果該任務要在沒有給定值的情況下自動觸發,那么GO_AUTH_VERSION默認設成develop(開發)分支。

接下來,在Source Code Management選項卡部分添加倉庫url,指定分支為${GO_AUTH_VERSION},這樣手動構建時將會使用git參數來選擇分支或標記進行構建及設置輪詢間隔。這樣一來,Jenkins就會持續追蹤我們開發分支的未來所有更改,在我們的CI(和CD)流水線中自動觸發第一個任務。這里要注意的是,GO_AUTH_VERSION的默認值(比如開發分支)將用于自動檢測到的更改。

現在在Build選項卡部分選擇Add Build Step > Execute Shell并從本章前面部分復制docker run命令粘貼到這。這樣可以從Github獲得最新的代碼,并將代碼構建到go-auth可執行文件中。這里需要安裝并運行docker。如果你使用的是Linux服務器,可能還需要在docker客戶機命令中添加sudo以便能夠訪問docker守護進程。

在構建步驟之后,我們需要添加兩個后續步驟,其中Archive the Artifacts(工件歸檔)將go-auth二進制文件和幫助腳本歸檔到項目中。我們在任務中需要指定下列的工件進行歸檔。

接著我們使用Trigger parameterized builds(觸發器參數化構建)啟動流水線中的下一個任務,如下圖所示。在添加Trigger parameterized build時,請確保是從Add Parameters中添加的Current build parameters。這樣可以讓當前任務的全部參數(比如GO_AUTH_VERSION)用于下一個任務。請留意在Trigger parameterized build部分中用于下游任務的參數名稱,我們將在下面的步驟中用到。

構建任務的日志輸出應該像下面展示的這樣。你可以看到我們使用了docker化的容器來執行構建。構建時將使用go fmt來修復代碼中任何格式的不一致,并且執行我們的單元測試。如果出現測試失敗或者編譯不通過,Jenkins就會檢測到失敗。此外,你應該通過email或者chat integrations(例如Hipchat或者Slack)設置通知,這樣在構建失敗時就能通知到你的團隊,快速地修復它。

打包應用

代碼編譯通過了,接下來我們就能將它打包進Docker容器中。創建打包任務的方式是,選擇New Item > Freestyle Project并給你的第二個任務起一個名稱,該名稱對應于在先前任務中指定的內容。和之前一樣,該任務也是一個帶有GO_AUTH_VERSION參數的參數化構建。要注意的是,這里和所有后續的任務中,GO_AUTH_VERSION只是一個默認值為develop(開發分支)的string參數。我們希望它的值是從上游傳過來的。

和之前一樣,添加構建步驟來執行shell。注意這里你不需要指定SCM設置,因為我們將從前一個構建生成的工件中提取所需的二進制文件和腳本。注意一下,我們這里是先創建未標記的usman/go-auth,之后再重新標記,這樣我們就可以在后面執行集成測試,搭建好未打標記的容器環境。

為了構建Docker容器,我們還需要前一步中構建的可執行文件。為此,我們增加一個構建步驟復制上游構建中的工件。這樣可以保證我們有可用于Docker構建命令的可執行文件,該命令可以打包到Docker容器中。注意這里我們選擇了flatten目錄來保證所有工件都復制到當前項目的根目錄中。

我們一直在使用GO_AUTH_VERSION變量標記我們正在構建的鏡像。在默認情況下,開發分支的變更,總會構建usman/go-auth:develop并覆蓋現有的鏡像。在下一章中,我們會發布應用程序的新版本并重新審視這個流水線。

和之前相同,使用了Trigger parameterized builds下(包含了Current build parameters)的后構建(post-build)來觸發流水線中的下一個任務,該任務將使用我們剛剛構建好的Docker容器以及在之前章節中詳述的Docker Compose來執行集成測試。

執行集成測試

接下來是執行集成測試,先要創建一個新任務。和打包任務相同,新任務是一個使用GO_AUTH_VERSION string變量的參數化構建。然后從構建任務中復制工件。這一次我們將使用上面的Docker Compose模板來搭建一個多容器測試環境,并對我們的代碼執行集成測試。集成測試(不同于單元測試)通常是與正在測試的代碼完全隔離的。因此,我們會用到一個shell腳本,它可以針對我們的測試環境執行http查詢。在執行shell命令中,將目錄修改為go-auth并執行integrationtest.sh。

腳本的內容可以在這里找到:https://github.com/usmanismail/go-messenger/blob/master/go-auth/integration-test.sh。我們用Docker Compose搭建我們的環境,然后使用curl發送http請求到搭建的容器中。這項任務的日志將會和下圖顯示的相似。Compose將會啟動一個數據庫容器,并將它連接到goauth容器。數據庫連接之后你應該會看到一些列“Pass: …”信息,說明各項測試都在運行和驗證。測試完成后,compose模板將會自行清理數據庫和go-auth容器。

經過了三個任務的設置,你就可以在Jenkins視圖中選擇【+選項卡】,選擇build pipeline view來創建一個新的構建流水線視圖。在彈出的配置界面中,選擇你編譯/構建的任務作為初始任務,然后選擇ok。現在你應該能看到CI流水線已經成型。這將給你一個可視化引導,展示每個提交是如何通過你的構建和部署流水線的。

當你更改開發分支時,你會注意到流水線是由Jenkins自動觸發的。如果要手動觸發流水線,選擇你第一個(構建)任務,運行它。系統會要求你選擇git參數的值(比如GO_AUTH_VERSION)。不指定的話會執行默認值,并且會運行針對開發分支中最新內容的CI流水線。當然,你可以直接在流水線視圖中單擊“Run”。

我們快速回顧一下到現在為止我們所做的工作。我們通過以下步驟為我們的應用程序創建了CI流水線:

  1. 使用git-flow添加新功能,并將他們合并到開發分支中。

  2. 跟蹤開發分支的變化,在一個容器化環境中構建我們的應用程序

  3. 將我們的應用程序打包到docker容器中

  4. 使用Docker Compose搭建短生命周期環境

  5. 執行集成測試以及清理環境

通過上面的CI流水線,每當新功能(或者修復)合并到開發分支時,CI流水線就會執行上述所有的步驟,創建出“usman/go-auth:develop” Docker鏡像。此外,我們在接下來的章節中將構建更深層的集成部署流水線。另外因為該視圖有清晰的測試階段,你還可以使用此視圖將應用程序版本推廣到各種部署環境中。

總 結

在本章中,我們分享了如何利用Docker為我們的項目創建一個持續集成流水線,該流水線是集中管理的、可測試的,并且在機器和時間上可重復。我們能夠根據需要對各種組件的環境依賴進行隔離。這是我們未來部署一條更長的基于Docker構建和部署的流水線的起點,我們將在下一次的文章中繼續構建這一流水線的余下部分并將過程經驗記錄下來。

我們流水線的下一步是創建持續部署,后續文章我們將展示如何使用Rancher部署整個服務器環境來運行代碼,我們還將介紹如何為大型項目設置長期運行的測試環境和持續部署流水線的最佳實踐。

轉載于:https://my.oschina.net/u/3330830/blog/1915645

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/451077.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/451077.shtml
英文地址,請注明出處:http://en.pswp.cn/news/451077.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

64 裝飾器函數: 母版 csrf防御機制 cookie

主要內容: 1: 裝飾器函數 a: 原理: 在不改變原函數的代碼和調用方式的情況下, 給函數動態的添加功能 b: 實例: 裝飾器的原理: def yue(tools):print(使用%s約一約 % tools) def wrapper(fn):def inner(*args, **kwargs):print(先準備好錢)fn(*args, **kwargs)return inner yue …

Facebook與Google的互聯網霸主爭奪戰

摘要:谷歌的兩位創始人對搜索情有獨鐘,而沒有看到互聯網發展的大勢。雖然目前Facebook的估值最高為1000億美元,與谷歌近2000億美元的市值還相去甚遠,但是未來很有可能超越谷歌,成為互聯網新一代霸主。谷歌的兩位創始人…

Eclipse將引用了第三方jar包的Java項目打包成jar文件的兩種方法

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 方案一:用Eclipse自帶的Export功能 步驟1:準備主清單文件 “MANIFEST.MF”, 由于是打包引用了第三…

Linux-MySQL基本命令-SQL語句

服務端命令SQL 在數據庫系統中,SQL語句不區分大小寫(建議用大寫) ?SQL語句可單行或多行書寫,以“;”結尾 ?關鍵詞不能跨多行或簡寫 ?用空格和縮進來提高語句的可讀性 ?子句通常位于獨立行,便于編輯,提高可讀性 ?注釋&#x…

webAPI token驗證

ASP.NET WebApi 實現Token驗證 https://www.cnblogs.com/dukang1991/p/5627584.html轉載于:https://www.cnblogs.com/KQNLL/p/9757025.html

評論:中國企業向Faceook學習什么

摘要:古人云:“迨天之未陰雨,徹彼桑土,綢繆牖戶。且不論究竟誰會成為中國的Facebook,伴隨著Facebook因上市帶來的又一輪火熱,不妨先來看看中國企業最需要向Facebook學習什么。古人云:“迨天之未…

java ++i、i++、i++ + ++i、i++ + i++原理

先上代碼: public static void main(String args[]) {int A 1;int B 10;int C 100;int D 1000;System.out.println(A);System.out.println(B);System.out.println(C C);System.out.println(C);System.out.println(D D);System.out.println(D);} 在來運行結果…

一個判斷session是否過期的小技巧

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 Session一直是我們做web項目經常使用的,以前沒太注意,這次又細致的看了下! 1.session其實就是一個Ma…

擴展方法

擴展方法是寫在靜態類中,且方法是靜態方法。 不限制參數的數量。 不限制返回類型。 不限制可使用擴展方法的類型。 和普通方法編寫相似,唯一不同的是每一個擴展方法都必須有一個固定的參數。statc void Method( this DataType name&#xff0…

cpu執行命令方式

(一)有序處理器 早期的處理器為有序處理器(In-order processors),有序處理器處理指令通常有以下幾步: 指令獲取如果指令的輸入操作對象(input operands)可用(例如已經在寄存器中了&#xff09…

jQuery基礎-事件

只能添加一個處理函數,后面的會覆蓋前面 會有兼容性差異 冒泡 會依次檢查父元素 截獲冒泡 或者 最大的缺陷 并且在IE和NetSpace里面分別為冒泡和捕獲兩種 多個處理函數 依次執行 捕獲--->自己--->冒泡 true 只捕獲,不冒泡 false 只冒泡 從父元素的…

別的AI還在打游戲,這個AI已經當上“超級馬里奧”游戲策劃了|GECCO最佳論文

AI打游戲已經不是什么新鮮事了,“沉迷”Dota 2、星際爭霸、LOL的AI一個接一個的出現。 但是你也許不知道,相比這些“游戲玩家”AI,還有一位優秀的AI,直接當起了“游戲策劃”,做的還是膾炙人口的“超級馬里奧”。 &…

單點登錄的三種實現方式

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 單點登錄SSO(Single Sign On)說得簡單點就是在一個多系統共存的環境下,用戶在一處登錄后,…

快速判斷數組中每個對象同一屬性值是否相同

做批量查詢的時候,要確定數組中的多個對象下的字符串是否能全部匹配,這時需要在匹配的名稱對象中通過字段記錄該名稱是否匹配。 const search [ { name: B, isExistence: false },{ name: C, isExistence: false } ]; 這時要確定 search 是否全部匹配上…

java對象占用內存大小?

一個不包含任何內部成員變量的空Object大約占33byte,若增加成員變量,則增加相應大小的內存占用。 測算方式:設置jvm的堆大小為1m,在堆中不停new不含任何成員變量的OOMObject對象,直到堆內存溢出。如下圖,在…

Java程序員面試中的多線程問題

很多核心Java面試題來源于多線程(Multi-Threading)和集合框架(Collections Framework),理解核心線程概念時,嫻熟的實際經驗是必需的。這篇文章收集了 Java 線程方面一些典型的問題,這些問題經常被高級工程師所問到。 0.Java 中多線程同步是什…

SpringBoot2使用WebFlux函數式編程

本文只是簡單使用SpringBoot2使用WebFlux的函數式編程簡單使用,后續會繼續寫關于Webflux相關的文章。 最近一直在研究WebFlux,后續會陸續出一些相關的文章。 首先看一下Srping官網上的一張圖,對比一下SpringMvc和Spring WebFlux,如…

單點登錄原理與簡單實現

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 一、單系統登錄機制 1、http無狀態協議 web應用采用browser/server架構,http作為通信協議。http是無狀態協議,瀏…

java接口類支持多繼承

一個類只能extends一個父類,只能有一個父類,但可以implements多個接口。java通過使用接口的概念來取代C中多繼承。與此同時,一個接口則可以同時extends多個接口,卻不能implements任何接口。Java中的接口是支持多繼承的。

xmind-HTTP協議

轉載于:https://www.cnblogs.com/margot921/p/9764788.html