天天看點

DockOne微信分享(八十二):基于Docker技術的CI&CD實踐

本文講的是<b>DockOne微信分享(八十二):基于Docker技術的CI&amp;CD實踐</b>【編者的話】Docker技術應用廣泛,可以将軟體與其依賴環境打包起來,以鏡像方式傳遞,讓軟體運作在“标準環境”中。這一特性可以應用到持續內建中,實作原生支援容器雲平台持續傳遞。本文将概述CI&amp;CD基本工作流程,軟體整體架構以及實作原理。

持續內建是一種軟體開發實踐,即團隊成員經常內建他們的工作,每次內建都需要通過自動化的建構,包括編譯、釋出、自動化測試來驗證,進而盡早的發現內建錯誤。持續傳遞是指頻繁地将軟體新版本傳遞品質團隊或者使用者以供評審,如果評審通過,釋出到生産環境。

Docker是一款基于LXC的容器引擎,自2013年開源以來,因為其易用性、高可移植性在開源社群非常火熱。Docker将軟體與其依賴環境打包起來,以鏡像方式傳遞,讓軟體運作在“标準環境”中,這非常符合雲計算的要求。各大IT巨頭紛紛跟進,基于Docker容器技術創業公司也如雨後春筍,Docker創造了一個嶄新的容器雲行業。

Docker技術應用廣泛。如,利用其隔離特性,為開發、測試提供一個輕量級獨立沙盒環境進行內建測試。加速本地開發和建構流程,使其更加高效輕量化,開發人員可以建構、運作并分享容器,輕松送出到測試環境中,并最終進入生産環境。Caicloud Circle正是基于Docker這一特性打造的一款容器原生持續內建持續傳遞Saas産品。

DockOne微信分享(八十二):基于Docker技術的CI&amp;CD實踐

Circle提供豐富的rest API供Web應用調用;

通過API建立VCS與Circle服務關聯後,VCS上的commit等動作會觸發Circle建構;

VCS Provider元件從VCS拉取代碼庫中源碼;

基于源碼中配置檔案CI配置啟動需要的CI微服務容器進行內建測試;

內建測試通過後,進入Pre Build階段在指定編譯環境容器中編譯可執行檔案;

Build階段中将可執行檔案拷貝到指定運作環境容器中,打成鏡像推送到Registry中;

Post build階段會做一些鏡像釋出後的關聯操作,比如推送運作依賴的靜态資源檔案到CDN中;

鏡像釋出後可以自動部署應用到Caicloud、Kubernetes、Mesos、Swarm等PaaS平台;

建構過程日志可以通過LogServer拉取;

建構結束建構結果可以發郵件通知使用者。

DockOne微信分享(八十二):基于Docker技術的CI&amp;CD實踐

Circle整體架構如下圖所示。Circle運作在容器中,與Kafka-ZooKeeper容器叢集通信推送拉取建構過程日志,基礎資料資訊存儲在mongo資料庫容器叢集中。在Circle内部:API Swagger元件提供線上Circle API說明幫助文檔;API Server元件接收使用者http請求,生成異步待處理事件記入Async Event Manager元件的事件隊列中,并應答使用者請求;Async Event Manager元件在檢測到新的待處理事件建立後,根據事件具體操作類型調用CI&amp;CD元件提供的工具函數組裝拼接成工作流水線,檢測到事件完成後更新資料庫中文檔記錄;在容器外運作一組Docker Daemon隊列,各工作流水線獨立使用一個Docker Daemon,以實作使用者和事件隔離;CD&amp;CD元件會從Docker Daemon Queue中排程取出一個空閑Docker Daemon執行流水線任務,過程日志推送到Kafka指定的topic中;Log Server元件向使用者提供一個擷取日志的Websocket伺服器,從Kafka拉取實時日志推送給使用者。

Circle也可以多節點分布式部署,部署圖如下所示。每一個立方體代表一個節點,使用Haproxy反向代理實作負載均衡和SSL資料加密,分發API請求到各Circle節點中。

DockOne微信分享(八十二):基于Docker技術的CI&amp;CD實踐

