灰度發佈系統設計

前言

互聯網公司在起步階段一般用戶量少,系統處在快速試錯與迭代階段,對於系統部署對用戶的影響及系統上線的流程不會有太多的顧慮和投入。相反,當業務量上升,系統承載的流量也因此升高,這時還用起步階段的部署流程和方式,不僅對用戶使用可能帶來較大的影響,也對自身產品的品牌形象帶來傷害。

這個話題其實已是老生常談,現在各種微服務治理,k8s等容器編排系統甚至service mesh的普及,將服務上線對現網的影響理論上已經減少到很小,藍綠髮布與canary發佈的設計思路也有許多說明文章。但就像Lessons of history這本書闡述的,一種文化在100年沒有發展就會自然消亡,如果需要重建該文化,那就必須要從零開始(狩獵、農耕、工業等)。所以寫這片文章,也是爲了將之前實踐過一些經驗記錄下來,以便在未來的工作中能事半功倍,這也是技術文化的一種延續。

本文記錄一些發佈系統的思路和設計,供參考。

常見問題

首先,灰度系統(統稱)能幫助解決系統工程裏的哪些問題。

  1. 服務中斷

傳統的發佈方式,新的系統打包上線後,關閉老系統,重啓新服務。這樣粗暴的方式通常都會導致服務中斷,如果沒有充分的測試和驗收,上線後再出現故障就會導致更長的中斷時間,嚴重影響用戶體驗。

這裏架構上不論是單點dedicated server還是分佈式集羣,其實還是有不少工程師是用這種方式來發布的。

  1. 風險不可控

系統總是存在bug,沒有100%完美的服務。但是不能因此就容忍故障導致的大面積宕機,設計好的灰度系統可以控制上線版本,將故障控制在一定的子集內,即使出現故障也將影響面控制在最小。

  1. 流量不可控

設想一個問題,即將上線的v2版本新功能我想讓北美區的用戶先體驗,採集使用數據並對用戶使用情況做分析,再投放到核心的國內地區。這樣的場景需要如何實現呢?如果能有一個灰度系統進行流量的分發,對於產品功能的A/B testing,甚至多地多集羣的系統出現故障也能實現跨地域的調度了不是?

幾種發佈方式

結合上述的幾個問題,除了傳統的粗暴發布方式,我們還有哪些發佈方式,它們又分別解決什麼問題?

  1. Rolling updates

這裏以k8s爲例,一個deployment設置了replicas後,更新新版本的操作就是一次rolling updates的過程,根據官網的說明,rolling updates的操作流程如下:

k8s-rolling-updates-1.png

k8s-rolling-updates-2.png

這樣的發佈方式存在一些缺陷:

  • 如何控制老pod的優雅下線?(需要在代碼邏輯里加一些連接的檢測,如果還有存活的前向連接,先維持一段時間等待連接釋放後關閉pod)
  • 無法做到精細化的流量控制
  1. 藍綠髮布

見下圖blue-green deployment .png

我們需要準備藍、綠兩套環境,前後兩個版本的服務在兩套環境裏不斷迭代變換角色。當我們充分驗證了藍色區域的服務後,再將服務上有的load balancer或者domain name切換。

這樣可以較好的控制發佈的風險,服務經過充分測試,甚至可以做一的shadow packets複製部分線上的流量模擬線上環境測試。但是很明顯,藍綠髮布是一個比較耗資源的方式,需要有一個鏡像資源,通過物理上的隔離來保證測試,上線穩定性和流量的切換。不過有時這樣的投入,相比上線出現故障也是值得的。

  1. canary發佈

這樣的發佈思路,簡單來說就是將新版本的服務按最小化可控比例進行上線,同時配合流量調度保證風險的控制和流量控制。見下圖。

canary delopment-1.png

canary delopment-2.png

首先,我們屏蔽一臺機器的流量,進行新版發佈(當然需要先測試過);其次切10%的流量(這裏可以精細控制一些IP range,比如公司內網等),驗證服務接收線上流量是否正常;最後可以切換100%的流量,用同樣的方式更新其他的節點。在實際過程中,我們更新的節點數量可以簡單的倍數增加。

A/B testing

單獨討論下A/B testing,它與藍綠髮布並不完全等同,藍綠髮布是技術側的術語,更多是解決服務更新的問題,並不是在業務層面做多功能的驗證。例如兩個不同UI風格,同時投放到一類用戶羣體中進行驗證,最後分析哪個UI風格更被用戶接受。

A/B testing也需要通過灰度發佈系統同時具備風險控制和流量控制的能力才能實現。

實踐

先上架構圖

gray system.png

我們採用的是openresty的開源框架來搭建內部的灰度系統,架構圖中上半區域爲我們的控制平面,下半區域爲數據平面。

技術點:

  1. 類service mesh的sidecar模式,實現灰度集羣發現與調度策略批量變更
  2. consul集羣做註冊中心,解耦上下游的控制流 (consul的部署與說明)
  3. 對雲平臺更加友好,新增的服務或者灰度節點都會調用雲平臺的Load balancer接口進行增刪
  4. 流量細化控制,我們可以根據訪問設備、IP範圍、HTTP header自定義特徵等做到流量分發

結束語

我們實現的方式算是比較通用的方案,之前在老東家也是用的類似的解決方案處理了無數次的發版,還因爲這個設計在一次跨域故障時很快的把流量切換走,保障用戶服務。

當然除了可以使用openresty,大家也可以看看kong(openresty的升級版)和istio(service mesh)。它們都是很不錯的開源項目,對大型分佈式系統的管理都有充分的理解和設計。

kong

service mesh

[外鏈圖片轉存中…(img-FahB80kh-1586262994229)]

[外鏈圖片轉存中…(img-oXFdZ36z-1586262994230)]

最後,用了新的畫圖工具(cloudcraft),感覺比較適用更大型的偏pipeline的架構圖。

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