搞定微服務線上生命週期管理,同時發佈上千個服務節點不是事兒

當微服務完成開發、測試後,就可以通過發佈服務將其發佈到線上。

如果只看一個服務節點的部署,貌似是一項非常簡單的工作,但如果同時發佈成百上千個服務節點,尤其是需要在不影響線上業務的前提下完成發佈工作,就會變得比較複雜。

批量發佈是風險度較高的事情,很大一部分線上事故都是由發佈引起的。爲了控制風險,需要對發佈做足監控,將所有發佈步驟在監控大盤上進行實時展示,如果出現發佈問題,則應及時告警,並提供完善的回滾功能。

本文選自《微服務治理:體系、架構及實踐》一書。

微服務的部署

▊ 包部署模式

以應用包或服務包的方式進行的部署工作,大部分是在非容器環境的物理機或虛擬機上進行的。如下圖,在多機房情況下,每個機房都會有發佈調度服務器,同時軟件版本倉庫在每個機房也都會有相應的鏡像服務。

微服務的包部署模式

1.服務部署包分發

當發佈指令從調度中心下發後,每個機房的發佈調度服務器會通知本機房內應用服務器集羣中的每個服務節點到本機房的軟件版本倉庫下載對應的服務發佈包。

這裏要注意的是,如果服務節點過多,同時下載微服務的部署包可能會產生瞬時的“網絡風暴”,導致網絡被堵塞。因此,在下載調度上需要做一些優化,讓這些服務節點分批下載,或者控制能同時下載的服務節點的數量。

2.服務狀態檢測

每個服務節點上新的服務部署包下載完成後,就要停止當前運行的服務進程,部署新版本服務。

在停止服務時,由於服務上有正在運行的請求,需要等待這些請求處理完畢,同時不讓新的請求進來,這就是所謂的“優雅停機”。可以通過服務註冊中心將該服務節點直接刪除,或者通過調整該服務節點的路由權重爲0來控制不再有新的請求進入該服務節點。另一方面,可以通過一些系統鉤子(如JVM中的shutdownhook)來實現等待所有請求處理完畢再關閉應用的功能,同時做一些資源清理工作。

新版本服務啓動後,會自動到服務註冊中心進行登記註冊,並重新恢復路由權重。這樣,新的請求會重新被路由到該服務節點。

3. 分批發布

微服務的發佈如果要做到線上業務無感,就必須控制同時進行上、下線操作的服務節點的數量。因爲如果一個服務集羣中過多的節點下線,則剩餘的節點可能無法負擔當時線上所有的請求流量,所以針對服務發佈,必須能控制同時進行上、下線操作的服務節點的數量或比例。

4. 服務發佈執行

在上圖中,發佈調度服務器承擔了“大腦”的作用,由它提供分批發布策略並向各個服務節點發出發布指令。微服務本身屬於被操作的“物料”,在服務節點上還需要有發佈操作的“執行人”。承擔執行人角色的可以是集成在服務節點中的Agent,這個Agent是一個獨立的進程,在服務節點啓動後同步啓動運行,並不斷監聽發佈調度服務的指令,收到具體發佈指令後,由其執行具體的發佈策略。

除了獨立部署的Agent,還可以採用以Ansible爲代表的無代理的遠程配置管理工具,以直接通過SSH協議對服務節點進行發佈操作管理。使用Ansible的最大好處是,不需要在服務節點上部署Agent程序,減少了Agent帶來的穩定性風險,降低了整體維護成本。

不論是Agent,還是遠程配置管理工具,在服務發佈上基本都遵循相似的步驟。

1)檢查環境:檢測系統環境是否正常,相關技術棧是否完備;

2)下載部署包:參考指定軟件版本下載部署物料;

3)關閉服務監控:關閉服務監控,防止部署過程中產生大量報錯信息,但部署監控必須開啓;

4)服務下線:服務註冊中心將該服務節點直接刪除,或者調整該服務節點的路由權重爲0來控制不再有新的請求進入該服務節點;

5)停止服務:發出進程關閉信息,通過“優雅停機”的方式在所有存量請求處理完畢之後,關閉服務進程;

6)部署服務:部署新服務的部署包;

7)啓動服務:啓動服務進程;

8)健康檢測:檢測服務是否正常啓動,進程是否正常,並在服務註冊中心中正常註冊;