在Web頁面通過OAUTH使用者授權拉取使用者VCS版本庫清單,選擇建立與指定版本庫相關聯的服務。如果VCS使用的Git還能調用Git API建立Webhook,當版本庫産生commit、tag、pull request等事件時調用Circle API觸發CI&amp;CD。

DockOne微信分享(八十二):基于Docker技術的CI&amp;CD實踐

Circle CI&amp;CD的具體各步驟操作定義在代碼庫caicloud.yml檔案中。分為integration、pre_build、build、post_build、deploy五段。Circle從代碼庫中拉取檔案後,解析caicloud.yml檔案,依配置執行具體操作。

integration段執行內建測試,Yaml檔案中定義了編譯可執行檔案使用的語言鏡像名,運作使用的環境變量,啟動指令(可以運作一些測試腳本、測試應用),以及內建測試依賴的微服務容器配置。首先使用Docker remote API調用配置設定的Docker Daemon啟動依賴的微服務容器;然後啟動內建容器編譯可以檔案,執行指令行,完成後容器退出,傳回指令行執行結果碼标示內建結果。

prebuild段執行編譯工作,可以使用Dockerfile也可以使用Yaml的K-V值。Yaml檔案中可以定義建構使用的Dockerfile路徑檔案名,prebuild容器啟動的基礎鏡像、環境變量、啟動指令行以及編輯結束後,需要輸出的可執行檔案夾或檔案名,如果Dockerfile和容器配置同時被定義,優先使用Dockerfile。CI&amp;CD首先解析指定的Dockerfile或者yaml檔案内容,擷取容器啟動配置,依配置調用容器,執行指令行編譯可執行檔案後退出容器,如果編譯成功,使用Docker copy API拷出指定的輸出檔案。

在build段中基于指定的Dockerfile建構釋出鏡像。在該Dockerfile中可以添加prebuild段中輸出的可執行檔案到釋出環境中。Prebuild和build的分步操作實作了軟體編譯環境與軟體運作環境的隔離。建構完成後push鏡像到指定的鏡像倉庫中。

Post build段可以定義一些鏡像釋出後的關聯操作。比如使用者可以制作一個包含程式運作依賴的必要靜态資源的鏡像,在Post build階段以該鏡像啟動容器,并通過執行指令行推送到CDN中。

釋出完成後進入部署階段。使用者在Web界面預先配置好部署方案,指定叢集分區應用和容器名,Circle會調用叢集提供的應用部署API,将建構好的鏡像部署應用中,并查詢部署狀态,如果失敗復原到上一個成功鏡像。

DockOne微信分享(八十二):基于Docker技術的CI&amp;CD實踐

作為伺服器不會在同一時刻僅處理單一請求,在同一節點上同時運作的事件任務可能會互相影響。Circle采用多Docker Daemon隔離實作使用者事件隔離。在節點上運作一組Docker Daemon隊列,排程配置設定給單一事件任務使用,使用完成後清理殘留容器和鏡像,確定建構環境整潔。隊列元素個數有限,當沒有空閑Docker Daemon時事件任務進入排隊等待狀态,等待超過2小時,事件任務逾時失敗。當使用者需要取消建構時,僅需kill正在執行目前建構任務的Docker Daemon,然後重新開機一個新的Docker Daemon加入到空閑隊列中。

微服務正在部落格、社交媒體讨論組和會議演講中獲得越來越多的關注。微服務架構是一種特定的軟體應用程式設計方式——将大型軟體拆分為多個獨立可部署服務組合而成的套件方案。為了管理微服務多子產品間的依賴管理,聯合內建釋出多個子產品,Circle實作了聯合釋出功能。

首先建立多個與單一子產品代碼庫代碼關聯的服務;然後通過UI拖拽方式設定多個服務間的樹形依賴關系,Circle将樹形關系轉化成線性釋出序列存儲。當使用者點選一鍵聯合釋出時,Circle将同時啟動多條CI&amp;CD流水線對多個子產品分别進行內建測試和建構(Integration+Prebuild+Build+Post Build操作),所有子產品建構都完成後依存儲線性釋出序列依次部署到容器叢集應用中(Deploy操作)。

DockOne微信分享(八十二):基于Docker技術的CI&amp;CD實踐

