支持幾十種業務場景,位元組跳動大規模 Sidecar 運維管理實踐

2023-09-13     InfoQ

原標題:支持幾十種業務場景,位元組跳動大規模 Sidecar 運維管理實踐

作者 | 位元組跳動基礎架構 / 服務框架團隊研發工程師 - 劉立偉

本文主要介紹了位元組跳動 Sidecar 應用場景,以及進行 Sidecar 大規模版本升級的實踐和總結。

位元組 Sidecar 場景介紹

Sidecar 是一種用於擴展應用程式功能的架構模式。在 Sidecar 架構中,應用程式主進程和一個或多個 Sidecar 進程運行在同一個計算節點中,例如 Pod、物理機等,Sidecar 進程與主進程保持相同的生命周期,為應用程式提供額外的功能支持,例如網絡、安全、日誌、監控等相關功能。

目前,在位元組跳動的微服務架構下,有豐富的 Sidecar 應用場景,包括 Service Mesh、網關、風控、流量錄製、業務安全等幾十種業務場景 Sidecar,支持了抖音、飛書、基礎架構等多個業務線 / 部門。

以下,對幾個典型 Sidecar 應用場景進行介紹。

Service Mesh

在微服務體系下,RPC 框架是微服務之間通信的核心組件,RPC 框架支持了服務發現、流量調度、負載均衡、訪問控制等複雜的服務治理功能。隨著微服務規模變大,RPC 框架暴露出一些問題:

  • 多語言成本高:服務使用的開發語言分散,包含 Go、Python、C++ 等多種語言,各語言 RPC 框架都要實現完備的服務治理功能,開發、維護成本很高;
  • 升級成本高:治理功能更新後,需要升級框架版本,但是推動業務升級成本很高,如果版本有 Bug 也難以收斂;

Service Mesh 解決了上述問題,作為服務通信的基礎設施,它實現了一個高性能多協議的數據面代理和一個靈活可擴展的控制面服務,RPC 框架複雜的治理功能下沉到了數據面,數據面以 Sidecar 的形式部署在服務實例中。

相比於傳統的 RPC 框架,Service Mesh 優勢如下:

  • 多語言成本低:治理功能收斂到了數據面,各語言 RPC 框架輕量化,維護成本降低;
  • 升級成本低:治理功能更新後,只需要升級數據面 Sidecar,Sidecar 與業務代碼不耦合,可以單獨升級;

分布式 API 網關

API 網關(APIGateway)以 API 為核心,提供流量調度、穩定性策略、服務治理等全套解決方案。

API 網關最初的架構是中心化網關,一個網關集群為多個服務進行分流,存在一些痛點問題:

  • 網關變更風險大:網關的邏輯變更發布一旦有問題,將會影響所有業務;
  • 業務故障隔離差:多個服務共用同一個網關集群,單服務出現問題可能影響其他服務;
  • 大促容量評估難:每年雙 11、新春紅包活動,上萬 API 接口的 QPS 很難評估,不同 API 的 延時、QPS、BodySize 對於網關性能的影響都是不同的,為了網關入口的穩定性,只能大量的擴容;

API 網關團隊將網關改造成 Sidecar 部署到服務實例中,實現了分布式網關,並通過 Sidecar 運維平台對分布式網關進行管理。

通過分布式網關方案,解決了上述痛點問題:

  • 網關變更風險小:網關的更新操作,只影響被變更的服務,粒度可控;
  • 業務故障隔離強:不同服務相互隔離,出問題不會互相影響;
  • 無容量評估問題:網關部署在服務 Pod 內,服務自行承擔成本,自行擴容;

除了上述優化,也有其他收益:

  • 由於網關和 Service 通信由 RPC 改為了 IPC,延時收益明顯,性能得到了提升。

風控 Sidecar

風控團隊為業務提供 API 反爬取、反作弊支持,可以降低業務接口風險,加強 API 安全防護。

