通聯數據是如何使用Docker+Rancher構建自動發佈管道的?

你們好,今天我將分享通聯數據使用Docker和Rancher構建自動化發佈管道的經驗,我會介紹通聯數據自動化發佈的流程及方案設計,咱們從踩過的一些坑中總結出來的經驗,以及咱們的自動化發佈管道的系統運行現狀。前端

1、通聯數據的需求及選擇Rancher的緣由

通聯數據是一家這幾年新崛起的金融科技公司,主要目標是致力於將大數據、雲計算、人工智能等技術和專業投資理念相結合,打造國際一流的、具備革命性意義的金融服務平臺。這裏面涉及到幾個關鍵詞:大數據、雲計算、人工智能,這些熱詞已經有不少企業說起過,所以我也不贅述了。nginx

通聯數據做爲一家創業公司,也會遇到不少創業公司都會遇到的問題,好比產品太多,並且每一年不少產品都會推翻重來,就會遇到各類各樣的問題。好比,應用在開發時,涉及到須要多少CPU、須要用什麼語言去編程等問題,開發人員不會與後臺人員事先溝通,出來一個產品,直接讓運維人員上線。web

基於這樣一個背景,咱們迫切須要打通上線這條管道,由於在可預見的未來,通聯數據每一年將會有大量的新應用出現,如何打通上線這條管道亟待解決。編程

咱們作的第一件事,就是作持續集成。因爲咱們公司每一年會有上百個新的項目產生,每一個項目的語言、框架、部署方法都不盡相同,發佈流程也是比較冗長低效的,部署應用佔用了運維人員大量時間。後端

咱們決定用容器解決這個問題,評估了多家供應商後選擇了Rancher,主要緣由在於:安全

首先,Rancher的操做界面很是簡單,相信用過Rancher的人都會有這種感覺,它不須要太多專業的知識,很容易上手;其次,Rancher在部署時也很是簡單,能夠一鍵式部署,Rancher還提供了良好的API支持,方便集成。框架

2、自動化發佈的流程

隨後,咱們開始搭建本身的CI/CD。當時咱們在流程方面遇到了不少困境,下圖已是簡化製做後的了,實際上還有更多各類各樣的分杈和分枝:運維

輸入圖片說明

就咱們原來的流程來講,流程最開始的部分是研發;隨後進入QA環境部署,這時候就須要人去部署,一般是運維人員,可是運維通常不肯意作這個事情;部署完成後,進入QA環境測試階段,通知開發和測試人員進行測試,過程當中可能會出現延遲,由於測試人員可能正忙於其它的事情,不能立刻進行測試;QA環境測試經過後,進入STG環境部署;隨後再進行STG環境測試,這幾個過程可能會循環不少次。跟着進入安全測試階段;測試經過後,還有一個正式包的一個準備過程,最後才能上生產部署。即便是這個簡化後的流程也是很是複雜的,並且其中涉及到不少線下的溝通,效率不可能高得起來。微服務

在使用Rancher以後,本來的流程大大簡化了,改進後的簡化流程以下圖:測試

輸入圖片說明

流程的第一步即持續集成,意味着開發人員寫好代碼後能夠直接經過CI,CI觸發自動編譯,隨後自動部署腳本,測試環境已經就緒。簡單來講,每次開發人員提交代碼以後,測試環境就始終處一個就緒的狀態,這時候就能夠直接進入測試階段,整個過程都處於線下,不須要走任何流程,所有實現自動化了。

測試人員完成測試後,再進行STG環境測試,由於後臺已經跟Rancher完成對接並實現自動化,這賦予了QA環境測試從未有過的強大的自動化能力,意味着QA環境測試能夠自動對接到STG環境測試。測試經過後,進入安全測試階段,這個階段是公司要求的,沒法避免,安全測試經過後就進入到生產部署。之前繞不開的線下溝通那些步驟和一些部署就能夠省去了,整個流程優化而且簡潔,效率也提高了。

CI/CD提及來可能很簡單,好比PUSH代碼、QA環境自動就緒。可是實際操做起來並不是如此,仍然存在不少須要解決的問題。好比開發的分支模型就涉及到在開發代碼的時,要PUSH什麼分支才能部署,仍是PUSH全部的分支都能部署?

3、開發分支模型

當時咱們想到最好就是PUSH任意分支都能部署,這樣就很是方便。但隨後就發現這方法行不通,會形成混亂,並且難以管理。此前咱們Git的一個The Successful Branch Modeling分支模型就相似於此,此模型規定了一個develop分支、一個feature類型的分支、一個release類型的分支、一個hotfixes類型的分支和一個master分支輸入圖片說明

