基於OpenStack+Docker設計與實現CI/CD——基於Docker技術的CI&CD實踐

天府雲創發表於2017-07-03

摘要

Docker技術應用廣泛,可以將軟體與其依賴環境打包起來,以映象方式交付,讓軟體執行在“標準環境”中。這一特性可以應用到持續整合中,實現原生支援容器雲平臺持續交付。本文將概述CI&CD基本工作流程,軟體整體框架以及實現原理。

背景概述

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

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

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

CICD基本流程

Circle提供豐富的rest API供web應用呼叫;

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

VCS Provider元件從VCS拉取程式碼庫中原始碼;

基於原始碼中配置檔案CI配置啟動需要的CI微服務容器進行整合測試;

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

Build階段中將可執行檔案拷貝到指定執行環境容器中,打成映象推送到Registry中;

Post build階段會做一些映象釋出後的關聯操作,比如推送執行依賴的靜態資原始檔到CDN中;

映象釋出後可以自動部署應用到Caicloud、K8s、Mesos、Swarm等Paas平臺;

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

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

整體框架

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

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

實現原理

在web頁面通過OAUTH使用者授權拉取使用者VCS版本庫列表,選擇建立與指定版本庫相關聯的服務。如果VCS使用的git還能呼叫git API建立webhook,當版本庫產生commit、tag、pull request等事件時呼叫Circle API觸發CI&CD。

Circle CI&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&CD首先解析指定的Dockerfile或者yaml檔案內容,獲取容器啟動配置,依配置呼叫容器,執行命令列編譯可執行檔案後退出容器,如果編譯成功,使用Docker copy API拷出指定的輸出檔案。

在build段中基於指定的Dockerfile構建釋出映象。在該Dockerfile中可以新增prebuild段中輸出的可執行檔案到釋出環境中。Prebuild和build的分步操作實現了軟體編譯環境與軟體執行環境的隔離。構建完成後push映象到指定的映象倉庫中。

Post build段可以定義一些映象釋出後的關聯操作。比如使用者可以製作一個包含程式執行依賴的必要靜態資源的映象,在Post build階段以該映象啟動容器,並通過執行命令列推送到CDN中。

釋出完成後進入部署階段。使用者在web介面預先配置好部署方案,指定叢集分割槽應用和容器名,Circle會呼叫叢集提供的應用部署API,將構建好的映象部署應用中,並查詢部署狀態,如果失敗回滾到上一個成功映象。

一些亮點feature

a) 多Docker Daemon構建實現使用者事件隔離

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

b) 微服務多模組聯合釋出

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

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

c) 映象安全掃描

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

今後工作展望

a) 運維

目前Circle實際部署採用的多節點分散式部署方式,各節點上使用Docker compose執行各容器,升級運維都比較麻煩,需要SSH連線到各節點上命令列操作。我們計劃近期將Circle部署到Caicloud CLaas技術棧,運用Kubernetes強大的運維功能提高Circle的生產效率。可能會對現有框架做些改造,目前思路如下:

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

b) 併發

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

QA

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

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

Q:您好!感謝分享,受益匪淺,想請問教:使用者在自有機器上安裝執行Docker後,將Docker remote API地址以及機器資源配置告知Circle,Circle驗證機器有效性後將該機器拉入叢集中。這裡既然已經手動安裝執行了docker還需要做哪些來驗證機器有效性?

A:還需要做哪些來驗證機器有效性:比如驗證docker daemon是否正常執行,安全證照等。

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

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

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

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

Q:問下程式碼包是放到映象裡還是放到宿主機上,如何解決映象分發慢的問題?

A:程式碼下載到宿主機再掛載到容器中編譯可執行檔案,完成後從容器中拷出可執行檔案,打包到釋出環境映象中。我們在宿主機上有執行一個proxy registry用於加速拉取映象。宿主機拉取過的歷史映象會快取在本地proxy registry,下次拉取時先從本地拉取。