風控最初提供 SDK 接入方式,用戶接入時,需要在業務代碼中主動集成風控 SDK,存在以下痛點問題:

  • 用戶接入成本高:API 防護是基本的安全能力,有大量的 API 服務需接入,但是業務接入仍需修改代碼,有一定的接入成本;
  • 多語言 SDK 維護成本高:API 服務使用的語言不一致,不同語言均需要實現 SDK,SDK 更新疊代成本高;
  • 升級疊代困難:SDK 和業務代碼耦合在一起,SDK 升級時需要業務配合升級,版本疊代、問題收斂效率低;

為解決以上問題,風控團隊和 Service Mesh 團隊合作,藉助 Sidecar 方案和 Service Mesh 的能力,設計開發了風控 Sidecar:

  • Mesh Proxy 與風控 Sidecar 通信進行 http 請求 / 應答的風控判斷處理,Service 不感知風控邏輯;
  • 如果風控 Sidecar 攔截 http 請求,請求直接返回,Service 不會處理請求;

對比風控 SDK,通過風控 Sidecar 的方案,解決了上述痛點問題:

  • 用戶接入成本低:通過 Sidecar 運維平台動態注入 Sidecar,業務無感接入,接入成本低;
  • 無需維護多語言 SDK:風控邏輯收斂到 Sidecar,只需要疊代 Sidecar;
  • 升級疊代簡單:風控邏輯更新,僅需升級 Sidecar,不用推動業務升級,升級節奏可控。

MQ Sidecar

消息隊列 MQ 團隊提供了 RocketMQ/BMQ 兩種消息隊列來處理在線、離線場景。為了滿足業務接入,目前每種消息隊列提供了多個語言的 SDK,存在一些問題:

  • 多語言 SDK 維護成本高:功能很難對齊,MQ SDK 需要拓展流量治理、動態配置等能力,完善統一 Log、Metrics 邏輯,支持成本高;
  • SDK 更新疊代速度慢:SDK 版本更新後,需要隨業務代碼發版,由於使用 MQ 的業務很多,業務發版速度很慢;

因此,MQ 團隊引入 Sidecar 架構方案,實現了 MQ Sidecar:

  • MQ Sidecar 負責對接 MQ,流量治理等複雜邏輯收斂在 MQ Sidecar;
  • 保留 MQ SDK,SDK 只有基本 Produce/Consume 邏輯,接口保持一致,業務無需感知 Sidecar;

對比 MQ SDK,通過 MQ Sidecar 的方案,解決了上述痛點問題:

  • 多語言 SDK 維護成本低:MQ SDK 只保留基本邏輯,更新頻率低,減少維護成本;
  • 更新疊代速度快:MQ SDK 更新頻率低,MQ Sidecar 更新頻率高,但是 Sidecar 升級不受業務限制,升級速度快。

Sidecar 架構的優勢和挑戰

優勢

綜合對幾個典型 Sidecar 應用場景的介紹,可以總結出 Sidecar 架構核心優勢如下:

  • 多語言維護成本低:業務邏輯收斂到 Sidecar,降低維護多語言 SDK 的成本;
  • 用戶接入成本低:業務能力以 Sidecar 形式提供,用戶可以無感接入,或者低成本接入;
  • 版本升級靈活可控:Sidecar 版本更新後,可以單獨升級,支持有效的版本收斂、缺陷版本召回。

挑戰 - 升級運維

從上述分析可以看出,Sidecar 架構的關鍵是 Sidecar 進程可以獨立運行、單獨升級,因此,只有支持 Sidecar 的升級運維能力,才能使 Sidecar 架構真正發揮出優勢。然而,Sidecar 的升級運維面臨嚴峻的挑戰。

不同於傳統的微服務升級,Sidecar 升級場景更加複雜:

其中最關鍵的特點,Sidecar 升級面向的服務規模很大,以 Service Mesh Sidecar 舉例,生產環境接入情況如下:

  • 微服務數量超過 4W
  • 實例數量超過 400W

在如此大規模的場景下,在進行版本升級的時候,一些問題會被放大:

  • 事故風險:不同於升級單個 / 少量服務,升級的服務覆蓋面過廣時,如果版本有缺陷且擴散到很多服務,可能導致嚴重的業務受損,甚至出現掛站風險;
  • 時間成本:由於服務數量過多,運維人員在進行升級時,需要進行灰度驗證、灰度觀察、全區域發布等操作,如果發現問題還要操作回滾、修復,這將耗費大量時間,可能影響疊代速度,也耗費大量人力;

