Operator
Service Mesh 是螞蟻集團下一代技術架構的核心,也是螞蟻集團內部雙十一應用云化的重要一環,本文主要分享在螞蟻集團當前的體量下,如何支撐應用從現有微服務體系大規模演進到 Service Mesh 架構,并平穩落地。
為什么需要 Service Mesh ?
使用 Service Mesh 之前
SOFAStack 作為螞蟻集團微服務體系下服務治理的核心技術棧,通過提供若干中間件來實現服務發現和流量管控等能力,例如:
Cloud Engine 應用容器
SOFABoot 編程框架(已開源)
SOFARPC(已開源)
經過若干年的嚴苛金融場景的錘煉,SOFAStack 已經具備極高的可靠性和可擴展性。通過開源共建,也已形成了良好的社區生態,能夠與其他開源組件相互替換和集成。在研發迭代上,中間件類庫已經與業務解耦。
但是,由于運行時兩者在同一個進程內,這意味著在基礎庫升級時,需要推動業務方升級對應的中間件版本。
使用 Service Mesh 之后
螞蟻團隊引入的 Service Mesh,將原先通過類庫形式提供的服務治理能力進行提煉和優化后,下沉到與業務進程協同,但獨立運行的 Sidecar Proxy 進程中,大量的 Sidecar Proxy 構成了一張規模龐大的服務網絡,為業務提供一致的、高質量的用戶體驗。同時,也實現了服務治理能力在業務無感的條件下獨立進行版本迭代的目標。
應用 Service Mesh 的挑戰
Service Mesh 提供的能力很美好,但現實的挑戰同樣很多,例如:
數據面技術選型和私有協議支持。
控制面與螞蟻集團內部現有系統對接。
配套監控運維體系建設。
在調用鏈路增加兩跳的情況下,如何優化請求延遲和資源使用率等等。
什么是 Operator?
如果說 Kubernetes 是 “操作系統” 的話,Operator 是 Kubernetes 的第一層應用,它部署在 Kubernetes 里,使用 Kubernetes “擴展資源” 接口的方式向更上層用戶提供服務。
本文將從 MOSN(Sidecar Proxy)的運維和風險管控方面,分享 Operator 的實踐經驗。
Sidecar 運維
注入
創建注入
已經完成容器化改造且運行在 Kubernetes 中的應用,接入到 Service Mesh 體系中的方式中,最簡單的方式為:在應用發布階段,通過 Mutating Webhook 攔截 Pod 創建請求,在原始 Pod Spec 的基礎上,為 Pod 注入一個新的 MOSN 容器。該方案也是以 Istio 為代表的 Service Mesh 社區方案所采用的,示例如下:
初始配置
在資源分配上,起初依據經驗值,在應用 8 GB 內存的場景下,為 Sidecar 分配了 512 MB 內存,即
App: req=8G, limit=8G
Sidecar: req=512M, limit=512M
但是,這種分配方案帶來了一些問題:
部分流量比較高的應用,其 MOSN 容器出現了嚴重的內存不足甚至 OOM。
注入進去的 Sidecar 容器額外向調度器申請了一部分內存資源,這部分資源脫離了業務的 Quota 管控。
應對策略
為了消除內存 OOM 風險和避免業務資源容量規劃上的偏差,螞蟻團隊制定了新的“共享內存”策略。該策略主要內容:
Sidecar 的內存 request 被置為 0,不再向調度器額外申請資源。
Limit 被設置為應用的 1/4,保障 Sidecar 在正常運行的情況下,有充足的內存可用。
為了確實達到“共享”的效果,螞蟻集團針對 Kubelet 做了調整,使之在設置 Sidecar 容器 Cgroups Limit 為應用 1/4 的同時,保證整個 Pod 的 Limit 沒有額外增加。
新風險及解決方案
在上述應對策略下,會出現新的風險,螞蟻也提出了對應的解決方案,說明如下:
風險:Sidecar 與應用“共享”分配到的內存資源,導致在異常情況(比如內存泄露)下,Sidecar 跟應用搶內存資源。
解決方案:通過擴展 Pod Spec(即相應的 apiserver、Kubelet 鏈路),為 Sidecar 容器額外設置了
Linux oom_score_adj
這個屬性,以保障在內存耗盡的情況下,Sidecar 容器會被 OOM Killer 更優先選中,從而讓 Sidecar 比應用能夠更快速重啟,從而更快恢復到正常服務。風險:在 CPU 資源的分配上,可能出現 MOSN 搶占不到 CPU 資源從而導致請求延遲大幅抖動。
解決方案:確保在注入 Sidecar 時,根據 Pod 內的容器數量,為每個 Sidecar 容器計算出相應的 cpushare 權重,通過工具掃描并修復全站所有未正確設置的 Pod。
原地注入
原地注入的背景為下述幾個方面:
接入方式:相對比較簡單的接入方式是在創建 Pod 的時候注入 Sidecar。此時應用只需先擴容,再縮容,就可以逐步用帶有 Sidecar 的 Pod,替換掉舊的沒有 Sidecar 的 Pod。
存在的問題: 在大量應用、大規模接入的時候,需要集群有較大的資源 Buffer 來供應用實例進行滾動替換,否則替換過程將變得十分艱難且漫長。
螞蟻目標:雙十一大促不加機器,提高機器使用率。
為了解決存在的問題并實現預期目標,螞蟻團隊提出了“原地注入”的概念,即在 Pod 不銷毀,不重建的情況下,原地把 Sidecar 注入進去。
原地注入的步驟如下圖所示:
在 PaaS 提交工單,選擇一批需要原地注入的 Pod。
PaaS 調用中間件接口,關閉業務流量并停止應用容器。
PaaS 以 Annotation 的形式打開 Pod 上的原地注入開關。
Operator 觀察到 Pod 原地注入開關打開,渲染 Sidecar 模版,注入到 Pod 中,并調整 CPU、Memory 等參數。
Operator 將 Pod 內的容器期望狀態置為運行。
Kubelet 將 Pod 內的容器重新拉起。
PaaS 調用中間件接口,打開業務流量。
升級
螞蟻團隊將 RPC 等能力從基礎庫下沉到 Sidecar 之后,基礎庫升級與業務綁定的問題雖然消除了,但是這部分能力的迭代需求依然存在,只是從升級基礎庫變成了如何升級 Sidecar。
替換升級
最簡單的升級就是替換,即銷毀 Pod 并重新創建,這樣新建出來的 Pod 所注入的 Sidecar 自然就是新版本了。
但通過替換的升級方式,與創建注入存在相似的問題,即需要大量的資源 Buffer,并且,這種升級方式對業務的影響最大,也最慢。
非平滑升級
為了避免銷毀重建 Pod,螞蟻團隊通過 Operator 實現了“非平滑升級”能力,示例如下。
非平滑升級步驟:
PaaS 關流量,停容器。
Operator 替換 MOSN 容器為新版本,重新拉起容器。
PaaS 重新打開流量。
原地升級 Pod 打破了 Kubernetes Immutable Infrastructure 的設計,為了能夠實現預期目標,螞蟻團隊修改了 apiserver validation 和 admission 相關的邏輯,以允許修改運行中的 Pod Spec,也修改了 Kubelet 的執行邏輯以實現容器的增、刪、啟、停操作。
平滑升級
為了進一步降低 Sidecar 升級對應用帶來的影響,螞蟻團隊針對 MOSN Sidecar 開發了“平滑升級”能力,以實現在 Pod 不重建、流量不關停,應用無感知的條件下對 MOSN 進行版本升級。
平滑升級原理:Operator 通過注入新 MOSN,等待 MOSN 自身連接和 Metrics 數據遷移的完成,再停止并移除舊 MOSN,來達到應用無感、流量無損的效果。
努力方向:
提高成功率。
改進 Operator 的狀態機來提升性能。
回滾
為了確保大促活動萬無一失,螞蟻團隊還提供了 Sidecar 回滾的保底方案,以備在識別到 Service Mesh 出現嚴重問題的情況下,迅速將應用回滾到未接入 Sidecar 的狀態,通過應用原先的能力繼續提供業務服務。
風險管控
主要從下述幾個角度來分析:
技術風險:關于 Sidecar 的所有運維操作,都要具備三板斧能力。在灰度能力上,Operator 為升級等運維動作增加了顯式的開關,確保每個執行動作符合用戶和 SRE(Site Reliability Engineer,簡稱 SRE)的期望,避免不受控制地或不被察覺地自動執行變更操作。
監控:在基本的操作成功率統計、操作耗時統計、資源消耗等指標之外,仍需以快速發現問題、快速止血為目標,繼續完善精細化監控。
Operator 目前對外提供的幾個運維能力,細節上都比較復雜,一旦出錯,影響面又很大,因此單元測試覆蓋率和集成測試場景覆蓋率,也會是后續 Service Mesh 穩定性建設的一個重要的點去努力完善。
對未來的思考
演進到 Service Mesh 架構后,保障 Sidecar 自身能夠快速、穩定地迭代十分重要。未來螞蟻會向下述幾個方向進行發力:
繼續增強 Operator 的能力。
可能通過以下幾個優化手段,來做到更好的風險控制:
對 Sidecar 模板做版本控制,由 Service Mesh 控制面,而非用戶來決定某個集群下某個應用的某個 Pod 應該使用哪個版本的 Sidecar。這樣既可以統一管控全站的 Sidecar 運行版本,又可以將 Sidecar 二進制和其 Container 模板相綁定,避免出現意外的、不兼容的升級。
提供更加豐富的模板函數,在保持靈活性的同時,簡化 Sidecar 模板的編寫復雜度,降低出錯率。
設計更完善的灰度機制,在 Operator 出現異常后,快速熔斷,避免故障范圍擴大。
持續思考:整個 Sidecar 的運維方式能否更加“云原生”。