?
本文目錄:
?
一、背景
二、我們的需求是什么?
三、概念澄清
四、概念模型
五、總體設計
六、關鍵點設計
七、總結
?
一、背景
?
?
說到自動化部署,大家肯定都會想到一些配置管理工具,像ansible,chef,puppet, saltstack等等。雖然這些工具給運維效率和安全性帶來了很多好處。但是實際工作中,我們還是會遇到一些問題:?
?
-
這些工具無法普及到開發、測試人員,經常找運維幫忙,無法自助;?
-
項目人員無法直觀的參看到系統的部署架構設計,及架構的演進過程;?
-
從物理架構設計到最終上線,無法形成閉環;?
-
受差異性的基礎設施影響較大。
?
二、我們的需求是什么?
?
?
我們DevOps平臺的部署模塊就克服上面這些問題,為實現DevOps以產品為核心,以項目管理為驅動,將需求、設計、交付、運維整個鏈路打通這一目標提供有力支持。具體來看其需求涵蓋一下幾點:?
?
-
將架構設計納入DevOps管理過程中,支持架構設計版本化;?
-
一次架構設計多次部署;?
-
以最佳實踐為基礎,實現架構設計模版重用;?
-
多環境部署,同時支持應用在虛擬機、容器上的部署;?
-
支持多種部署模式(單機、高可用)、部署策略(全新、藍綠、滾動升級、回滾)
?
?
三、概念澄清
?
?
在正式講解我們的設計之前,我們想澄清CI/CD的基本概念,因為本次的主題和持續集成、持續交付和持續部署這些名詞總有些淵源。
?
?
?
1、什么是持續集成?
?
?
?
持續集成(Continuous Integration)指的是,頻繁地將代碼集成到主干,以便快速發現錯誤、防止分支大幅度偏離主干。?
?
持續集成的目的,就是在產品快速迭代的同時保持代碼質量,它的核心措施主要有兩點:?
1)代碼集成到主干之前,必須通過自動化測試,只要有一個測試用例失敗,就不能集成。?
2)通過Code Review、代碼質量分析工具對代碼質量進行把關,以便確定是否能夠集成。
?
Martin Flower說過, “持續集成并不能消除Bug,而是讓他們非常容易發現和改正。”
?
2、什么是持續交付?
?
?
?
持續交付(Continuous Delivery)指的是,新版本為了能夠快速安全的交付到生產環境中,需要將新版本先交付到類生產(Production-like)環境中(如UAT/Staging/Lab環境),以便進行相應的業務驗證、安全驗證、性能驗證等過程。?
?
一旦類生產環境驗證通過,新版本就進入到生產階段。?
?
持續交付可以看作是持續集成的進一步。它強調的是,不管怎么更新,軟件是隨時隨地可以交付的。
?
?
3、什么是持續部署?
?
?
?
持續部署(Continuous Deployment)指的是,新版本通過類生產環境的驗證后,自動部署到生產環境中。?
?
持續部署可以看成持續交付的進一步。持續部署的前提是自動化完成測試、構建、驗證等步驟。?
?
持續部署的目標是,代碼在任何時刻都可以進入自動地進入生產階段,為最終用戶提供服務。?
?
持續交付和持續部署的區別可以參考下圖:
?
(點擊可放大查看)
從上圖中,我們可以看出:
持續交付流程將自動的測試新版本應用,但是否將新版本交付到生產環境中是一個手動過程。持續部署則是自動地將新版本交付到生產環境中去。
?
關于持續交付/持續部署,我們不能說哪一個是最好的方案。對于不同的組織,適合的就是最好的。
?
?
4、什么是自動化部署?
?
?
自動化部署(Automatic Deployment)指的是,通過自動化工具將應用介質部署到指定環境中去。?
自動化部署只是持續交付和持續部署流程中的一個功能單元。?
自動化部署工具:Ansible、Puppet、SaltStack等等。?
?
通過以上概念的澄清,我們了解了什么是持續集成、持續交付、持續部署以及自動化部署。?
本文的主題不是介紹持續集成、持續交付、持續部署的Pipeline與實現,而是介紹DevOps平臺中,在傳統自動化部署工具之上的自動化部署框架的設計與實現。而自動化部署模塊也是我們DevOps平臺中的CI/CD的底層能力。?
?
下面我們就來聊聊具體的設計。
?
四、概念模型
?
(點擊可放大查看)
除了系統內置的一些模版概念,我們將自動化部署流程分為三個階段,即設計、轉換、運維。每個階段都會有相應的基本模型。?
下面,我們分階段的去解釋一下這些概念模型。
?
?
1、設計階段
?
設計(Design),是在裝配(Assembly)內對應用/系統的架構的描述;而應用/系統,是由含有多個組件(Component)的系統(Platform)組成的。?
Design階段的基本流程:
?
(1)創建裝配(Assembly)?
-
通過選擇可用的系統模版(Platform Template),添加一個新的Platform;
-
每一個Platform都對應一種應用(如mysql,tomcat,springboot,nginx);
-
每一個Platform都是有一組組件(Component)組成的,并且已定義好了組件之間的依賴關系;
-
在Assembly內,用戶可以通過設置Platform Link設置各個Platform之間的關系
?
(2)配置系統(Platform)內的組件(Component)的屬性值?
-
Component是最底層的部署(或者配置)單元,如springboot中的secgroup, compute, os, jdk, fatjar, lb都是一個組件;
-
每一個Component都有相應的配置模版
?
(3)提交設計?
-
提交的過程是將已經完成的設計做一次Commit,做一次歸檔。
?
2、轉換階段
?
轉換(Transition),是在Assembly內對應用/系統在某一Environment內的部署過程。?
Transition階段的基本流程:?
?
(1)創建部署環境(Deploy Environment)?
-
根據環境類型(如dev, test, prod等),添加屬于某個Assembly的部署環境
-
部署之前,部署環境是應用/系統用于部署的配置的抽象
-
部署之后,部署環境就是管理和監控應用/系統的具體實例的集合
?
(2)配置部署環境?
-
設置每個Platform關聯的資源(vm/container)、部署模式(單點,高可用)
?
(3)選擇Assembly內的一個或多個Platform生成并提交執行計劃?
-
根據部署策略不同,一個Platform的執行計劃可能包含幾個子計劃
?
(4)執行部署?
-
每個Assembly/Environment/Platform下面的每個Component都有一個instance,這些instance可以進行單獨Repair
?
3、運維階段
?
運維(Operation),是在Assembly內對各個部署環境內Instances的管理和監控。?
Operation階段的基本任務:?
?
(1)組件實例運維,例如?
-
Compute:?Status, Reboot, upgrade-os-security, powercycel, repair, upgrade-os-all
-
Tomcat/Jboss:?Status, Stop, Start, Restart, Repair, Debug
-
Artifact: Repair, Redeploy, Custom User Attachment
?
(2)展現正在部署的操作,有可能還會Replace或Cancel其中一項組件部署或整個部署?
?
(3)展示Assembly某一Environment下的組件實例圖譜?
?
(4)日志查詢?
-
對基本的概念模型有了基本認識后,我們來看一下自動化部署框架的總體思路。?
?
五、總體思路
?
DevOps自動化部署框架采用DevOps平臺(設計)+Jenkins(執行)的方式完成。?
?
DevOps的職責
-
完成部署架構設計;
-
根據部署架構設計和部署環境的配置創建生成相應的執行計劃及子執行計劃,每一個子計 ? ?劃對應一個Jenkins pipeline job配置文件(config.xml);
-
查詢Jenkins執行job的實時進度與結果。
?
Jenkins的職責
-
根據config.xml創建Jenkins Pipeline Job;
-
執行pipeline job;
-
Jenkins job 通過pipeline script中ansible/openshift命令進行相應的部署等執行操作;
-
提供查詢job執行情況的Rest API。
?
結合上面提到的三個階段,具體的流程如下所示:
?
(點擊可放大查看)
?
下面是具體的部署視圖:
?
?
(點擊可放大查看)
?
看完整體思路和部署視圖,大家肯定會問為什么選擇jenkins作為具體的執行引擎??
首先,jenkins支持master/slave架構,能根據性能需求水平擴張,slave又可以支持多種環境,可以將不同的job分配到不同的slave節點。?
?
還有非常重要的一點,就是Jenkins Pipeline的能力。?
Jenkins中pipeline的設計理念是實現基于groovy腳本,靈活,可擴展的工作流。
?
-
durable持久性:在jenkins的master按計劃和非計劃的重啟后,pipeline的job仍然能夠工作,不受影響。
-
可暫停性:pipeline基于groovy可以實現job的暫停和等待用戶的輸入或批準然后繼續執行。?
-
更靈活的并行執行,更強的依賴控制,通過groovy腳本可以實現step,stage間的并行執行,和更復雜的相互依賴關系。?
-
可擴展性:通過groovy的編程更容易的擴展插件。
-
豐富插件:Jenkins已經支持通過groovy命令調用git、maven、npm、gradle、shell、junit、sonarqube、ansible、docker、openshift、kubernetes等插件,不需要我們再單獨實現集成。
-
Rest API:Jenkins提供通過Rest API的方式獲取每一個stage的執行情況。
?
由于我們最終會將應用部署到虛擬機和容器云中,虛擬機部署主要通過jenkins中提供的ansible插件+jenkins pipeline script來實現;容器云部署則根據具體的容器云,通過openshift插件(會有一定擴展)或者http request插件+jenkins pipeline script來實現。?
?
下面我們來看一下Jenkins2的主要概念。
?
step, 其實跟jenkins1中的概念一樣, 是jenkins里job中的最小單位,可以認為是一個腳本的調用和一個插件的調用。比如通過git拉取代碼就是一個step,mvn clean package也是一個step,一個http遠程調用等等。 ?
?
node, 是pipleline里groovy的一個概念,node可以給定參數用來選擇agent,node里的steps將會運行在node選擇的agent上。這里與jenkins1的區別是,一個 job里可以有多個node,將job的steps按照需求運行在不同的機器上。例如一個job里有好幾個測試集合需要同時運行在不同的機器上。 ?
?
stage, 是pipeline里groovy里引入的一個虛擬的概念,是一些step的集合,通過stage我們可以將job的所有steps劃分為不同的stage,使得整個job像管道一樣更容易維護。pipleline還有針對stage改進過的view,使得監控更清楚。這里補充一句,多個stage可以在一個node里定義及執行,一個stage內的多個step可以分到不同的node上執行。?
?
六、關鍵點設計
?
前面我們說的都是概念和流程上的東西,那么用戶該如何進行部署架構設計?部署架構設計完成后,如何提交呢? 如何將提交的設計在具體的部署環境中轉換成執行計劃與子執行計劃呢?子計劃又如何與jenkins pipeline job映射呢?這就是我們下面要介紹的一些關鍵點設計。
?
?
1、模塊化
?
?
(點擊可放大查看)
前面提到,當用戶創建Platform時,我們的DevOps平臺提供可選的Platform Template,Platform Template定義了其中可以包含的組件類型(Component Template)等信息。也就是說,我們的平臺提供了一種基于最佳實踐的方式,幫助用戶完成系統的架構設計。不僅如此,通過對Platform Template/Component Template等相關數據準備的介紹,也對以后用戶擴展添加新的組件類型,提供了充足依據。基本思路如下:
?
1)定義不同的系統模版Platform Template(見表DPS_DLV_PLATFORM_TEMPLATE)。系統模版就是我們通過最佳實踐的方式提供了一套應用/中間件系統的模版。如tomcat,nginx、springboot、mysql等。?
一個Platform Template定義了這個模版中包含的組件模版,定義了組件模版之間的依賴關系(見表DPS_DLV_COM_RELATION_DEFINITION),以及每一種組件類型所在的層以及每一種組件類型允許添加的組件的個數(見表DPS_DLV_COMP_CONTAINER_DEFINITION)。當用戶添加一個Platform時,必須要選擇一種Platform Template。?
?
2)根據不同的部署模式(單節點、高可用)、不同的目標資源(虛擬機、容器)、不同的部署策略(全新、藍綠、滾動升級、回滾),一個系統模版會對應到多個執行計劃模版 (見表DPS_DLV_PLATFORM_ACTION_PLAN_TEMPLATE)。?
?
3)一個系統由多個組件組成,因此系統模版和組件模版之間也是多對多的關系。例如springboot模版對應的組件模版有:secgroup模版、os模版、jdk模版、java application模版等等。?
?
組件模版Component Template(見表DPS_DLV_COMP_TEMPLATE)以及組件的所有屬性(見表DPS_DLV_COMP_ATTRIBUTE_DEFINITION)。組件模版就是組件的元數據,為Platform添加的Component都是源于Component Template。?
?
4)為每個Component Template定義Operation模版(見表DPS_DLV_COMP_OPERATION),以便對單個組件實例進行操作,如restart, repair, stop等。 ?
?
通過以上4步系統預置的Platform Template和Component Template以及相應的數據,就可以提供給用戶添加一個Platform了。這些預置數據也為后面生成部署計劃Deploy Plan做好的準備。?
?
?
2、變量管理
?
?
?
在需求分析中,我們就提出希望一次設計多次部署。但是在設計階段設置各個組件屬性時,并不能確定在不同的部署環境中其值是一致的,并且一個系統的不同組件的屬性也可能是共用一個值。這時候我們就需要引入變量管理。變量管理的主要思路如下:?
?
1)設計階段,為系統定義一些變量(ConfigMeta)并設置一個默認值,如install_dir。然后在設置某個組件屬性值時可以用@P{install_dir}來表示。
?
2)提交設計時,也一同將變量定義作為設計的一部分進行提交。?
?
3)轉換階段,在部署環境中,為每一個變量設置當前環境下的值(ConfigValue)。當創建執行計劃時,會將屬性@P{install_dir}替換為當前環境的值。?
?
不僅Platform內可以定義變量供該Platform下的Component使用,我們也可以給Assembly定義變量供所有Platform及其組件使用, 形如@A{assembly_var}。
?
3、設計提交
(點擊可放大查看)
?
當用戶設計完部署架構、設置每個組件屬性及變量后,需要將當前的設計指定好版本進行提交,即歸檔。只有提交的設計,才能在部署環境中獲取的到指定的版本。通過版本化,我們可以設計的不同版本做相關的對比。?
?
上面的表結構是比較清晰的表述。
?
?
?
4、執行計劃
?
-
根據不同的部署模式(單節點、高可用)、不同的目標資源(虛擬機、容器)、不同的部署策略(全新、藍綠、滾動升級、回滾),一個系統模版會對應到多個執行計劃模版,并且計劃模版之間有父子關系。
-
每一個子執行模版就是一個jenkins pipeline script模版。
-
當用戶在部署環境中選擇某個具體系統及部署策略生成相應的執行計劃(含子計劃)時,每一個子計劃的jenkins pipeline script就是將具體的組件屬性注入到執行模版中生成的。
?
另外,為什么需要顯示的創建出子計劃呢?例如,對于一個高可用的應用,除了要部署具體的應用,還需要更新load balance配置,而這兩者之間可能需要加入一些人工活動。所以我們通過顯示的創建處子計劃,支持用戶按子計劃一步步的來做。?
?
而jenkins pipeline script的stage幾乎都對應到一個具體的組件,具體可以看下圖。
?
?
(點擊可放大查看)
?
5、部署策略
?
前面我們提到了“部署策略”這個詞,除了全新部署,我們常見的部署策略有藍綠發布、滾動升級、灰度發布/金絲雀發布、回滾。下面來看看我們的相應解決方案。每一種部署策略都會有相應的執行計劃模版(含子計劃)。?
?
藍綠發布
?
什么是藍綠發布?
在發布的過程中用戶無感知服務的重啟,通常情況下是通過新舊版本并存的方式實現,也就是說在發布的流程中,新的版本和舊的版本是相互熱備的,通過切換路由權重的方式(非0即100)實現不同的應用的上線或者下線。
?
-
前提條件
-
雙份資源 or 支持雙端口模式
-
負載均衡服務 + 操作API接口
?
-
實施方案
-
第一步,設置系統將要部署的資源列表。
-
第二步,將新版本部署容器部署到資源列表中。
-
第三步,調用負載均衡服務的API接口更新負責均衡配置。第四步,更新資源的標簽。
?
考慮到用戶可能會手工介入確定是否需要更新負載配置,我們會將第二步、第三步分為兩個子執行計劃。?
?
滾動升級
?
什么是滾動升級?
滾動發布,一般是取出一個或者多個服務器停止服務,執行更新,并重新將其投入使用。周而復始,直到集群中所有的實例都更新成新版本。?
這種部署方式相對于藍綠部署,更加節約資源——它不需要運行兩個集群、兩倍的實例數。我們可以部分部署,例如每次只取出集群的20%進行升級。?
?
-
前提條件
-
負載均衡服務 + 操作API 接口
?
-
實施方案
-
第一步,設置滾動升級系數(步進),如20%/n個。
-
第二步,依次將20%的部署容器移除負載,然后在原資源處部署新版本,然后加入負載。
?
灰度發布/金絲雀發布
?
什么是灰度發布/金絲雀發布?
灰度發布是增量發布的一種類型,它的執行方式是在原有軟件生產版本可用的情況下,同時部署一個新的版本。同時運行同一個軟件產品的多個版本。?
其實,灰度發布是滾動升級的一種變體,其實灰度發布是先劃分出新版本的路由權重,新版本在真實數據驗證通過后,在進行剩余老版本的升級。?
?
-
前提條件
-
負載均衡服務 + 操作API 接口
?
-
實施方案
-
第一步,設置新老版本的路由權重,如90%的用戶維持使用老版本,10%的用戶使用新版本。
-
第二步,將10%的部署容器移除負載,然后在原資源處部署新版本,然后加入負載。
-
第三步,待真實數據驗證通過后,再進行剩余老版本的滾動升級。
?
回滾
?
什么是回滾?
回滾是指將應用/服務回退到上一可用版本,并使之可用。?
我們暫時只支持針對藍綠發布的回滾。
?
-
前提條件
-
新版本是基于藍綠發布策略完成的部署。
-
負載均衡服務+操作API接口。
?
-
實施方案
?
-
更新負載配置
?
七、總結
?
本文大致向大家介紹了我們的DevOps平臺中自動化部署框架的相關設計,主要簡單介紹了實現思路和幾個關鍵點。?其中還有很多細節,比如如何與CMDB集成,如何與各種容器云集成,以及我們實踐過程中遇到的各種坑等等,這里不再一一贅述,有問題可在本文文末留言。?