天天看點

聯想企業網盤:SaaS服務叢集化持續傳遞實踐

當代資訊技術飛速發展,軟體和系統的代碼規模都變得越來越大,而且元件衆多,依賴繁複,每次新版本的釋出都仿佛是乘坐一次無座的綠皮車長途夜行,疲憊不堪。軟體傳遞是一個複雜的工程,涉及到軟體開發的各個細節,其中任何一環出現問題,都會導緻軟體不能及時傳遞,或者傳遞的品質堪憂。

從企業的角度來講,如何利用更科學的工具、更科學的流程來提高産品品質,提升客戶滿意度,是剛需。從員工角度來講,生命裡值得追求的事情很多,不能把寶貴的時間浪費在一些機械的、重複的事情上面。

聯想企業網盤從2007年開始面向企業客戶提供專業的雲存儲服務,10年來服務了250000+企業。軟體的更新疊代司空見慣,聯想企業網盤就是由成百上千台伺服器組成的,是一個非常複雜的網際網路應用,僅僅在服務端就有幾十個子產品協同工作,加上各種用戶端,需要使用不同的編譯釋出環境,有時候需要單獨子產品釋出,有時候需要多個子產品聯合釋出,使得每次的更新情況都非常複雜。曾經經曆過一次大版本的更新疊代,運維和研發團隊不眠不休的工作了40多個小時,既影響了使用者的服務,也使得團隊疲憊不堪。類似的經曆,使得我們思考如何通過技術革新來解決這一難題,能夠把我們的工程師們從簡單勞動中解放出來,這樣在未來面對更大規模的叢集的時候,才能夠遊刃有餘。

縮短上線時間,提高上線準确度,是我們建設這個系統的初衷。

2 問題

先讓我們借用一張圖(來源于 thoughtworks 官方文檔)來回顧一下軟體釋出的一個完整的流程:

聯想企業網盤:SaaS服務叢集化持續傳遞實踐

整個過程中,代碼管理,內建和測試,釋出上線是3個主要的環節。我們所有的問題都集中在這3個環節當中。

 1、代碼管理

代碼管理混亂是一個研發團隊的常見問題,研發的過程中,代碼的分支設計不合理,分支過多或者過少,分支依賴混亂,權限控制缺失,完全靠人治,沒有代碼稽核。

2、內建和測試

從研發環境到測試環境,都沒有統一規範的部署環境,研發團隊直接給測試出版本(野版本),因為編譯環境,人員水準的差異會導緻各種莫名其妙(有時候很低級)的問題,極大的影響了測試的效率和準确度。

 3、上線傳遞

代碼最終部署到生産環境的時候,需要運維人員和研發人員頻繁手工操作,費時費力,還容易出錯,整個過程不可重複且沒有記錄,復原操作複雜,有時候甚至是無法復原的,一旦是上線出現錯誤,對我們使用者的影響就是非常惡劣的。

3 實踐

多年來,我們在研發過程中不斷總結,想了很多的辦法,在服務客戶的同時積累了大量的生産環境運維經驗,開發了許多工具和流程,來解決更新和産品上線的問題。,下面基于聯想企業網盤的生産實踐,分享一些我們在建設持續傳遞系統方面的方法。

如下圖所示,我們主要讨論這幾個方面:

聯想企業網盤:SaaS服務叢集化持續傳遞實踐

  3.1 代碼管理

代碼是軟體傳遞過程的源頭,是以合理的規劃與管理尤為重要。

3.1.1 代碼倉庫

早期,我們所有研發人員的代碼都存放在一個 svn 庫裡,分支和 tag 散布在各個子產品的子目錄裡。svn 是很好的一個工具,但是太靈活了,要大家嚴格遵守紀律,但是更多時候要靠大家自覺,但是人總是會有松懈的時候。一旦有人不守紀律,對于後來者就是一個苦不堪言過程。

是以我們的第一步,就是把 svn 遷移至 git。按照子產品拆分為單獨的庫,每個子產品單獨授權,統一分支模型。倉庫軟體用的 gerrit,它原本是代碼稽核工具,擁有強大的權限管理系統,git 倉庫隻是附帶的功能。

其實在從svn遷移到git的時候,有很多工程師會有疑問,為什麼遷移到 git?不是 svn 不好,也不是為了追逐技術潮流,而是後面的自動化工作(包括代碼稽核工具)用 git 更友善,當然 git 強大的分支功能以及分布式也是一個重要原因。

3.1.2 分支設計

分支我們參考比較常見的一個 git 分支模型(參考連結),針對我們自己的需求做了一些調整,如下圖:

聯想企業網盤:SaaS服務叢集化持續傳遞實踐

1、 設計兩條主分支,dev 和 master,dev 是開發分支,master 是對外的穩定分支,持續傳遞系統會從master分支拉取代碼進行建構;

2、 輔助分支隻使用 feature 分支和 hotfix 分支,feature 分支原則上是盡量不建,隻用于開發周期比較長的新功能開發,短平快的 feature 都直接送出至 dev。

3.1.3 稽核

代碼是産品品質的源頭,代碼品質不行,其他再多輔助手段都沒用。代碼稽核是保證代碼品質至關重要的一環。隻要團隊人員數大于一個就應該推行代碼稽核。

代碼稽核有兩種模式:

l 內建前稽核(pre review)

顧名思義,在代碼合并至目标分支前進行代碼稽核,有問題改,改完再繼續稽核,稽核通過則內建進目标分支,這一類稽核的代表工具軟體有:github,gerrit,其中 github 是以分支為機關進行稽核,gerrit 以送出為機關進行稽核。

l 內建後稽核(post review)