事故案例介紹

以下是一個真實的事故案例,展示了一次 Service Mesh 升級導致業務故障的處理全過程:

核心問題:穩定性 & 效率

在進行大規模 Sidecar 升級時,最核心的兩個問題是穩定性效率

對於穩定性,主要關注業務故障風險:

  • 新版本缺陷:新版本可能引入缺陷,比如邏輯 Bug、SDK 兼容問題等,導致業務發生故障;
  • 灰度驗證有效性:升級新版本時,需要進行灰度驗證,但是灰度驗證不充分,導致沒有發現問題;
  • 故障感知與處理:問題發生時,Sidecar 運維人員缺少報警沒有及時感知到,並在繼續升級的過程中,異常版本大範圍擴散,導致回滾、止損成本高。

歷史上,Service Mesh 升級導致過 P0 事故,導致業務受損

歷史上,Service Mesh 升級導致過 P0 事故,導致業務受損

對於效率,主要關注時間、人力成本:

  • 發布周期長:一個版本的發布周期可能很長,發布過程中,會出現多種情況影響發布速度,比如新 feature 隨意插入、緊急 feature、缺陷修復等;
  • 耗費人力:發布過程中,會有多種原因導致人力耗費嚴重,比如發布周期長,自動化程度低導致灰度、升級、版本召回繁瑣等。

歷史上,Service Mesh 進行 1 次大版本升級,歷時 5 個月,期間多次 feature 插入、問題修復,共發了 25 個小版本才最終完成升級

歷史上,Service Mesh 進行 1 次大版本升級,歷時 5 個月,期間多次 feature 插入、問題修復,共發了 25 個小版本才最終完成升級

Sidecar 大規模升級 - 思考

如何設計一套可靠的 Sidecar 大規模升級方案?為應對穩定性和效率兩個挑戰,主要從變更安全和變更效率兩個角度展開思考:

  • 變更安全:確保升級過程是安全的,不會對業務造成穩定性影響;
  • 變更效率:儘可能縮短升級的時間,減少手工操作,降低人力成本。

變更安全

要保障升級過程的安全,必須樹立對風險的正確意識:問題一定存在

只不過,對於問題,存在已知問題和未知問題,對兩種問題有不同的應對措施:

  • 杜絕已知問題:對於已知問題,要有嚴密的機制防止其發生,比如:維護缺陷版本,攔截缺陷版本的升級,拒絕不該升級的服務;
  • 謹慎驗證未知問題:保證版本驗證流程的合理性,儘早的將問題暴露出來,防止擴散。

當然,總有問題不可避免的發生,此時需要積極應對已發生問題:

  • 主動發現問題:要有主動檢測、發現問題的手段,主動、儘早發現問題,縮短影響時間;
  • 阻斷問題擴散:問題出現,要及時阻斷,防止問題擴散面積過大;
  • 快速修復:要對問題快速修復,及時止損,比如快速回滾、修復版本快速覆蓋等。

變更效率

為提升變更效率,首先,要完善變更規範:

  • 加強准入限制:杜絕隨意的 feature 插入,並保證合入的 feature 經過嚴格測試,防止出現 Bug 影響發布速度;

其次,通過技術手段,儘量加快升級速度:

  • 自動化:提升灰度驗證、逐步擴量、版本召回等流程的自動化水平,減少人的參與,減少人為導致問題的風險;
  • 安全加速:在有安全保證的前提下,合理的進行發布加速,提升速度。

總結

綜上,對 Sidecar 大規模升級的思路進行總結:

在不同的升級階段,綜合多種策略保障變更安全和變更效率:

同時,最關鍵的,要將版本升級流程平台化,將上述策略固化在平台上。

Sidecar 大規模升級 - 方案解析

我們構建了一套 Sidecar 運維管理系統,在系統上落地了 Sidecar 大規模升級方案,本節對如何進行安全、高效的 Sidecar 大規模升級進行詳細解析。

