為了讓大家更好的理解,我通過一個簡單的例子和大家說一下什么是灰度更新。

假設你有⼀個關於酒店預定的項⽬,需要對外提供⼀個 Web 網站,供用戶預定房間。為了保證業務的⾼可⽤,該項⽬研發的服務端是⽀持分布式的。因此,你在⽣產環境,組了⼀個酒店預定 Web 集群,⼀共起了 3 個服務端,通過 Nginx 反向代理的方式對外提供服務。
左圖是傳統意義上的灰度更新,即先將部分流量導到新版本上進行測試,如果可以就全面推廣,如果不行就退回上一個版本。具體舉例來說的話,有三台機器分別部署了服務端,IP 地址分別為 0.2、0.3、0.4。日常更新的話,選擇先在 0.4 服務端更新並看一下是否有問題出現,在確定沒有問題后才進行 0.3 和 0.2 的更新。鄭州哪家醫院看心理咨詢好http://www.hyde8871.com/
右圖則是使用容器技術,它會比物理機部署的方式更加靈活。它用到的概念是 instance,也就是實例,同一台機器上可以起多個實例。訪問流量會如圖從左往右的方向,先經過網關,通過在網關上添加一些策略,讓 95% 的流量走上面的原服務,5% 的流量走下面的灰度服務。通過觀察灰度服務是否有異常,如果沒有異常,則可以把原服務的容器鏡像版本更新到最新,並刪掉下面的灰度服務。這和左圖是不一樣的,它不是滾動式一台接一台的更新,而是借助一個彈性資源平台直接把原服務全部更新掉。
灰度更新現狀

上圖是灰度更新在 Luffy2 上面的現狀,主要問題出現在 API 處理這一塊,因為之前的狀態是靠數據庫來維護的,容易出現狀態不統一的問題。
左圖是一個簡略的處理流程。當一個 API 請求服務過來要求進行服務灰度更新時,第一步會先生成一個帶灰度名稱的 App。
第二步這里給大家細說,首先要將生成的 App 放入數據庫,同時在 Kubernetes 創建無狀態服務,這通常需要 10 分鍾左右的時間。這期間會通過一個 Go 語言程序對 App 表進行不間斷掃描以確認服務是否完成創建。同時還需要使用 Kubernetes 創建轉發規則等,等待所有需求都創建完成后就返回原版 ok 給調用方。
這里涉及到性能問題,因為數據庫內有很多條要處理的東西,這些要等待挨個處理,而這其中有很多都是無用數據,在掃到 App 前的這 10 分鍾里,就算去 Kubernetes 那邊調用,也是在做無用操作。
另外還有一個調用鏈很長的問題,在 Kubernetes 里創建的很多東西都會包含在同一次 API 請求里,這就導致隨時可能出現在一步完成后,下一步崩潰的情況。這種時候可能要考慮是否回滾的問題,而如果回滾就要刪掉相關服務和數據庫。這種情況在調用外部組件越多時,越容易出現。比較直觀的解決方法是簡化 API 流程,針對這個方法 Kubernetes 提供了 CRD。