9)開啓服務監控:服務啓動成功並正常註冊後,開啓服務監控。

▊ 容器化部署模式

在容器編排領域,K8S(Kubernetes)已經成了事實上的王者。本節中,就以K8S爲例,討論如何進行P2P直連模式微服務的部署。首先了解K8S的兩個關鍵概念:Pod和Service。

1.  Pod

和常規的理解不一樣,K8S管理的基本單元不是容器,而是Pod。Pod是K8S中的最小管理單元,K8S不直接管理容器,就算只有一個容器,也會給它分配一個Pod,Pod裏的容器數也可以爲0(其實不可能真正爲0,因爲還有K8S自己創建的基礎容器Pause,它負責網絡及存儲的管理)。

2. Service

可以通過給Pod打標籤(Label)來對Pod進行分類和組織。一個Pod的若干個實例組成一個Service,可以認爲Service就是對應一個Pod的副本集羣,並通過Service來進行這些副本實例的負載均衡控制。一個Service由一個IP地址和一個Label Selector組成,副本控制器(Replication Controller)通過Label Selector來控制每個Service包含多少個Pod實例。簡單地理解,可以把Service看成一個彈性組。

如果設定一個Pod的實例由基礎容器Pause和一個業務容器組成,並且這個業務容器只運行微服務的某一個服務節點,就可以讓K8S和微服務在“服務”這個概念上達成一致。

微服務和K8S在架構上的映射及融合

上圖中,微服務中的服務對應K8S中的Service,服務節點對應Pod中的業務容器。這樣,只要將每個微服務打包成容器鏡像,並在創建對應Pod資源的時候,將服務名稱以標籤的形式寫入資源清單文件中,就可以利用Label Selector過濾出相關的服務Pod,並通過K8S進行上線、下線、擴容、縮容操作。

▊ 混合部署模式

與服務化類似,大部分企業的容器化之路也不是一蹴而就的。企業內部的IT環境會長期處於新舊混搭的狀態,基礎資源層除了K8S提供的容器服務,可能還存在IaaS雲平臺(公有云或私有云),甚至還存在傳統的物理機。整個微服務集羣混部在這些不同的環境中,新增加的K8S容器服務平臺需要能與原有的資源平臺共存。

微服務集羣的混部

以上架構會導致一個網絡問題,Pod的IP地址只在K8S容器集羣裏可見,無法和容器集羣外的微服務交互,相當於K8S容器集羣內、外形成了兩個網絡域。

爲了解決這個問題,可以使用第三方開源的網絡組件 Calico,結合物理核心交換機做策略優化,基於BGP協議將容器集羣的內、外兩個網絡連接在一起,使得K8S集羣外的主機能訪問到Pod的IP地址。它的原理如下。

1)Calico將所有的Node主機變成了路由器,並將該Node主機上存在的所有網段信息都彙報給路由反射器(核心交換機),包括該主機上運行的Pod網絡;

通過BGP網絡解決K8S集羣內、外網絡訪問問題

2)配置核心交換機以路由反射器(Route Reflector)的角色與其他節點建立BGP鄰居關係;

3)K8S集羣外的主機只要能連接到核心交換機,就可以獲取抵達所有Pod地址的路由信息。

藍綠髮布

藍綠髮布是一種歷史悠久的服務端應用發佈模式,不僅適用於分佈式應用或服務,而且也適用於大量的單體應用,它能有效縮短髮布導致的業務中斷時間,並且能夠在發佈版本出現問題時快速回退。

藍綠髮布的核心思想是新舊兩套服務共存。新系統的發佈由於不涉及舊系統,自然不需要使用藍綠髮布,所以直接發佈就行了,只有存量服務的升級才需要使用藍綠髮布。所以,準確地說,藍綠髮布主要應用於服務的升級。

下面是藍綠髮布的示意圖,藍綠髮布包含如下幾個步驟。

藍綠髮布示意圖

1)部署開始前,線上只有舊版本(藍集羣)的服務在運行。

2)在線上部署服務的新版本(綠集羣),並在線上進行充分測試。

3)調整路由及負載均衡策略,將流量統一切換到新版本(綠集羣),但舊服務(藍集羣)不下線。此時兩套集羣並存,只是舊集羣沒有流量,一旦新版本服務出現異常,通過調整路由及負載均衡策略,快速切換回舊版本(藍集羣)。