運維管理系統

Sidecar 運維管理系統提供了一套 Sidecar 應用運維管理解決方案,支持多種雲環境下 Sidecar 標準化接入、安全運行、觀測運維、版本治理等能力。

系統包含以下核心組件:

  • SidecarAgent:與業務進程部署在同一個實例中,負責管理 Sidecar 進程的生命周期,包括啟動、升級、退出、異常處理等;
  • SidecarManager:負責存儲 Service 啟用的 Sidecar 列表及版本信息,並下發給 SidecarAgent;
  • Sidecar 運維平台:負責 Sidecar 運維管理,支持 Sidecar 元信息管理、啟 / 停用、升級等運維能力,平台的升級計劃功能支持 Sidecar 大規模升級。

方案總覽

以下為完整的升級方案總覽:

方案從升級的各個階段入手,通過引入多項措施控制變更質量,保障變更安全,並在安全的基礎上加速升級,提升變更效率。

升級前,嚴格控制准入,包括:變更准入、版本准入、服務准入等策略。

升級中,平台構建了灰度驗證、逐步全量的自動化發布流程,可以謹慎的對版本進行驗證,並且謹慎的將版本逐步全量。

問題發生時,平台支持通過快速回滾、修復覆蓋的流程,支持快速恢復,快速止損。

升級後,支持版本治理,包括對長尾版本的收斂,以及在版本發現異常後,對版本進行快速的召回。

另外,在發布的整個流程中:

  • 加強變更管控:平台對齊公司變更管控、封禁策略,杜絕在非可變更窗口進行升級,降低變更風險;
  • 主動檢測異常:構建了異常檢測機制,支持在升級中,對服務進行異常檢測,在發現異常後,及時阻斷升級。

以下,對升級流程中灰度驗證、逐步全量和異常檢測進行介紹,詳細介紹如何將上述策略落地

升級流程

灰度驗證

灰度是逐步將新版本驗證穩定、可靠的過程,要在灰度階段儘可能的驗證出問題,不要到全量階段才暴露出問題,不然會導致更大面積的影響。

謹慎驗證

首先,關於灰度覆蓋面,要確保灰度驗證的有效性,需要保證足夠的覆蓋面,這樣才能驗證到足夠多的場景。

但是,如何保證足夠的覆蓋面,對於 Sidecar 新版本可能影響的服務,分為兩類:

  • 預期內受影響的服務:新版本的邏輯改動,對於預期內會受影響的服務,在升級時會明確關注;

比如:新版本變更了負載均衡算法,升級時會明確關注服務的流量負載情況

比如:新版本變更了負載均衡算法,升級時會明確關注服務的流量負載情況

  • 預期外受影響的服務:新版本的邏輯改動,意外的影響到了某些服務,這些服務不會被關注到。

比如:一些歷史邏輯受影響,或者有用戶使用了非公開的特性

比如:一些歷史邏輯受影響,或者有用戶使用了非公開的特性

但是,「預期外受影響的服務」是很難知道的,如果灰度覆蓋不到這些服務,就無法保證灰度的有效性。為了簡單起見,我們選擇了大力出奇蹟的做法,選擇對所有服務進行灰度,這樣就儘量保證了覆蓋面。

其次,關於單服務灰度範圍,位元組的服務部署區分小流量、單機房、全流量的部署階段,小流量階段一般只部署少量的實例,業務升級服務時使用該階段進行新版本驗證,因此 Sidecar 也使用小流量階段進行灰度驗證。

另外,關於升級方式,要保證灰度版本快速生效,這樣有問題才能儘快暴露出來,因此,我們選擇使用熱升級的方式,熱升級後,服務使用的 Sidecar 版本可以立即更新。

最後,還構建了特徵服務機制,Sidecar 的升級,可能會對特定服務產生影響,比如特定語言、框架、通信協議,或者使用了特殊配置的服務,因此,我們構建了特徵集合,並對每種特徵選取有代表性的服務集合,灰度驗證時,首先對這些服務進行驗證,並充分觀察服務是否異常。