【總結】本文所述內容的背景是,基於Docker容器技術的OpenStack研發、測試、運維及其相關的CI/CD、DevOps等活動。思想是相通的,讀者可以取其可用部分用於自己的業務需求中。

IaaS雲和容器雲不是可有可無、相互競爭的關係,而是相互彌補彼此缺陷的關係。容器改變了應用部署和管理的模式,眾所周知,IaaS雲通過提供基本的計算、儲存和網路來執行虛擬機器(VM),在IaaS(基礎設施即服務)之上,還有PaaS(平臺即服務)、SaaS(軟體即服務)、CaaS(容器即服務)。OpenStack作為一個IaaS雲的基礎設施管理平臺,為使用者提供了建立VM和其他資源的服務,至於具體怎麼用這些虛擬機器、怎麼執行業務應用,如Hadoop大資料、Docker微服務、CI/CD工具鏈、Cloud Foundry等,使用者自己可以按需使用。

Docker的整個生命週期階段,主要分為:

  • Build——使用Dockerfile檔案或手動方式生成映象。
  • Push——將構建好的映象上傳到映象倉庫中。
  • Pull——從映象倉庫中拉取映象到使用環境中。
  • Run——啟動映象為容器服務。
  • Stop/Remove——停止或刪除容器、映象。

Docker適用於CI/CD的場景,主要是基於:

  • Docker容器是把應用程式和環境打包在一起的,所以是一次構建,處處執行。比如,當開發人員變更程式碼後,測試人員和運維人員只需要執行停止舊容器、啟動新容器這兩個步驟即可。因此,Docker最大的好處就是標準化了應用交付,只要系統能執行Docker,就能無差別地執行應用。
  • Docker映象統一封裝了軟體服務及其依賴環境,可以讓映象成為一個標準的軟體交付物。
  • 容器比虛擬機器執行效率更高,在開發測試工作日益繁重的CI/CD環境中,Job任務執行的速度是至關重要的。
  • 通過容器雲平臺如Kubernetes,可以方便地實施叢集和容器管理。相關技術也日趨成熟,生態環境豐富。

不同於其他軟體應用,OpenStack有著自身固有的特點,既有眾多優勢,也存在對研發測試帶來的諸多挑戰。如何運用有效的方法,才是解決問題的關鍵所在。

一、OpenStack和Docker整合現狀

Docker是一種集Namespace、Cgroups等技術於一體的容器技術,可以將應用和環境等進行打包,形成一個獨立且隔離的環境,讓每個應用彼此相互隔離,並在同一臺主機上同時執行多個應用,進行更細粒度的資源管理。Docker和VM(虛擬機器)的區別如下圖所示:

圖片描述

工欲善其事,必先利其器。Docker是一種具體的容器技術,雖然以REST API形式提供服務,但在實際生產環境中管理大規模叢集的Docker映象和容器仍然是一個巨大的挑戰。開源軟體專案的成功往往根據其催生的生態系統來衡量,使其日臻完善。

1.Kubernetes

談論Docker管理,自然不能不提及Kubernetes,這是谷歌開發的一款開源的Docker管理工具,用於跨主機叢集部署容器。Kubernetes還提供了讓容器彼此互通的方法,不需要手動開啟網路埠或執行其他操作。它提出兩個概念。

  • Pods:每個Pod都是一個容器集合並部署在同一臺主機上,共享IP地址和儲存空間,比如將Apache、Redis之類的應用分為一個容器集合。
  • Labels:提供服務標籤,方便Pod容器之間的呼叫協作。

2.Docker Compose

Docker Compose 是容器編排工具,讓使用者可以自定義容器的映象、容器之間的依賴關係等。定義好這些資訊之後,只需要一條命令就可以按照順序啟動容器,然後整個應用就部署好了,這對於自動化來說是一個很好的進步。對於應用編排來說,Compose是一個非常不錯的選擇。

3.Docker Machine

Docker Machine是一個便捷的容器建立工具,即從0到1地安裝Docker,極大地簡化了安裝過程。使用docker-machine create命令,引數-d指定虛擬化的驅動,即可在相應的平臺上建立Docker。