4)新版本(綠集羣)線上穩定運行無異常後,將舊版本服務(藍集羣)下線,發佈結束。

採用藍綠髮布模式,由於新舊兩套服務集羣並存,所以一旦發佈過程出現異常,回滾速度會比較快,只要切流量即可。但這種發佈模式在發佈過程中,需要額外佔用一套線上資源。

灰度發佈

灰度發佈是專門針對分佈式、多節點的應用或服務的發佈方式,和藍綠髮布不同,它不需要額外的資源。它利用現有服務集羣,通過分批替換的方式將風險控制在可接受範圍內,以減少發佈後的質量風險。

灰度發佈目前也是互聯網企業的主流發佈模式。這些企業一般都構建了完善的灰度發佈平臺,利用該平臺,運維人員可以在服務集羣中設定發佈批次,並同步將用戶(流量)進行劃分,根據功能、兼容性、併發和性能選定發佈批次對應的用戶(流量)範圍,分批平滑發佈,逐漸擴大範圍,同時將選定的線上用戶路由到新版本上,實時收集用戶反饋來驗證發佈效果,以決定是繼續發佈還是回滾。下圖就是典型的灰度發佈過程,服務節點和用戶流量同步進行階梯切換。

典型的灰度發佈過程

在灰度發佈的用戶選擇上,除了考慮集羣的負載,還可以根據實際需要靈活切分,一般會優先使用用戶區域、用戶級別、用戶設備等屬性。所有選擇都通過灰度發佈平臺控制,灰度發佈平臺同時要和監控系統緊密結合,以對較長時段的發佈過程進行全程監控。

▊ 金絲雀測試

在灰度發佈中,第一批(或前N批)發佈的服務節點及被切流到該節點上的用戶流量具有特殊意義,它們往往扮演了“先行者”的角色,大部分異常都能在第一批發布中被發現。由於第一批(前N批)發佈的範圍非常小(一般不超過1%),影響範圍有限,因此又把第一批(前N批)發佈單獨稱爲“金絲雀測試”。

“金絲雀測試”的覆蓋範圍很小,所針對的用戶羣體可以限制在很小的可控範圍之內。就像筆者目前所負責的在線金融業務,每當一個較大的功能上線時,一般都會先讓部門內部員工承擔“金絲雀”的角色,再將範圍擴大到公司員工,然後基於特定規則(地區、機型、年齡等)挑選一批用戶。

“金絲雀測試”無誤後,就可以進行全量滾動發佈了。

小貼士:

礦井工人面臨的一大風險就是井下的瓦斯爆炸,後來人們發現,金絲雀對瓦斯氣體非常敏感,只要空氣中存在極其微量的瓦斯氣體,金絲雀就會停止歌唱或死亡。因此,在採礦設備不發達的古代,礦井工人每次下井都會帶上一隻金絲雀,並根據金絲雀的表現來判定是否有瓦斯,以便在危險來臨前及時撤離。

▊ 基於版本號的灰度發佈

對服務的升級,會遇到兩種情況。第一種情況是接口不變,只是代碼本身進行完善。這種情況處理起來比較簡單,因爲提供給使用者的接口、方法都沒有變,只是內部的服務實現有變化。在這種情況下,採用上述灰度發佈的方式驗證後全部發布即可。第二種情況是需要修改原有的接口,如果只是在接口中增加新方法,可以參考第一種情況處理。複雜的是接口方法的參數列表被修改了,這時就需要有相應的手段來區分新舊接口方法,比較通用的辦法是通過增加服務接口的版本號來解決,使用老方法的系統繼續調用原來版本的服務,需要使用新方法的系統則使用新版本的服務。這意味着,在服務框架中,必須通過“服務接口+版本號”的方式來唯一區分服務(在服務多租戶的模式下,還需要加入分組group)。基於版本號的灰度發佈升級如下。

基於版本號的灰度發佈升級

上圖中,C1代表服務調用方(消費者,Consumer),P1代表服務提供方(提供者,Provider),V1、V2代表版本號。

總體流程是,找一個訪問低谷,先將一部分服務提供方升級爲新版本,接着將所有服務調用方升級成新版本,最後將剩餘的服務提供方升級成新版本。這個過程涉及流量的各種調整,具體可以參考上圖各個步驟。


更多科技資訊請見微信公衆號:博文視點Broadview(微信號:bvbooks)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章