在平時開發時,開發人員經常會在develop分支上切出一個feature的分支,好比,開發一個包含不少功能的story,那麼全部人切一個story,這邊story有本身的ID,而後再去開發,把story開發完以後,再把它merge過來。最終,咱們只選擇了一條線作CI,當代碼PUSH或者合併到develop分支時,咱們幫你去作這個,而在這個feature分支的時候,咱們另做處理。

feature分支意味着當用戶提交一個feature分支以後,咱們會另外幫你部署一套,每個feature分支部署一套,至關於每個story均可以分開獨立去測試,最後把它合併到develop分支。那麼測試的時候,測試能夠根據本身的需求來決定它到底在哪一條分支線上去測試。

好比,A測試中若是用戶只關心story A,那就在story A這個分支測試環境去測,這些story所有合併進來以後,再進行一次集中測試,測試經過後,在發佈時把這個分支切到release 的一個分支上來,而後,在release上發佈正式包,讓QA在STG環境繼續進行測試,就如前面看的那個流程圖。分支模型很是混亂,爲了作CI,咱們會跟開發人員定義好每一條分支,每一個分支對應的每一個不一樣行爲也定義好,這在混亂的分支模型下很是有用。

4、版本號規則

爲了作CI,版本號的規則必須一致,若是每一個團隊版本號命名不同的話,匹配規則就會很是麻煩和混亂。後來,咱們選擇了Semantic Versioning的一個版本號的規則,就是幾點幾點X,這是一種常見的版本號命名方法,此版本號包含標準的一個文檔,文檔描述了此版本號的具體定義,第一個叫MAJOR,第二個叫MINOR,第三個叫PATCH,後面還能夠加各類本身的版本號。 輸入圖片說明

5、CI觸發路徑

下面我將介紹咱們的CI的觸發路徑——Git push,push到develop分支,Git push就會push到Gitlab的server上,隨後經過webhook去調用Jenkins,Jenkins會把這個包bulid出來。本來咱們是想經過Jenkins調用Rancher的API,後來發現直接調用Rancher有差距,過程進行的也不那麼順利,爲了解決Jenkins和Rancher之間的gap這一問題,咱們在它們之間裝了一個Ponyes的軟件。 輸入圖片說明

爲何須要Ponyes這一中間層?它到底提供了哪些價值?

(1)動態修改版本號

首先,它能夠解決動態修改版本號的問題,你們用Rancher的時候,發現Rancher的商店很是好用,咱們能夠在商店裏把一些東西定義好,接着QA只要填幾個參數,就能夠把一個應用部署起來了,沒有Ponyes這一中間層以前,必須找運維人員去作,過程也比較複雜。

爲了用起來Rancher應用商店,咱們還定義了一個應用商店的模板,這樣咱們就能夠在每次PUSH代碼的時候,把這個模板生成一個真正能夠部署的應用。可是,版本號仍是存在一些問題,咱們每次PUSH代碼的時候,到Jenkins,咱們會根據閱覽數給Jenkins升級一次版本號,好比說1.0.1.0-1,第一次閱覽是-1,第二次閱覽即-2,Jenkins的版本號根據閱覽次數相應變化。這時候應用商店也要隨之而變。

所以,咱們作了這樣一個模板,經過這樣一種方式,在Ponyes中,每一個Jenkins能夠得到對應的版本號,而後把這個版本號經過變量把它注入進去:

sample:
  image:    {{ REGISTRY }}/automation/auto-sample:{{ m['auto-sample']}}

這一過程還涉及到registry,由於QA環境和STG環境是徹底分開的,在進行模板渲染時,咱們須要知道究竟是發到QA環境仍是STG環境,從而對registry的地址作出相應改變,這樣的話,上面說的修改版本號的問題就解決了。

(2)多service管理

還有一個比較棘手的問題,即一個stack中有多個服務怎麼辦?好比,一個比較小的團隊可能總共就幾我的,每一個人負責好幾個項目,與微服務的關係有些類似,那麼一個stack可能有好幾個服務,最典型的就是前端、後端,或者是其餘的一些中間件,每一項是一個服務。

開始部署時,Rancher裏面的這些服務也要用一個stack來管理,有多個服務就會面臨怎樣管理的問題。好比,一個stack有ABC三個服務,服務C更新時,整個stack也應該更新版本號,由於在Rancher裏面,stack被部署出來以後,有個update available的黃色按鈕,若是有新版本,點這個按鈕,就能夠升級這個stack,並且必須升級整個stack,而不是隻升級某個服務,這時候就須要管理多個服務。Ponyes記錄了服務和stack之間的關係,任意一個服務更新,也會觸發stack的更新,更新的方法就是每一個服務每次更新,stack的版本號+1。

