談談企業的持續交付流水線設計
本文轉自微訊號EAWorld。掃描下方二維碼,關注成功後,回覆“普元方法+”,將會獲得熱門課堂免費學習機會!
有一天,業務人員急衝衝的跑過來,對你說生產上出現了一個嚴重BUG,必須要儘快修復。你聽完問題描述後,胸有成竹坐定並迅速定位問題,隨後改動了一行程式碼並提交,系統開始自動編譯、各個環境自動化測試、釋出上線。幾分鐘後,生產環境上該BUG已經被修復掉。
上面所提到的場景,這是不是很美妙?但是想必不少讀者要忍不住要吐槽了,這太不實際了:新功能上線測試不要時間麼?新增了功能肯定要做迴歸測試,這都需要一定的時間。況且怎麼可以隨便部署上線?還得通過預發演練、走釋出審批流程。其實這些過程大家也都清楚,那麼不妨從另一個角度思考下,是否可以把這個過程中所有需要人工線下操作的環節都通過一個平臺自動化實現掉呢?
這些其實都是本文要為大家一一解讀的,事實上上述的例子雖然有些理想化,但是卻可以作為一個終極目標,並非沒有實現的可能。
本文目錄:
一、什麼是持續交付?
二、設計持續交付四大關鍵要素
三、落地持續交付五大注意事項
四、總結
一、什麼是持續交付?
首先來了解下持續交付的概念,在維基百科中持續交付的定義如下:
持續交付(Continuous delivery,縮寫為 CD),是一種軟體工程方法,讓軟體產品的產出過程在一個短週期內完成,以保證軟體可以穩定、持續的保持在隨時可以釋出的狀況。它的目標在於讓軟體的編譯、測試與釋出變得更快更頻繁。這種方式可以減少軟體開發的成本與時間,減少風險。
好吧,看定義總是很抽象的,我們從兩個維度來理解持續交付,一個是範圍,一個是宗旨。
先說說範圍,軟體研發的生命週期大家想必都很瞭解,大致包括如下幾個階段,需求、設計、構建(包括開發、編譯)、測試(系統整合測試、使用者驗收測試、非功能性測試)、釋出上線。
持續整合覆蓋構建、測試兩個階段,關注於程式碼的提交、編譯、測試。持續部署意在保障每一個程式碼提交,都能自動化的部署到生產環境上;持續交付和持續部署有些類似,而是保障從原始需求到最終交付上線全過程的穩定可靠,但是不強求自動化部署到生產環境上,在最終釋出上線時,可以人工介入,也可以自動部署。
再看看持續交付的宗旨,持續交付的核心宗旨是:保證每次提交程式碼都產生一個可釋出的版本。下圖是持續交付的一個核心流程圖,程式碼提交觸發構建和單元測試,完成後觸發自動化測試,根據自動化測試的結果進行審批是否進行使用者驗收測試,使用者驗收測試通過後進行釋出上線。中間每一個環節都會產生反饋,一旦失敗就終止當前交付流程。
通過這範圍和宗旨兩方面,是否已經有些瞭解持續交付是什麼了呢?還是有些泛?不急,接下來我們針對持續交付的整個流程進行拆分。
從程式碼提交開始,我們可以把整個持續交付歸納出四個關鍵要素:持續整合、自動化測試、自動化部署、流水線。
二、設計持續交付四大關鍵要素
持續整合
在傳統瀑布開發模式下,通常很長一段時間內,程式碼都是不穩定且不可用的;待到功能開發完畢了,才會進入整合階段,這時問題出現了:團隊規模越大,要開發的需求越多,這個週期就越長,整合階段花費的代價也就越大,專案風險也越大,專案的進度極不可控。
而在敏捷過程中,將程式碼開發和整合按模組拆分成多個小階段,每一階段完成後都會進行整合,這在一定程度上減少了風險。
持續整合要求程式碼的開發和功能整合並行進行,相輔相成,要求至少做到每日編譯甚至程式碼提交即觸發編譯。構建時會對整個應用的所有模組進行編譯,並伴隨單元測試以及程式碼質量分析等動作。如果編譯失敗了或者單元測試失敗了,那麼必須要立即修復問題,直到構建成功。總之,要求程式碼庫的程式碼持續處於可用狀態。
持續整合的時間一定要儘可能的短,尤其是程式碼提交觸發構建的場景下。否則試想:一支20餘人的開發團隊,每次構建(編譯+單元測試+程式碼質量分析)需要花費20多分鐘;而每次程式碼提交時觸發構建,會產生大量的編譯任務排隊,並且會不停增加;編譯發生問題時較難定位,因為在上次開始編譯到這次編譯中間,會有多人提交,很難快速確認是由誰的提交導致的編譯失敗。
持續整合的時間通常建議在5分鐘以內,90秒內完成是極好的。因此對於程式碼的編譯、單元測試都一定要注意時間。在分散式場景下,應用可能會依賴於很多外部應用或者中介軟體,單元測試不一定非要連通真實環境,會帶來請求響應時間的損耗,並且一般也要求單元測試可以在離線環境下可執行,所以可以採用Mock的方式,提升單元測試速度。同樣,由於要控制每次構建的時間,不建議在持續整合流程中去做整合測試(SIT),這個可以交給集測流水線去處理,由測試人員在整合測試環節繼續跟進。
持續整合保證了程式碼始終是可用的,編譯正確並且通過所有單元測試。這是持續交付流水線的第一步。
自動化測試
在整個軟體過程中,測試可以分為兩類:功能測試(冒煙測試、系統整合測試(SIT)、使用者驗收測試(UAT))、非功能性測試(壓力測試、穩定性測試、安全測試)等。非功能性測試姑且不論,功能性測試如系統整合測試、使用者驗收測試等都需要儘可能地覆蓋所有的功能模組,功能越是複雜的應用系統,測試起來的工作量也越大。
雖然自動化測試的理念已經普及了好多年,但是大部分企業內部,還是以手工測試為主,甚至大部分企業,對手工測試的投入也都是不足的。原因有很多,比如人員缺乏和時間週期緊張,來不及寫自動化測試指令碼,或者測試人員的水平不足等。這些確實都是客觀存在的原因,但是這樣真的是節省了成本嗎?事實上對於持續發展的產品而言,每次釋出時都需要大量的人力投入去進行測試,會有大量重複的測試工作,釋出的次數越多,成本越高,某種程度上這甚至限制了快速頻繁釋出的能力,由於人力資源的限制,很多企業迴歸測試時,只能相信開發人員對於功能調整影響範圍的預估,縮小回歸測試的範圍,為線上執行帶來了極大的風險。在《持續交付》一書中看到這樣一個數字:某組織每次釋出軟體是花費在手工測試上的錢就有300萬美元。自動化測試帶來的價值也絕對值得上現在的投入。
想要實現整個持續交付流水線的自動化,實現本文一開始的那個例子,全面的自動化測試不可或缺。只需要花費幾分鐘至幾十分鐘,通過了各個環境的自動化測試,便相當於對質量打上了合格標籤。可以選擇直接部署到生產環境上,或者等待晚上某個時間點進行上線部署。
交付流水線
持續交付是一個大流程,從程式碼提交一直到部署上線,但是我們在實踐過程中發現,這種大流程,未免太大太笨重。在企業真實的情況下,大流程本身沒問題,但是其中的環節往往沒有這麼簡單,想要讓這個流水線真正能被企業實際使用,還要對大流程進行拆分。我們在實踐中把持續交付流水線拆分成三個子流水線:開發流水線、集測流水線、釋出流水線。
開發流水線:
面向開發人員和開發環境。開發人員提交程式碼,觸發構建,部署到開發環境中由開發人員進行自測。這個流水線在開發的過程中會頻繁進行。
集測流水線:
面向測試人員,同樣以構建為開始,基於構建的產物(部署介質),部署到整合測試環境,進行系統整合測試。
釋出流水線:
當次釋出的所有需求全部通過系統整合測試後,便可以進入後續測試如使用者驗收測試、非功能性測試等,通過後,則認為已經達到釋出上線標準,觸發上線申請審批流程,審批通過可以進行自動化釋出上線。
在專案中,開發流水線的觸發頻率最高,集測流水線其次,釋出流水線觸發的頻率最低。
將整個的持續交付流水線拆分為三個子流水線,可以做到面向不同的角色,這樣更靈活也更便於使用。當然,不同企業的流程也是有著區別的,不一定嚴格按照這三個流水線。即使定義成這三個流水線,每個流水線的流程和環節也是不同的,可以結合自己企業的實際流程來拆分。
三、落地持續交付五大注意事項
上面說了很多理論,理論終究要落地實踐,流程和關鍵環節也已經比較清楚了,但是在實際落地時還是會有很多問題和細節點需要注意。先思考下幾個問題:
如何快速支援流程使用過程中的一些微調(如環節的配置欄位屬性等)?
如何做到流程手工和自動執行的自定義?
如何讓每個環境部署的介質對應的是哪次程式碼提交、哪個交付物有跡可循?
如何直觀的檢視交付流程目前到了哪個環節、每個環節的狀態是什麼樣的?
如何以環境為視角,看到該環境下正在執行哪些應用?
帶著上面幾個問題,我們在實踐的過程中,梳理出如下幾個持續交付能力落地的關鍵點:
安全
交付流水線的核心是驅動開發、測試、運維、質量等多個部門和角色進行協作,涉及眾多的角色和功能、又囊括了各個環境的部署運維操作,安全問題自然不容忽視。
明確責任人:流程中每個環節都要有責任人,在人工執行時,只有該責任人才能執行該環節,同時每個環節執行資訊都要有詳細的記錄和展現,如:操作人、開始時間、結束時間、自動化執行時間等。
環境型別授權:而由於自動化部署的支撐,對於每個環境的部署都可以通過平臺一鍵執行。開發、測試環境尚還好,但是對於預發、生產環境的部署,一般要由運維人員來操作。對於環境型別的細分授權,在人工執行的時候,會更加安全。
釋出審批流程:事實上,在企業內部,正常釋出上線通常需要經歷應用釋出審批流程,在生產部署前,根據釋出的型別(如正常釋出、緊急釋出)等來觸發不同的上線審批流程,完成上線審批後,才可以執行部署上線的動作。具體的流程可以結合企業內部實際的流程。
流程支援環節、屬性自定義
理論上說,一個企業的持續交付流程應該是一致並且基本穩定的,但實際上大部分企業內部不止一套流程,不同部門、不同專案組的過程體系甚至都可能是不同的,姑且不論這種情況的對與錯,在尚未統一流程和過程前,這種情況總歸是要考慮支援的。即使統一了流程,隨著企業的不斷髮展,流程的一些細節也會持續變化,如一些環節的屬性配置等。所以對於流程的環境、屬性自定義、可動態擴充套件等能力在設計時是要重點關注的。
保持部署介質不變,便於追溯
很多企業由於規範的不標準,經常會出現最終上線使用的部署介質和系統整合測試、使用者驗收測試的部署介質有所不同。比如在使用者驗收測試階段,發現了一個問題,有可能開發人員改動後直接打一個包進行部署上線,不再通過系統整合測試,或者通過人為的判斷改動影響範圍,進行小範圍測試。這些都帶來了很大的生產隱患。
從標準來說,從系統整合測試開始,後面所有環境應該用的都是同一個介質。在系統整合測試的一開始,進行程式碼構建,得到部署介質。該介質地址在整個流水線上下文中進行傳遞,後面每個環境的部署都採用該介質。如果把集測流水線和釋出流水線分離開,釋出流水線必須要關聯一個整合測試流水線,在釋出流水線中的環境部署,採用集測流水線中的介質,依舊維持介質一致。如果發現問題需要進行修復,必須要從集測流水線重新開始。對於介質可以使用nexus等介質倉庫進行統一管理。
直觀的協作看板
一個流水線有多個角色協作參與,從實際參與者視角出發也好、管理者視角出發也罷,都需要一個直觀的看板,來整體檢視每個應用當前的交付進度,當前處於哪個環節(系統整合測試、使用者驗收測試環境、預發、生產),以及成功和失敗情況。我們提供了兩種看板:釋出看板、環境看板。釋出看板基於產品、微服務的角度,檢視每個產品版本在不同環境上的部署情況。體現產品版本、產品修訂版本、產品釋出版本、產品的微服務及其版本。
環境看板則是從環境的維度,檢視每個環境下有哪些應用的哪些版本部署了。如下圖所示:
不要一味的自動化,自動和人工要結合
回過頭來看,文章開篇的例子並非不可達成,但是要求很高,需要成熟的持續整合體系、完整覆蓋的的自動化測試交付,全面的自動化部署能力的支撐,想達到這一步,自然不是一時之功就可以的。在建設的過程中,是少不了人工介入流水線中具體環節的,尤其是測試環節。所以在流水線的設計時,要充分考慮人工執行和自動執行的自定義,如果自動執行失敗的話,也要提供人工介入的入口,允許人工選擇重新執行、終止流程等動作。
以這些為基礎準則,我們底層基於了普元的BPS流程引擎,支撐流程的自定義和擴充套件。並且,針對於每個環節,都可以配置前置後置事件、人工執行還是自動執行,責任人等。整個流水線從構建開始,以程式碼的buildNumber貫穿全流程。便於問題、進度的追溯。效果圖如下:
四、總結
最後再回頭看看開篇的例子,在建設企業的持續交付流水線時,能做到全自動化固然很好,但並非是要立刻實現全自動化的效果,這也不現實。初期首先是結合企業的標準流程和規範,將企業的持續交付流水線打通。可以自動化的環節儘量做到自動化,尚且做不到自動化的就人工介入。
畢竟持續交付的價值絕不僅僅是快,對於大多數企業而言,在提升軟體交付效率之外,統一企業的軟體交付流程和規範、保證軟體交付質量、降低軟體釋出風險,這才是最重要的。
關於作者
王海龍
現任普元資訊高階研發工程師,畢業於華東師範大學,曾參與和負責銀聯Paas雲平臺專案、興業銀行CAP4J專案、交通銀行信用卡中心統一監控平臺專案、神華災備雲平臺、萬達DevOps平臺等專案。
關於EAWorld
微服務,DevOps,元資料,企業架構原創技術分享,EAii(Enterprise Architecture Innovation Institute)企業架構創新研究院旗下官方微信公眾號。
掃描下方二維碼,關注成功後,回覆“普元方法+”,將會獲得熱門課堂免費學習機會!
微訊號:EAWorld,長按二維碼關注。