比如:Service Mesh HTTP 壓縮算法調整,影響到了配置特殊 HTTP 壓縮算法的服務

比如:Service Mesh HTTP 壓縮算法調整,影響到了配置特殊 HTTP 壓縮算法的服務

防擴散

在灰度階段,要將問題儘早的暴露出來,並防止問題擴散,其中有兩個關鍵點:

  • 防擴散到全量階段:在灰度階段,將問題驗證出來,並及時阻斷後續升級流程;
  • 防擴散到過大灰度範圍:因為要灰度覆蓋所有服務,即便是在灰度階段,出現問題後,也要避免影響過多服務,將業務影響降到最低。

為達成防擴散的目標,設計實現了以下方案:

首先,控制升級順序,保障:

  • 服務敏感 / 重要程度:不敏感 / 不重要 -> 敏感 / 重要
  • 升級後觀察充分程度:觀察充分 -> 觀察不充分

具體順序如下:

  • 服務等級:P2 -> P1 -> P0
  • 部署區域:線下 -> 線上各區域
  • 部署環境:預覽環境 -> 生產環境
  • 服務分類:特徵服務 -> 全量服務

基於上述升級順序,對全量服務進行順序編排,然後逐步對服務進行灰度升級。

其次,控制升級節奏,要防止一次變更影響過多服務,控制好爆炸半徑:

分批發布:對服務進行合理的批次劃分,確定合適的分批間隔,逐個批次進行升級,目前平台支持指數分批、線性分批策略;

限制變更數量上限:限制好每批的變更數量上限,也限制好每天的變更數量上限。

分批發布 - 指數分批

分批發布 - 線性分批

最後,支持異常檢測、異常阻斷

  • 異常檢測:在升級時,創建異常檢測任務,對服務異常進行檢測;
  • 異常阻斷:如果檢測到異常後,及時阻斷升級,並通知用戶,進行異常問題確認。

檢測到異常後的工單詳情頁面

異常檢測詳情頁面

逐步全量

灰度驗證完成後,說明新版本已經基本穩定,可以開始全量的發布,但是,仍不排除有特殊問題沒有暴露出來,因此,在全量的過程中,也要防範問題的發生。

全量階段,主要目的是進行安全的鋪量,在保證安全的前提下,將新版本逐步的升級到全量服務。

主要採用了以下策略:

  • 安全升級

不同於灰度階段使用熱升級的方式,使用安全升級進行全量,安全升級不會讓版本立即生效,而是配置好目標版本,跟隨業務升級生效。使用安全升級,可以避免熱升級可能導致的業務流量受損,並且服務在升級時,有服務負責人進行充分的穩定性觀察,相比熱升級安全很多。

  • 控制順序

和灰度驗證類似,安全鋪量階段,也採用相同的升級順序控制,確保先升級不敏感 / 不重要的服務,保障敏感 / 重要的服務。

  • 控制節奏

和灰度驗證類似,安全鋪量階段,也採用相同的升級節奏控制,進行分批升級,限制變更數量上限,控制好爆炸半徑。

  • 並行加速

由於升級的區域很多,為加速升級速度,對不同的區域進行合理的並行推進,加快推進速度。

流程總結

對升級流程進行總結,以下為一個升級流程的全貌,包括灰度階段、全量階段,以及,升級完成後的版本收斂階段。

平台將這些流程、策略都固化下來,支持了大規模升級流水線,可以支持自動化的版本升級,保障變更安全,提升變更效率。

以 Service Mesh 升級為例,各階段大概耗時如下:

  • 灰度階段 - 線下:5 個工作日
  • 灰度階段 - 線上各區域:12 個工作日
  • ‍全量升級(線下 & 線上):11 個工作日

以 Service Mesh 升級為例,各階段大概耗時如下:

  • 灰度階段 - 線下:5 個工作日
  • 灰度階段 - 線上各區域:12 個工作日
  • ‍全量升級(線下 & 線上):11 個工作日

異常檢測

在 Sidecar 升級過程中,平台支持主動檢測、主動發現異常,在出現問題後,平台可以及時的阻斷異常,降低故障影響時間,減少業務損失。