(3)多版本並行發佈

接下來還有一個更嚴重的問題,若是多版本並行發佈,咱們應該怎麼去處理?好比說咱們ABC三個模塊,A發佈過1.0和2.0,B發佈過3.0、4.0,C發佈過5.0和6.0。若是發佈一個C應用的5.0.2,那麼對應的AB模塊號應該選什麼,這個問題困擾了咱們好久。

有好幾種方法能夠解決,好比用某個東西記錄C5.0和AB的一個版本號之間的關係,這表示用戶能夠自定義。但也存在一個問題,用戶須要本身去管理它們之間的版本號關係,時間長了,可能會弄亂或弄錯版本號,或者弄錯版本號之間的關係,隨後上線到生產環境,後果更嚴重。

還有一種方法,就是將用戶的C版本號最後一次發佈到5.0時AB是什麼版本靜態地記錄下來。但這樣的話系統會變得至關複雜,很容易出錯。

最後,咱們選擇去除多版本並行發佈的能力,只支持單個版本的發佈,意味着若是要發佈,必須是最新版本,歷史版本能夠用另外的方法進行人工處理,這樣的話,系統會更簡單,並且不容易出錯,也不須要用戶去維護一個版本號之間的關係。以上這些功能都是藉助咱們本身寫的Ponyes解決的。

Rancher 2.0也提到了CI/CD這樣一個功能,在實際過程當中,會遇到一個很是現實的問題,從代碼研發到整個生產環境部署有許多環節,具體狀況也很是複雜,而CI的做用可能僅止於QA,後面的環節還會有新的難題,這時就須要一個體系把整個生命週期貫穿起來管理,Rancher承擔的做用就在於此。

6、肉身踩坑總結的三條經驗

(1)部署幾套Rancher環境?

這問題看似很小,最初也在咱們內部也引起過很多討論。最初咱們只部署了一套Rancher,在Rancher裏面用環境去區分QA或production。部署一套Rancher的方式最簡單,可是有一個嚴重的問題:Rancher升級了怎麼辦?這套Rancher既管了QA,又管了production,升級的時候須要把生產環境也升級,此刻若是出現bug,問題將很是嚴重。

後來咱們把它拆成四套,Rancher平臺自己也得有一個升級的環境。建議你們在前期部署Rancher的時候要部署多套環境(至少兩套),咱們其實是dev、QA、staging、production每一個環境都有一套,總共四套。

(2)配置項爆炸

第二個問題是關於配置項。咱們最開始是使用Rancher compose的,它很是簡單強大,咱們在Rancher Catalog裏點一下「部署」,配置選項全彈出來,咱們只須要點選一些東西,就能夠部署一個很複雜的應用。後來咱們卻發現,應用的配置項愈來愈多(甚至多達上百個)。這致使它們難以在一個頁面裏展示,同時上百項的配置讓咱們無從填寫,運維也沒法成功部署,咱們從而面臨了配置項爆炸的問題。

咱們的解決經驗是,在容器平臺裏面,配置項必定要集中管理。咱們把配置項所有用consul管理,每次容器啓動時到consul裏把配置拉到對應的容器裏來。如此一來,容器能夠在任意平臺漂移。另外配置項自己在原server存有副本,咱們copy原配置項加以修改,就能夠部署另外一個實例了。因此說,配置項必定要所有集中管理起來。

(3)泛域名+Rancher LB

咱們每個業務都有一個web服務,要申請本身的域名。每一年咱們有上百個項目上線,這意味着有上百個域名要申請。加上這些域名都分別須要在開發、測試、生產環境中使用,因此咱們每一年要申請將近五百個域名。這是一件恐怖的事情。

後來咱們就用了泛域名的方法。好比用*.sub.example.com的域名,直接CNM到Rancher環境中的其中一臺主機。而後在Rancher上設置它的LB,LB就能夠分佈在全部的主機上,每一個主機上都會有一樣的LB。這個域名任意指向一臺主機,它均可以工做。

好比說,在QA環境,這個LB上serve了以下這些域名,若主機壞掉了,容器自己會啓動,入口問題則能夠很簡單地經過修改*量來搞定。若是是生產環境則能夠在上面再加層nginx,配三個upstream,死掉任意一臺,還能夠經過另外兩個入口進來。

使用泛域名的方法,在配置好泛域名以後,在Rancher LB上再加任意域名都不用再去申請新的域名,而是能夠直接寫123.sub.example.com,而後直接在LB上配置,配完以後域名便可用,無須再走申請的流程了。

相關文章
相關標籤/搜索