4.Docker Swarm

Docker Swarm 是Docker的叢集管理工具,能夠通過Master/Slave 的方式管理跨主機的Docker,為Docker叢集化部署提供了非常好的支援。

5.Docker Datacenter

Docker Datacenter 是Docker的自動化叢集管理工具,並非第三方工具,它其實是一個基於Docker的管理平臺。

6.Apache Mesos

Mesos的名氣比較大,基於它可以做很好的擴充套件,開發個性化的Docker叢集管理工具。

7.Marathon

Marathon是一個與Mesos結合在一起的Docker叢集管理工具,支援在Mesos之外排程容器。

8.Panamax

在眾多的叢集管理工具面前,如何管理單機的Docker容器也是一個需要解決的問題。因為Docker佔用資源少,在單機伺服器上部署成百上千個容器也是可能的。Panamax提供了人性化的Web管理介面用來安裝軟體,讓部署變得更簡單。並且,Panamax還提供了豐富的容器模板,讓線上建立服務成為可能。所有的操作都可以在Web介面上完成,開發者只需要關注開發應用即可。

9.Tutum

Tutum提供了一套非常友好的Dashboard介面,支援建立Docker容器的應用。

10.Harbor

使用Harbor可以管理大規模的Docker映象,以及基於同步複製功能的HA主備高可用性、細粒度的角色許可權和專案管理。

除此之外,還有一些Docker效能監控工具,如Docker Stats、CAdvisor、Scout、Data Dog以及Sensu等。

11.OpenStack整合Docker專案

OpenStack社群為了整合Docker做了很多努力,如開發了Nova+Docker Driver、Heat+Docker Driver等模組,但都存在諸多不足。為了能更好地與Docker整合,社群陸續開發了幾個新專案,如Magnum、Murano、Solum和Kolla等。

目前,Kolla是OpenStack整合Docker最火熱的一個專案,將大部分的OpenStack服務Docker容器化,便於安裝部署升級。其他的如Magnum,則提供了CaaS(容器即服務),Solum、Murano和Docker有些關係。但Solum更偏重於CI/CD,可以理解為一個應用軟體的持續整合/持續交付環境,Murano是一個App Store,Solum可以將開發的應用釋出到Murano中。

二、基於OpenStack+Docker設計CI/CD

目前,在Docker容器中部署和執行OpenStack雲端計算服務,已成為主流趨勢之一。基於這樣的背景,設計和實現OpenStack+Docker環境下的CI/CD應用便成為了必然。

在IT企業中,當我們面對以OpenStack為代表的雲端計算+以Docker為代表的容器技術這兩種可用的基礎設施平臺時,如何利用二者的關係為產品研發測試帶來效益,是至關重要的。對於競爭激烈、快速革新的網際網路企業而言,持續創新及快速交付服務是其打造產品核心競爭力的重要因素之一。特別是在產品設計、功能實現、快速釋出到視覺化管理等方面,無疑都需要自動化測試、敏捷開發、持續整合(CI)和持續交付(CD)等方式進行高效支撐。其中,產品開發和自動化測試等重要環節,對環境的執行能力都提出了更高的要求。

我們深知,僅僅有一些方法和工具是不夠的,真正給產品開發帶來價值的,是如何完成產品的敏捷創新、降低風險,並根據市場反饋及時變更產品等。在這方面,OpenStack社群的做法是成功的。當然,我們可以借鑑其優勢,將其引入到自己的業務環境中。在開發階段,通過CI對專案進行持續整合、自動化編譯和測試,以達到控制程式碼質量的目的,持續提升開發效率,同時在交付階段,利用CD幫助在短週期內生產有價值的產品,並且保證能夠在任何時間進行釋出。

設計與實現基於OpenStack雲端計算+Docker容器技術的CI/CD服務,其核心是在OpenStack IaaS雲端計算平臺上建立虛擬機器,實現基於OpenStack研發測試業務背景下的CI/CD服務。

