得物SRE視角下的藍綠發布
一、前言
發布變更是影響穩定性的一個重大因素,為了發布異常時能快速回滾,增加發布期間的穩定性,也為了解決多服務部署時互相依賴而導致的發布時間增長等問題,得物在今年引入一種新的發布模式--藍綠發布。這種發布模式帶來了穩定性和效率的提升,這里我們以SRE的視角來解讀下得物的藍綠發布。
二、常見的發布形式有哪些?分別有什么優勢?
全量發布
全量發布是早期企業進行系統升級的一種方式,因為早期的服務大多為大型機,單實例程序為主。并沒有形成當下流行的微服務架構,因此當發布時往往需要停機發布。生產環境禁止使用這種方式進行部署!
滾動發布
滾動發布顧名思義,假如生產中16臺機器,我們可以分成4批。每批4臺機器,每批機器執行更新,從版本V1更新為V2,更新后重新將其投入使用,連續不斷的更新其他機器,直到集群中所有的實例都更新為版本B后,結束發布。
這種方式的好處就是更新過程體驗影響少,費用開銷也少,發布期間無需額外新增機器。但是缺點也同樣明顯,一旦開始發布后,回滾時長很久,在多個有關聯的服務部署時,需要上游服務完全發布后,才能發布下游服務,整體發布時間也很長。
滾動發布流程演示:
圖片
圖片
藍綠發布
通常意義上的藍綠發布一般是將服務分為兩組,藍組和綠組,正常運轉的情況下每組承載50%的流量。當準備發布服務時, 將藍組流量設置為0%,將綠組空閑出來,將服務部署到綠組的機器,然后利用SLB將流量切換到綠組的機器,讓綠組來運行業務,沒問題的話流量全部導向綠組,把藍組也進行服務更新。
傳統意義上的藍綠發布優點在于發布策略簡單,對于用戶幾乎無感知,可以實現平滑過度,在發布期間發現問題后也可以快速的回滾。而缺點則是通常需要準備正常業務使資源倆倍以上的服務器,需要投入較大的資源成本。
藍綠發布流程演示:
切除綠集群流量:
圖片
當A組升級完畢,負載均衡重新接入A組,再把B組從負載列表中摘除,進行新版本的部署,A組重新提供服務。
圖片
最后,B組也升級完成,負載均衡重新接入B組,此時,AB組版本都已經升級完成,并且都對外提供服務。
灰度發布
灰度發布,也被叫作金絲雀發布。與藍綠部署、紅黑部署不同的是,灰度發布屬于增量發布方法。也就是說,服務升級的過程中,新舊版本會同時為用戶提供服務。
灰度發布的具體流程是這樣的:在集群的一小部分機器上部署新版本,給一部分用戶使用,以測試新版本的功能和性能;確認沒有問題之后,再對整個集群進行升級。簡單地說,灰度發布就是把部署好的服務分批次、逐步暴露給越來越多的用戶,直到最終完全上線。
圖片
之所以叫作灰度發布,是因為它介于黑與白之間,并不是版本之間的直接切換,而是一個平滑過渡的過程。
AB Test就是一種灰度發布方式,讓一部分用戶繼續用A,一部分用戶開始用B,如果用戶對B沒有什么反對意見,那么逐步擴大范圍,把所有用戶都遷移到B上面來。灰度發布可以保證整體系統的穩定,在初始灰度的時候就可以發現并調整問題,以保證其影響度,而我們平常所說的金絲雀部署也就是灰度發布的一種方式。
之所以又被叫作金絲雀發布,是因為金絲雀對瓦斯極其敏感,17 世紀時英國礦井工人會攜帶金絲雀下井,以便及時發現危險。這就與灰色發布過程中,先發布給一部分用戶來測試相似,因而得名。
圖片
對于灰度發布來說,它的優點在于如果前期出問題影響范圍很小,相對用戶體驗也少;可以做到及時發現、及時調整問題,影響范圍可控。但是采取這種模式對自動化以及運維監控能力的要求非常高。
三、得物的藍綠發布是如何實現的?
前面講了“what”,我們現在來說下“how”。
在平時,我們也會保留藍綠兩個集群,在發布時,引入灰度的流量平滑過度,幫助我們完成整個發布過程,下面以SRE的視角大致講一下藍綠發布的架構與流程。
藍綠發布的流程
在這種架構下,整體的發布流程如下:
- 日常流量
在未發布時,我們接入藍綠發布的服務是平均分成藍綠倆個集群的。平時通過網關均勻切分流量,平均每個集群50%的流量。
圖片
- 開始發布
當進行藍綠發布時,我們將需要發布的應用創建在一個通道中(這里先說下只有一個通道部署的情況)。
圖片
- 藍集群(右側)摘流
此時所有流量將只訪問綠集群,如下圖所示,當藍集群摘流完成后, 此時集群沒有任何流量,即可進行部署。
圖片
- 藍集群(右側)引流
當藍集群發布完成后,我們需要對藍集群發布后的服務進行確認。在確認部署成功后,則梯度的將流量引入更新后代碼的藍集群(右側),最開始我們會切1%的流量,切流量后,我們可以在線上觀察藍服務的流量、錯誤率等。以此觀測發布的版本是否有異常。之后,我們逐漸將流量切回50%。注意,需要確保相關缺陷都在該環節暴露出來,因為這個環節另一半老版本的、穩定的代碼還在Standby,可以隨時操作流量比例,進行流量遷移。
圖片
發布過程中,藍、綠節點間流量不會互竄(對比上圖,藍綠集群間斜向箭頭沒有了)。
此階段需要注意MQ流量,因為MQ當前無法按比例進行切分,因此一旦開始切流,則MQ流量會恢復為50%/50%。
- 綠集群(左側)摘流
通過擴大流量比例,流量全部切到藍集群,這個階段流量已全部切到新代碼,可以讓測試同學介入進行新功能驗證以及回歸測試。
在這個階段只要綠集群還沒發布,發現問題,仍然可以全部切回老代碼!
當測試驗證完成后,即可進行綠集群發布。發布后則不可以回切了!就算要代碼回滾,也得等本次發布結束后,再單獨對服務進行回滾。
圖片
- 綠集群(左側)引流
在發布后則開始進入綠集群引流了,此時可以快速引流,因為已經沒有可以回滾的、穩定版本的代碼了。同樣,還在發布階段,及時流量均衡,也不會出現互相交叉的流量。
圖片
- 發布完成
發布完成后,則去除通道,藍綠集群可以繼續進行交互。
圖片
如上圖所示,使用以上發布流程具備以下好處:
- 整個發布過程是以藍、綠集群維度并行調度、實施的,通過發布平臺統一操作,摘流,無需各業務域各自處理。
- 通過請求藍綠粘性,讓下游應用的新老版本代碼可以同時存在,無需阻塞等待下游應用全部升級到新代碼,解除了批次依賴。
- 發布過程中有靈活的流量控制能力,可以按1%、50%等階梯流量驗證應用。
- 上述發布流程,可以同時并存若干個,摘流、引流動作互不影響(多發布通道)。
藍綠發布的架構
應用架構 [1]
圖片
1.1 流量規則SDK
在所有需要接入藍綠發布的程序中,首先需要升級流量規則SDK,流量規則SDK是應用藍綠發布能力的代碼底座,向中間件組件如RPC、MQ、JOB提供了主動查詢流量規則和被動接受流量規則變更事件的能力,各中間件組件響應流量規則進行合適的動作,實現各類型流量的動態摘流、動態引流。
1.2 核心能力
- 依賴配置中心做持久化存儲與事件推送。
- 所有配置讀取都是內存操作,只會在啟動時讀取一次配置中心的配置,后續配置變更都依賴于配置中心的事件推送。
- 提供了如下的能力:
當前應用所在的發布通道,是否在藍綠發布中。
指定應用所在的發布通道,是否在藍綠發布中。
藍色流量百分比,范圍[0, 100]。
- 提供了如下的事件推送:
發布開始事件onStart。
發布結束事件onFinish。
切流事件onFlowChange,切流事件又細分了以下幾個事件。
切流事件,藍色流量標占比為100,綠色流量標占比為0,onEnterAllBlue。
切流事件,藍色流量標占比從100改為非100,綠色流量標占比從0改為非0,onExitAllBlue。
切流事件,藍色標流量占比為0,綠色流量標占比為100,onEnterAllGreen。
切流事件,藍色標流量占比從0改為非0,綠色流量標占比從100改為非100,onExitAllGreen。
流量控制
得物目前的流量分為內部流量及外部流量,大部分流量情況如下:
- 外部流量
通過各類Gateway請求
通過k8s Ingress請求(暫不支持藍綠發布)
- 內部流量
- 通過Gateway互聯
- 通過Dubbo/Feign RPC協議互聯
- 通過MQ異步請求
- 通過kafka異步請求(暫不支持)
- JOB類任務發起的流量
- 通過k8s SVC請求(暫不支持藍綠發布)
其中Gateway也是通過Dubbo或者Feign請求下游服務,因此也可統一為RPC類型,所以得物目前的流量主要包含RPC、MQ、JOB三種。
2.1 RPC
我們RPC流量核心主要依賴注冊中心,通過Dubbo的負載均衡策略進行調整。
圖片
- 如何實現RPC流量比例控制
RPC場景下應用的流量比例控制,取決于它的上游應用按照流量規則比例向其發起調用。核心是上游應用感知到下游應用實例權重。
當前應用通過流量規則SDK監聽到所在通道的流量規則變更時,修改注冊中心上的實例權重。
上游應用通過注冊中心透明的感知下游應用的實例權重,通過加權負載均衡策略實現流量比例控制。
Dubbo原生的各類負載均衡策略都支持加權,也就是即便上游沒有升級藍綠依賴,下游應用依然可以通過藍綠實例權重控制自己藍綠集群被調用的比例。
Feign原生是不支持的,Fusion框架重寫了負載均衡策略。
- 如何控制流量比例
藍色流量比例Rate,藍色集群實例權重WB,綠色集群實例權重WG。
假設Rate從1調整到99,一共有4個節點。
調整前WB=1,WG=99,調整后WB=99,WG=1,可能出現以下情況:
圖片
- 流量規則變更時,只讓藍或綠某一個集群修改自己的權重。
權重值是相對的,只需要保證藍、綠集群節點權重相對值服從流量比例即可,無需同時修改藍綠集群所有節點的權重。實例權重初始值設為100,修改權重時,盡可能保證一半集群實例權重保持100不變,只修改另一側被調整的集群實例的權重。
規則如下:
藍色流量比例Rate,公式:W/(100+W) = Rate/100。
Rate = 50,藍色集群實例權重=100,綠色集群實例權重=100。
Rate < 50,藍色集群實例權重=100 * Rate / (100-Rate),綠色集群實例權重=100。
Rate > 50,藍色集群實例權重=100,綠色集群實例權重=100 * Rate1 / (100-Rate1),其中Rate1=100 - Rate。
- 只有一個顏色的集群時,忽略權重。
- 如何實現完全摘流
Dubbo框架內置的所有負載均衡策略都會識別下游實例的權重進行加權篩選節點,無需上游升級依賴,下游應用實例權重置0后即可實現摘流。
Feign框架默認不識別實例權重,不進行加權負載均衡,為了避免藍綠發布項目落地時推動發布鏈路上下游應用升級的困難,應用摘流時,會將自身注冊的所有Feign服務反注冊,以保證Feign流量能被徹底摘流。
- 如何實現請求鏈路藍綠粘性(一藍到底或一綠到底)
藍綠子集群的代碼是不一樣的,按我們制定的發布流程,藍集群是新代碼,綠集群是老代碼,如果不能固定請求鏈路的顏色,實現請求過程一藍到底或者一綠到底,那么可能會出現上游新代碼調用到下游老代碼,出現代碼不兼容的異常。
將RPC請求第一次進入每個通道時的藍綠決策結果以KV形式Append到分布式Trace的baggage中,全鏈路透傳、隔離、復用。
如果Trace中有藍綠決策結果,則按照藍綠決策結果篩選節點;
否則按照流量比例篩選節點,并將決策結果(節點集群顏色)Append到Trace。
baggage-key: x-deploy-channel-type。
baggage-value:key=通道標識,value=藍集群或綠集群標識,多個通道以&分割。
圖片
2.2 MQ(RocketMQ)
核心是通過多消費組實現MQ流量隔離和控制。業務上創建的一個業務消費組,會在MQ SDK層面透明的創建2個衍生的顏色消費組。
發送消息時,會在消息頭上攜帶當前節點藍綠標。3個消費組收到消息時,根據消息顏色和消費組顏色做顏色請和判斷,互斥的消費同一個TOPIC上的所有消息。
- 非摘流狀態
圖片
- 摘流狀態
應用感知到通道內藍集群摘流時,藍集群節點關閉消費組、綠集群節點啟動三種顏色消費組。此時,MQ流量完全由綠集群接管。
圖片
通道內綠集群摘流時同理。
- 過程詳解
原本一個消費組,拆分成三個消費組。
原始消費組origin-consumer用于消費無(藍綠)標識的流量。
藍色消費組blue-consumer用于消費「藍色」標識流量。
綠色消費組green-consumer用于消費「綠色」標識流量。
圖片
2.3 JOB(elasticjob)
圖片
elasticjob在運行時會在業務應用集群內利用ZK協調產生一個Master節點,由Master節點來按負載均衡策略將任務分配到各個執行器節點上。這個任務分配關系一經分配就會固定并在后續復用,除非是有應用進程上下線、JOB分片數有變更。
改造elasticjob客戶端適配流量規則SDK,正在藍綠發布的應用,在感知到有集群已經摘流時,會修改ZK上的狀態標識,將上述記錄的分配關系失效。
失效后,后續JOB執行時,會根據流量規則重新進行任務分配,避讓已經摘流的節點,以保證已經摘流的節點上不會有JOB執行。
- 過程詳解
圖片
藍綠接入注意事項
因當前技術限制, 服務接入藍綠需要注意以下事項:
- 流量無法摘除的服務暫時無法接入
未通過網關進入服務流量:例如,通過域名SLB進入服務、通過Ingress進入服務的流量無法摘除。
消費Kafka的流量無法摘除:由于應用使用的原生kafka客戶端并全面鋪開、無法對切入提供支持。
未使用統一框架/注冊中心:未使用統一框架和注冊中心的Java應用、以及非Java類應用當前不支持藍綠發布。
- 使用特別提醒
- 消費消息需冪等:使用消息中間件必須做冪等,這是基本要求,在消費組啟停管控中可能產生重復消息。
- 消費組線程數量:由于會有三個消費組、消費線程也會增加兩倍,有業務影響時需調低線程數。
- 需要好流量評估:藍綠發布需一半節點承接線上流量、在應用升級藍綠集群時做好確認。
- 升級到特定版本:使用藍綠發布需要應用升級到框架指定版本,詳見接入指南。
- Feign/HTTP流量:針對使用框架Feign的HTTP流量,需上下游應用全部升級后方可使用。
- 使用Dubbo流量:使用框架Dubbo的服務只需要自身服務升級版本即可、無需上下游升級。
四、得物SRE團隊對藍綠發布的相關支持
容器集群針對藍綠的改造
我們容器的workload使用的OpenKruise來進行管理。在進行藍綠發布之前,我們使用的單個clonesets進行控制。
以下圖所示,為我們一個測試非藍綠集群,這里就是使用單個cloneset進行控制的單實例。
圖片
在進行藍綠改造后,我們將workload分為藍綠兩個clonesets,通過這樣,我們可以實現藍綠發布時候的單邊實例發布。同時在我們管理平臺界面,任是單個集群界面, 以此來實現單集群下 藍綠集群的拆分。
圖片
藍綠發布擴容資源優化
前面就說過,藍綠發布的一大缺點是通常需要準備平常流量2倍的資源,以應對藍綠發布期間的流量。我們在加入藍綠發布集群時,也盡量會提醒需要增加資源以應對藍綠發布。但如果毫無規劃的進行擴容,則會帶來以下幾個問題,比如長期保留擴容資源,則會帶來成本的答復增長,而臨時的擴容,則代表著對人力的消耗增加,而且臨時的擴容也增長了對資源池管理的難度。可能在用戶擴容時,出現資源池不足的情況。
為了應對這個問題,我們針對藍綠發布進行了優化。首先是在發布流程中加入了擴縮容的環節。讓平臺自動幫助進行服務的擴縮容。其次,在容器層面,我們利用云服務商的彈性實例功能,來彌補常規資源池不足的情況,通過基于Virtual Kubelet技術接入到k8s中,支持秒級啟動,按量計費,可快速完成擴縮容,滿足業務的實時響應需求。
注意: 在應用加入發布通道時,因藍綠發布會導致流量減半,請務必對核心服務進行擴容(SRE建議擴容30%以上)。
圖片
圖片
圖片
發布監控
加入灰度的藍綠發布,因為涉及流量切換過程,因此對監控要求非常高,需要及時觀測整個通道中的服務狀態,而歷史中單應用的監控頁面無法滿足發布owner有效觀測。因此,針對這個問題,我們專門設計了通道級的藍綠發布大盤,有效的觀測流量分布情況,服務的請求情況等。通過該大盤,發布owner能有效掌握本次發布情況,決定是否繼續進行切流。
圖片
五、藍綠發布期間可能出現的問題及應急響應策略
資源不足導致的服務異常
- 發布前擴容
根據藍綠發布原理可知,我們在發布時,只有50%的實例來支撐原先100%的流量, 因此務必在藍綠發布前勾選發布前臨時擴容。擴容量需要評估以下幾個數據:
- 服務CPU 水位情況
根據歷史經驗,如日常水位99值在20%以內的服務,無需進行臨時擴容,而99值在20%-30以內的服務,建議擴容20%左右。而99值在30-40%之間的服務,應當擴容30%以上。同時也要考慮發布當天的流量情況。
比如我們在七夕大促期間的發布,因大促流量過高,我們許多服務在藍綠發布時擴容達到了50%以上的情況,通過此方式,保證在切流期間,服務也能正常。
因為我們的服務大多以JAVA為主,內存大多用固定方式分配給了JVM堆,因此內存不是一個核心的參考指標。
- 服務線程使用情況
除了服務CPU外,服務線程也是一個核心參考指標,特別是Dubbo線程池以及DB/Redis的線程池。比如原先Dubbo線程池,max為 200,10個實例的服務,當日常QPS大于1000的時候,在藍綠發布時就需要擴容了,否則實例數少了一半,意味著可用線程也少了一半,這個時候就會出現線程拒絕異常了。
- 發布期間的資源不足
有些時候,我們評估不足會導致在開始發布后因為資源不足導致的錯誤率上升,此時需要我們緊急處理,但為了發布期間的穩定性,一旦我們開啟了藍綠通道,就不允許進行集群的擴容了。此時需要SRE接入在后臺進行處理,處理邏輯如下:
- 確認待擴容集群未處于發布狀態。
- 手動修改藍/綠單邊集群cloneset的replicas數據。
- 待發布完畢后,手動還原該cloneset的replicas數據。
因該操作非標準操作,且存在風險,請盡量不要使用以上方式進行。
發布中出現流量不均衡的情況
之前的一次測試中,我們在引流后出現了服務流量不均衡的問題,當時因為Fusion框架升級了Dubbo異步的改造中存在邏輯缺陷,導致流量無法均衡分布。之后,通過回退Fusion框架版本后問題恢復。
圖片
這是個比較危險的情況,某些節點會在發布時承擔日常400%的流量,很容易造成服務雪崩。因此,在藍綠發布中,負責人和SRE要加強服務的監控和關注力度,及時發現流量不均衡的情況并介入。
發布中出現流量互竄的情況
流量互竄的問題會有許多種情況:有因為切流前的JOB持續運行,導致雙邊集群依舊有流量;有的因為鏈路中間節點沒有升級藍綠能力,導致流量錯位;有的因為MQ請求下游導致的流量錯位。這里不針對問題進行一一分析,問題的解決僅能依靠框架的升級,這里僅說下問題的影響和排查方法。
在藍綠發布時,原先我們的預計是老代碼連老代碼,新代碼連新代碼,但出現異常請求時,可能出現新代碼連老代碼,或者老代碼連下游新代碼的情況,這個時候就會出現因為依賴不匹配,導致的服務異常。
圖片
要發現此類問題,我們首先要知道,在這種情況下,大多會出現單邊集群錯誤率上升。通過我們的監控頁面,我們能很好的發現單邊錯誤率上升的情況。此時,我們就能根據這些錯誤的情況,在天眼的調用鏈分析中,查看錯誤的具體情況。此時需要我們判斷鏈路里是否有出現流量異常的情況,查看節點的Host name,可以判斷是藍或者綠集群節點。
圖片
圖片
六、歷史總結及展望未來
藍綠發布的效果
自從交易域進行藍綠發布以來,平均大版本的發布時效較之前得到了較大的提升,同時近期大版本已沒有出現故障事件,在升級藍綠發布后,我們可以提前在切流階段發現問題,并快速回切進行修復,避免了故障帶入生產。因此,現在藍綠發布相比過去滾動部署,在效率和穩定性上均大有提升。
未來展望
目前我們核心服務都已切換至藍綠集群,這種為我們的多活打下了優勢,已經天然具備了多活的條件。因此,未來我們可以通過這種架構來部署我們的多活,這樣,當任何單機房出現異常后,能夠快速切換到另外一個機房,我們的抗風險能力也會有巨大的提升。參考引用:
[1] 特別鳴謝,本節藍綠發布架構及原理部分引用了得物中間件平臺 “羊羽”同學的文章。