Sidecar 升級過程中,如果新版本有問題,一般會導致 Sidecar 自身或者業務出現異常問題,比如:

  • Sidecar 異常:Sidecar 異常退出,Sidecar CPU、MEM 出現異常增長;
  • 服務異常:服務接口錯誤率升高、延時升高,調用下遊錯誤率升高,實例 CPU、MEM 出現異常增長,甚至服務出現告警等。

這些問題一般能從指標、日誌等方面檢測出來,也可以從服務告警反映出異常。因此,我們可以對這些指標、日誌、服務告警等進行檢測,檢測是否有異常發生。

我們和位元組內部上線檢測平台(Niffler)合作,構建了 Sidecar 檢測模型,在升級過程中對服務、Sidecar 的異常進行檢測,檢測模型包含以下三類檢測指標:

  • 基座服務指標:檢測服務是否出現進程退出 /Panic,CPU、MEM 占用上漲,接口成功率下降、延時上漲,錯誤日誌增多,出現服務告警等;
  • Sidecar 通用指標:檢測 Sidecar 是否發生進程退出 /Panic,CPU、MEM 占用上漲等;
  • Sidecar 自定義指標:Sidecar 開發者可以配置自定義指標,檢測這些指標是否出現異常。

落地效果

以 Service Mesh 為例,該大規模升級方案上線後,升級穩定性和效率都有明顯收益:

穩定性方面,很多問題在灰度驗證時被及時發現,異常檢測機制也檢測、發現到很多異常,版本升級導致的事故數量、等級明顯降低

升級效率方面,Service Mesh 發布一次大版本,小版本數量發布耗時都明顯下降:

Service Mesh 在一個大版本的升級過程中,會發布小版本進行灰度、全量的全流程,如果小版本成功全量到所有服務,則完成大版本的升級。

但是,在小版本發布過程中,如果有緊急 feature、問題修復,則需要重新發布的小版本,一般要發布多個小版本,才能完成大版本升級。

Service Mesh 在一個大版本的升級過程中,會發布小版本進行灰度、全量的全流程,如果小版本成功全量到所有服務,則完成大版本的升級。

但是,在小版本發布過程中,如果有緊急 feature、問題修復,則需要重新發布的小版本,一般要發布多個小版本,才能完成大版本升級。

  • 平均小版本數量:從 10+ 個降低到 8.6 個

  • 一次大版本發布,平均耗時:從 4+ 個月降低到 2.1 個月

下一步計劃

1. 繼續提升效率

目前,雖然大規模升級效率已經有了明顯提升,但是由於位元組跳動業務覆蓋區域很多,平台缺乏多區域串聯能力,目前操作所有區域的升級仍是一件繁瑣的事情。因此,我們計劃會進一步增強多區域升級的能力,降低多區域操作成本。

另外,為了解決升級過程中,如果發現版本缺陷,進行修復並重新升級,對升級速度影響過大的問題,我們也在探索更高效的小版本自動驗證機制,進一步加快問題發現能力,加快升級速度。

2. 完善異常檢測

目前,雖然支持了異常檢測能力,但是當前的檢測模型還比較簡單,檢測準確率有待提升,存在較多的誤報、漏報。因此,我們後續會對檢測模型進行進一步調優,提升準確率,以發揮異常檢測的更多價值。

3. 加強版本收斂

目前,雖然設計了版本收斂階段,但是平台對於版本收斂的功能支持並不好。有些 Sidecar 仍舊會存在比較多的長尾版本,並且如果出現缺陷版本,召回流程也比較繁瑣。因此,我們後續會進一步加強版本收斂能力,支持更有效的長尾版本收斂、缺陷版本召回功能。

AI 大模型熱潮來襲,看機密計算如何應對敏感數據安全挑戰

號稱比 Python 快 68000 倍的 Mojo 語言正式發布!Rust 能否與之匹敵?

小米一開源項目被批「三無」,項目導師回應;Ruby on Rails之父將Type從Turbo框架中移除 | Q資訊

大模型之戰,騰訊來了

文章來源: https://twgreatdaily.com/zh-cn/ef690dda5d14c1a4964cd2331da53e3d.html