這裡涉及三個重要組成部分:一是基於原生OpenStack研發的雲端計算產品,以及基於OpenStack基礎設施平臺構建的CI/CD服務;二是包括諸如Jenkins、GitLab、Gerrit、Harbor等系統在內的CI/CD應用;三是將OpenStack每個服務容器化,並使用Kolla方式部署。

基於雲服務的CI/CD服務,可以實現彈性伸縮和橫向擴充套件等。本節將以案例方式進行實踐,如下圖所示:

圖片描述

首先在物理伺服器上搭建好OpenStack IaaS雲平臺,以及建立數臺可用的虛擬機器等,以備後續使用。

建議:在生產環境中,通過建立並掛載雲硬碟到虛擬機器中執行的服務資料目錄下,或者通過rsync同步備份資料的方式,以保證資料的高可用性和完整性。對於CI/CD系統的HA(高可用性)等,可以通過計算節點HA或虛擬機器HA的方式實現。

所用到的持續整合和持續交付平臺如下表所示:

系統 IP地址 用途
Jenkins 172.16.71.235 持續整合系統,是整個CI/CD環境的核心任務系統
Jenkins_slave+Tempest 172.16.70.199 Jenkins Slave節點,用於執行具體的Job任務
GitLab 172.16.71.236 程式碼倉庫託管系統
Gerrit 172.16.71.118 程式碼評審系統
Harbor_test 172.16.71.221 Docker映象管理測試系統(Registry)
Harbor_devel 172.16.71.222 Docker映象管理開發系統(Registry)
OpenStack all-in-one 172.16.71.230 OpenStack單節點環境

在實際的企業研發測試和CI/CD環境下,建議使用三個Harbor系統並相互關聯,一個是開發系統,用於存放和管理平時開發人員上傳的開發Docker映象,該系統允許存放同一個映象的不同副本(tag);一個是測試系統,用於存放經過了CI/CD流程驗證測試的Docker映象;一個是生產系統,用於存放釋出的Docker映象,其產出物便是用於交付的最終產品。

2.1 基於Docker的軟體持續交付

目前,Docker容器已經在IT軟體生產的各個環節中得到了大量的推廣和使用,如從軟體開發,到持續整合和持續交付,再到生產環境上的微服務應用等。除了Docker技術本身的發展以外,還不斷湧現出一系列與容器相關的生態應用,包括容器編排、高可用性、運維監控和日誌收集等各個方面。

在基於容器的持續交付實現當中,以映象為內容傳遞的單元,通過CI(持續整合)的測試以及驗證,完成映象從開發、測試到可釋出的狀態轉變和軟體的交付流程,如下圖所示。

圖片描述

  • 開發人員:編寫和提交程式碼,從提交程式碼起,這一過程均自動化完成,完成所屬範圍的工作內容,負責輸出待測試的映象。
  • 測試人員:編寫測試用例,手動或自動部署環境,執行各種測試,完成所屬範圍的工作內容,負責輸出預釋出的映象。
  • 運維人員:將預釋出的映象部署到預生產環境中,執行驗收測試,完成所屬範圍的工作內容,負責生產環境的部署和運維。

1.持續整合和持續交付流水線

建立持續整合和持續交付流水線的核心問題是如何定義企業的軟體交付價值流動。價值流動涉及各個職能團隊的高度協同,在以映象作為不同職能團隊之間的價值傳遞物當中,其基於容器的CI/CD流水線的設計應該遵循如下一些基本原則。

  • 視覺化:流水線的執行和停止、成功與失敗應對所有人直觀可見,以掌握全域性變化。
  • 資訊反饋:流水線應通過郵件等多種手段,及時將失敗資訊傳達給相關團隊成員。
  • 可控制:從開發到生產釋出總有一些環節需要人手動驗證,比如迴歸測試、環境配置等,也就需要流水線在某些環節可以暫停,等待手動繼續。
  • 門禁:流水線中任何一個環節失敗,都應該讓流水線停下來,並通知團隊解決,比如自動化測試不通過、程式碼或映象構建失敗等。