先合并代碼,然後進行稽核,有問題隻能用新的送出來修複了,這一類稽核的代表工具軟體(其實這兩款軟體也支援 pre review):reviewboard,phabricator。此種方式容易導緻目标分支不穩定,是以一般不建議。

我們采用的是第一種內建前稽核的方式,工具軟體用的 gerrit,以送出為機關,強制稽核過後再合并至目标分支(當然這個過程是自動的)。

好了,話不多說,有圖有真相,下圖是我們的代碼送出工作流:

聯想企業網盤:SaaS服務叢集化持續傳遞實踐

圖中黃色的部分即是代碼稽核的部分,每個送出需要經過其他人稽核(code review +2)和持續內建系統驗證過(verify +1)才能合并至目标分支。

代碼稽核頁面:

聯想企業網盤:SaaS服務叢集化持續傳遞實踐

  3.2 建構部署

在這裡我簡單的将建構部署分為持續內建和部署流水線,實際上,這兩塊很多地方有重合,這裡的持續內建僅僅隻讨論建構驗證和自動內建,部署流水線包括從建構到部署至不同環境的整個過程。

3.2.1 持續內建

持續內建是一個大的議題,是靈活開發的一項核心實踐。在持續傳遞過程當中,持續內建将從開發到部署的各個環節組成一條流水線,是整個傳遞過程的核心。重點是要快速回報,在內建代碼之前迅速發現問題并改正。

我們把單元測試、編譯驗證、靜态掃描和覆寫率檢測分離出來(這一步驟的時間控制在 5分鐘内,這也是前面為什麼要把庫拆分的原因之一),在研發人員送出代碼後立即觸發建構,在5分鐘内把結果回報給研發人員,繼而快速修複錯誤,直至驗證通過。

我們采用的工具軟體是 jenkins,最流行的持續內建軟體,通過插件支援 gerrit,功能非常強大。

在實際的實施過程當中,要求每個子產品都要提供在一個幹淨環境執行編譯、單元測試等等步驟的腳本或方法,建構環境可以通過 vagrant 或者 docker 來自動配置,我們内部采用了docker 技術來隔離各個建構環境。

流水線

聯想企業網盤:SaaS服務叢集化持續傳遞實踐

  3.2.2 部署流水線

顧名思義,這一步驟就是把打包好的軟體部署到不同的運作環境,并且要自動處理各個環境的配置(例如域名、資料庫資訊、登入資訊等等),此步驟嚴重依賴于前面步驟的實作,倉庫的規劃、分支的規劃、持續內建的流水線建構等等。

一個典型的部署流水線

聯想企業網盤:SaaS服務叢集化持續傳遞實踐

  在建構部署流水線的時候,我們要遵循幾個原則:

1、 過程可重複;

2、 一次建構多地部署;

3、 子產品化部署;

4、 變更管理;

5、 審計功能;

6、 快速復原。

在選擇部署工具方面,我們考察過兩個:thoughtworks go 和 jenkins(插件 delivery pipeline)。

go 系統自帶管道,但是靈活性不如 jenkins;jenkins 的一個好處是我們的持續內建都在 jenkins 裡實作,很多腳本都可以複用,甚至很多任務都能直接複用,缺點是管道各任務之間資料共享比較繁瑣,需要額外的插件(例如 copy artifact),是以實作的不是很自然。

在實際的實施過程當中,能夠完全實作自動化(無人值守釋出)是一種理想狀态,但實踐當中總是會受各種因素制約,是以必要時也必須向現實低頭。我們最終實作了一鍵部署加關鍵環境(例如生産環境)手工觸發(下面圖中的播放小箭頭就是這樣的步驟)相結合的流程,參見下圖:

聯想企業網盤:SaaS服務叢集化持續傳遞實踐

在實施過程當中,配置檔案的管理也是很重要的一個議題。配置檔案主要分為兩類:

1、 配置檔案與運作程式不能分離,像j2ee這樣的應用,配置檔案與編譯成果物打包成一個 war 檔案,我們的處理方法是把敏感資訊(例如資料庫資訊)存放在其他的git 庫,建構的時候針對不同環境分别建構,建構時由jenkins 自動記錄代碼的版本和配置檔案的版本;

2、 配置檔案與運作程式可以分離,類似于 nginx 這樣,我們把程式打包成 rpm 或者 deb ,配置檔案存放在 puppet 主伺服器上,每次部署都觸發 puppet 的自動分發。

在持續傳遞流程中,我們可以清楚的知道目前每個環節,每個節點都處在一個什麼版本狀态,這對于清晰的了解,快速復原非常有用。參見下圖,某項目部分子產品不同環境版本資訊(請忽略頁面醜陋這個細節,紅色即表示某個子產品正在釋出,還沒最終上線):

聯想企業網盤:SaaS服務叢集化持續傳遞實踐

  4 尾聲

目前聯想企業網盤的服務已經全面采用流程化的上線傳遞體系,從研發環境到測試環境到生産環境,全部是流水線作業,保證了各個子產品間代碼和版本的一緻性,代表的內建、釋出隻需要我們輕點一下滑鼠,然後就可以喝着茶耐心等待收到釋出成功的郵件了。

持續傳遞是一個長期的需要不斷完善的過程,公司的政策在變,産品需求在變,人在變,流程也在變,我們所做的僅僅是開始,還需要繼續去摸索,磨合,打造出更為完善的傳遞系統。這是一個任何軟體開發團隊都需要重點考慮的事情,建立規範,制定流程,利用科學的工具來實踐規範和流程,脫離小作坊式的傳遞模式,按時按質按量傳遞産品。

本文轉自d1net(轉載)