常見的檔案分析方法有兩種:靜态分析和動态分析。我們采用的是靜态分析,檢閱鏡像的檔案系統。漏洞是從Linux作業系統的通用漏洞披露(CVE)資料庫擷取。

DockOne微信分享(八十二):基于Docker技術的CI&amp;CD實踐

目前Circle實際部署采用的多節點分布式部署方式,各節點上使用Docker compose運作各容器,更新運維都比較麻煩,需要SSH連接配接到各節點上指令行操作。我們計劃近期将Circle部署到Caicloud CLaas技術棧,運用Kubernetes強大的運維功能提高Circle的生産效率。可能會對現有架構做些改造,目前思路如下:

DockOne微信分享(八十二):基于Docker技術的CI&amp;CD實踐

每個立方體表示一個Pod。使用Nignx做反向代理,TLS加密;Circle-Master中API-Server元件向web提供API服務,Log-server元件提供實時日志服務,當調用API建構,會到建立一個建構任務發送給Worker manager元件,Worker manager記錄任務資訊到etcd中,并建立一個Circle-Worker pod執行任務;Circle-Worker中有之前的CI&amp;CD元件,依次啟動容器執行Integration、Prebuild、Build、Post Build和Deploy,中間過程日志推送到Kafka,任務狀态同步到etcd,任務結束後pod退出;各元件需要持久化的資訊寫入mongo。

CI&amp;CD任務需要占用大量的系統資源,Circle伺服器資源有限,如何才能支援大量并發的建構任務?我們的思路是可以讓使用者添加自有工作節點到Circle叢集中,由Circle來排程CI&amp;CD任務管理邏輯,由使用者自有工作節點來承載執行任務的運算負荷。将CI&amp;CD流水線部分拆分出來,基于Docker in Docker鏡像打包制作成Circle-Worker鏡像。使用者在自有機器上安裝運作Docker後,将Docker remote API位址以及機器資源配置告知Circle,Circle驗證機器有效性後将該機器拉入叢集中。當該使用者有需要執行的CI&amp;CD任務時,排程使用者節點運作Circle-Worker容器從Circle擷取任務資訊并執行,完成後傳回結果。

Q:感謝分享,請問你們選用Circle的而不是Jenkins原因嗎?個人感覺Jenkins還是比較強大的,尤其是它豐富的插件?

A:我們目的是研發一套基于容器雲原生的CI&amp;CD平台,以便于更好支援今後對接容器叢集部署應用和應用管理。

Q:感謝分享,由于CI會涉及到不同的(開發,測試等等)環境,那麼對于不同環境的自動編譯和部署可能處理機制不同,可以通過同一個YML去定義和識别麼?

A:沒錯,整個CI會涉及不同的環境,正是因為環境的問題,也是我們采用容器技術原因之一。在不同的環境上部署同一個容器鏡像,确實也會有不同的環境特殊配置,比方說資料庫位址,這個時候需要外部來解決配置管理的問題,我們整個容器解決方案中包含配置中心,以環境變量和檔案挂載的方式來解決此類問題。

Q:請問:如果使用環境鏡像進行編譯,那麼最終編譯後的鏡像大小會不會因為有大量的依賴包而很大?

A:不是很清楚您指的環境鏡像是什麼,最終編譯生成的鏡像大小基本與應用使用的程式設計語言、依賴的中間件和本地其它依賴庫或檔案。

Q:問下代碼包是放到鏡像裡還是放到主控端上,如何解決鏡像分發慢的問題?

A:代碼下載下傳到主控端再挂載到容器中編譯可執行檔案,完成後從容器中拷出可執行檔案,打包到釋出環境鏡像中。我們在主控端上有運作一個Proxy Registry用于加速拉取鏡像。主控端拉取過的曆史鏡像會緩存在本地Proxy Registry,下次拉取時先從本地拉取。

原文釋出時間為:2016-09-18

本文作者:陳曦

本文來自雲栖社群合作夥伴Dockerone.io,了解相關資訊可以關注Dockerone.io。

原文标題:DockOne微信分享(八十二):基于Docker技術的CI&amp;CD實踐

繼續閱讀