持續整合和持續交付(CI/CD)流水線的建立,主要包括開發流水線、測試流水線和生產運維流水線3種,如下圖所示:

圖片描述

(1)開發流水線

開發人員:頻繁提交程式碼,通過持續地編譯、打包、測試、映象構建和自動化測試等環節,產生可測試的候選映象列表(如0.1-dev)。

  • 以原始碼倉庫為起點,開發人員頻繁提交程式碼,每一次程式碼變更都要立即在流水線中傳遞;Jenkins持續整合平臺支援定時週期觸發、程式碼變更檢查以及Webhooks等多種觸發方式。
  • 手動測試階段,當新的程式碼提交部署到環境中後,開發人員可以快速地進行手動測試,確保新提交的程式碼在測試環境中是可用的,並且滿足相關的功能需求。
  • 自動化測試階段,該階段主要是使用JUnit、Pytest、Selenium、Cucumber等自動化測試框架進行單元測試、功能測試等一系列的自動化測試,同時還可以根據需要在持續交付流水線中整合Sonarqube進行程式碼的質量跟蹤和管理。
  • 映象構建,當所提交的程式碼通過了整個流水線的持續驗證後,就會產生相應版本的Docker映象。

基於流水線中的持續驗證和程式碼質量資料,團隊可以快速處理典型的程式碼質量問題,避免累積。總而言之,開發流水線可以幫助團隊頻繁地進行程式碼整合並通過單元測試、程式碼靜態分析、自動化測試等,有效幫助開發人員及時發現和解決問題,最終輸出待測試的映象列表。

(2)測試流水線

測試人員:從候選測試映象列表中選擇需要測試的目標映象,標記為測試版本(如將0.1-dev標記為0.1-test),並且將待測試映象自動部署到驗收測試環境中進行測試,對於測試通過的映象標記為預釋出版本(如將0.1-test 標記為 0.1-beta)。

測試階段,從功能交付斷言整個系統是能夠滿足需求設計或客戶規範的,該階段會進行一系列的手動或自動化測試,同時基於容器技術解決異構環境下的依賴問題。

對於測試人員而言,流水線的起點則變為待測試的映象列表,基於Jenkins建立類似的流水線,可以支援測試人員快速建立測試環境,並且執行相關的自動化測試指令碼,同時滿足手動探索性測試的需求。

(3)生產運維流水線

運維人員:從預釋出映象列表中選擇映象部署到預釋出環境中,在驗證通過後標記為release版本(如將0.1-beta 標記為 0.1-release),最後釋出到生產環境中。

與自動化測試流水線相同,運維人員可以建立獨立的部署流水線,從待發布的映象列表中選擇映象釋出到生產環境Registry中,並且設定流水線的自動或者手動觸發,實現預生產環境的一鍵部署。

2.2 基於OpenStack+Docker的應用部署

Docker產生應用映象有兩種辦法:一種是啟動一個基礎映象(比如基於CentOS的Linux映象),然後在容器中執行各種命令來安裝相應的軟體包,進行配置後,再通過Docker commit命令把已經更新的容器儲存為相應的映象;另一種方法則是通過編寫Dockerfile檔案,然後使用Docker build命令自動化構建相應的映象。

相比第一種手工方式,通過Dockerfile檔案的方式可以更好地維護映象,並將Dockerfile 提交到版本庫進行管理。並且通過CI/CD系統的自動化build、push、pull、run等工作流,可以與研發測試業務更緊密地結合起來。維護的不再是一條條零散的命令,而是一個檔案集合。這樣,Dockerfile檔案便如同程式碼一樣,做到隨時維護修改和協作開發。

將所有的原始碼存放在私有倉庫GitLab中,Docker映象則託管在私有Registry中,並使用諸如Ansible之類的自動化工具將容器部署到伺服器環境中,這些都是一個完全自動化的過程。Docker典型的應用場景包括:

1.測試

Docker很適合用於標準化場景中,將Docker封裝後直接提供給測試人員進行環境搭建與部署,不再需要與運維、開發人員進行協商。同時,還可以很容易地將測試資料與應用服務分離,根據不同的測試場景隨時進行映象—容器切換。

2.開發

開發人員使用同一個Docker映象,同時修改的原始碼都掛載到本地磁碟上,然後對映到容器中。不再為因為環境的不同而造成不同的程式行為而傷透腦筋,同時新人到崗時也能迅速建立起開發、編譯環境。

3.PaaS雲服務

Docker可以支援命令列封裝與程式設計,通過自動載入與服務自發現,可以很方便地將封裝於Docker映象中的服務擴充套件成雲服務,根據業務請求的規模隨時增加或減少容器的執行數量,實現彈性伸縮和橫向擴充套件。

2.3 基於OpenStack+Docker的CI/CD流程設計

構建基於OpenStack+Docker雲平臺研發測試用的CI/CD系統,其核心元件包括:Jenkins持續整合系統、GitLab程式碼倉庫管理系統、Harbor私有映象倉庫管理系統、Gerrit程式碼評審系統等。

基於OpenStack+Docker的CI/CD任務分解和流程設計步驟如下圖所示。

圖片描述

①開發者準備好一個單節點環境,將開發工具連結到遠端開發目錄,並使用Git將程式碼提交到程式碼評審系統Gerrit中,目的是通過協作發現一些明顯的問題,減少把Bug帶到軟體中的概率。

②當Jenkins持續整合系統檢測到Gerrit系統的程式碼提交事件後,觸發相關的Job任務,自動化執行程式碼編譯、打包、構建、部署和測試等工作流。相應地,會執行如下任務:

  • 執行原始碼編譯、打包,如RPM、WAR包等。
  • 構建Docker映象。
  • 部署環境,如使用Kolla自動化部署OpenStack。
  • 自動化執行測試,如單元測試、整合測試等。測試結果有兩種,一種是測試失敗,流程返回到步驟1;一種是測試成功,流程繼續。

③根據測試結果和其他資訊綜合決定此次開發人員提交的程式碼是否合併,這樣保證只有通過了測試和稽核的程式碼才能合併到GitLab倉庫中。

④ GitLab的Webhooks會觸發Jenkins系統中的兩個構建任務,一個是原始碼編譯、打包任務;一個是原始碼打包後的Docker映象構建任務。Docker映象構建後,Jenkins系統會自動將映象推送到私有Registry倉庫中。整個流程如下圖所示:

圖片描述

圍繞以Jenkins系統為中心的自動化測試、整合和釋出平臺,開發人員可以經常整合自己開發的程式碼,而每次整合都要通過自動化構建來驗證,包括自動化編譯和測試,從而儘快地發現整合錯誤。

同時,以GitLab作為自託管的Git專案倉庫平臺,配合程式碼評審系統Gerrit,在程式碼合併前進行審查。一個團隊內的參與者,可以相互審閱各自修改後的程式碼,決定是否能夠提交,或者退回繼續修改。

這些應用系統的實現可以滿足OpenStack研發測試的日常需求,這樣,開發人員和QA測試人員就不需要關心從何處獲取程式碼,尋找環境來做軟體打包、環境部署、驗證測試等了。相關人員只需要分別編寫好各自負責的那部分程式碼,然後關聯到相應的環境中即可。

首先,以Jenkins為核心的任務排程系統,自動觸發程式碼編譯、構建和打包;然後,GitLab和Gerrit協作完成程式碼及軟體倉庫的管理。由於OpenStack環境的部署對相關資源服務依賴性較強,因此,需要使用自動化部署管理工具。這裡選擇使用Kolla方式,實現高效的配置管理和持續部署,從程式碼打包、Docker映象構建、部署實施到驗證測試等環節,自動化實現程式碼持續整合的一系列任務。

Docker是一種標準化的開發、測試、部署和運維方式,通過Docker映象,我們可以在開發、測試、線上等各個階段無差別地使用服務,可以在本地端,也可以在雲端執行程式。

很多企業內部都有一套標準化規範,在這套規範中定義了開發所使用的語言、框架、軟體包版本及依賴環境等,這樣做可以統一開發環境並解決因差異化帶來的其他問題。基於此,我們可以根據不同的服務進行邏輯或物理上的分組,如下圖所示:

圖片描述

在上圖中,把Docker映象分為了三層:基礎映象層、服務映象層和應用映象層。上層映象的構建依賴於下層映象,越下層的映象越穩定,也越不會經常變更。

  • 基礎映象層:負責安裝最基本的、所有映象都需要的軟體及環境,例如作業系統等。
  • 服務映象層:負責構建符合企業標準化規範的映象,這一層很像SaaS,例如Python環境、某個專案的公共軟體包等。
  • 應用映象層:負責部署和執行應用程式,這個階段是CI的產出物,例如rpm包、Python原始檔等。

分層後,由於下層映象已經提供了應用所需要的全部依賴環境,因此可以顯著加快應用映象層構建的速度。對於容器而言,它只操作變更的部分,已經存在且沒變化的內容則不做任何操作。

典型地,在Dockerfile檔案中使用FROM命令構建基礎映象層,如選擇CentOS 7作為所有容器的基礎作業系統;依據標準化規範,安裝Nova計算專案的公共軟體包,構建服務映象層;最後安裝指定的軟體包,構建應用映象層。

glance-base映象的Dockerfile檔案內容如下:

FROM {{ namespace }}/{{ image_prefix }}OpenStack-base:{{ tag }}
MAINTAINER {{ maintainer }}

{% block glance_base_header %}{% endblock %}

{% import "macros.j2" as macros with context %}

{% if install_type == 'binary' %}
    {% if base_distro in ['centos', 'fedora', 'oraclelinux', 'rhel'] %}
        {% set glance_base_packages = [
            'OpenStack-glance',
            'Python-rbd',
            'Python-rados'
        ] %}
    {% elif base_distro in ['ubuntu'] %}
        {% set glance_base_packages = [
            'glance',
            'Python-rbd',
            'Python-rados'
        ] %}
    {% endif %}

{{ macros.install_packages(glance_base_packages | customizable("packages")) }}

{% elif install_type == 'source' %}
    {% set glance_base_packages = [
        'Python-rbd',
        'Python-rados'
    ] %}

{{ macros.install_packages(glance_base_packages | customizable("packages")) }}

ADD glance-base-archive /glance-base-source
RUN ln -s glance-base-source/* glance \
    && useradd --user-group glance \
    && /var/lib/kolla/venv/bin/pip --no-cache-dir install --upgrade -c requirements/upper-constraints.txt /glance[cinder] \
    && mkdir -p /etc/glance /var/lib/glance /home/glance \
    && cp -r /glance/etc/* /etc/glance/ \
    && chown -R glance: /etc/glance /var/lib/glance /home/glance

{% endif %}

COPY glance_sudoers /etc/sudoers.d/kolla_glance_sudoers
COPY extend_start.sh /usr/local/bin/kolla_extend_start

RUN usermod -a -G kolla glance \
    && chmod 750 /etc/sudoers.d \
    && chmod 440 /etc/sudoers.d/kolla_glance_sudoers \
    && touch /usr/local/bin/kolla_glance_extend_start \
    && chmod 755 /usr/local/bin/kolla_extend_start /usr/local/bin/kolla_glance_extend_start

{% block glance_base_footer %}{% endblock %}
{% block footer %}{% endblock %}
{{ include_footer }}

glance-api映象的Dockerfile檔案內容如下:

FROM {{ namespace }}/{{ image_prefix }}glance-base:{{ tag }}
MAINTAINER {{ maintainer }}

{% block glance_api_header %}{% endblock %}

COPY extend_start.sh /usr/local/bin/kolla_glance_extend_start
RUN chmod 755 /usr/local/bin/kolla_glance_extend_start

{% block glance_api_footer %}{% endblock %}
{% block footer %}{% endblock %}
{{ include_footer }}

USER glance

相關文章