Categories
程式開發

螞蟻金服 Service Mesh 大規模落地系列 – 運維篇


《螞蟻金服Service Mesh 大規模落地系列》將會從核心、RPC、消息、無線網關、控制面、安全、運維、測試等模塊對Service Mesh 雙十一大規模落地實踐進行詳細解析,文末包含往期系列文章。本文為該系列文章的第三篇 – 運維篇。

引言

Service Mesh 是螞蟻金服下一代架構的核心,也是螞蟻金服內部向雲原生演進的重要一環。本文為Service Mesh 系列文章的運維篇,作者:黃家琦(花名:嘉祁),螞蟻金服運維專家,Service Mesh SRE,主要關注云原生基礎設施、中間件及Service Mesh 的穩定性,同時也是Pythoner,sofa-bolt-python 作者。本文將主要分享大規模服務網格在螞蟻金服當前體量下落地到支撐螞蟻金服雙十一大促過程中,運維角度所面臨的挑戰與演進,包括雲原生化的選擇與問題,對資源模型的挑戰,大規模下運維設施的演進,以及周邊技術風險能力的建設。 Service Mesh 在2019年得到了大規模的應用與落地,截止目前,螞蟻金服的Service Mesh 數據平面MOSN 已接入應用數百個,接入容器數量達數十萬,是目前已知的全世界最大的Service Mesh 集群。同時,在剛剛結束的雙十一大促中,Service Mesh 的表現也十分亮眼,RPC 峰值QPS 達到了幾千萬,消息峰值TPS 達到了幾百萬,且引入Service Mesh 後的平均RT 增長幅度控制在0.2 ms 以內。

擁抱雲原生

Service Mesh 在軟件形態上,是將中間件的能力從框架中剝離成獨立軟件。而在具體部署上,保守的做法是以獨立進程的方式與業務進程共同存在於業務容器內。我們在螞蟻金服內部的做法,則從開始,就選擇了擁抱雲原生。

Sidecar 模式

業務容器內獨立進程的好處在於與傳統的部署模式兼容,易於快速上線;但獨立進程強侵入業務容器,對於鏡像化的容器更難於管理。而云原生化,則可以將 Service Mesh 本身的運維與業務容器解耦開來,實現中間件運維能力的下沉。在業務鏡像內,僅僅保留長期穩定的 Service Mesh 相關 JVM 參數,從而僅通過少量環境變量完成與 Service Mesh 的聯結。同時考慮到面向容器的運維模式的演進,接入 Service Mesh 還同時要求業務完成鏡像化,為進一步的雲原​​生演進打下基礎。

||優|劣|
|獨立進程|·兼容傳統的部署模式
·改造成本低
·快速上線|·侵入業務容器
·鏡像化難於運維|
|Sidecar|·面向終態
·運維解耦|·依賴 K8s 基礎設施
·運維環境改造成本高
·應用需要鏡像化改造|

在接入 Service Mesh 之後,一個典型的 POD 結構可能包含多個 Sidecar:

  • MOSN:RPC Mesh, MSG Mesh, …(擴展中);
  • 其它 Sidecar;

MOSN:https://github.com/sofastack/sofa-mosn

螞蟻金服 Service Mesh 大規模落地系列 - 運維篇 1

這些 Sidecar 容器,與業務容器共享相同的網絡 Namespace,使得業務進程可以以本地端口訪問 Service Mesh 提供的服務,保證了與保守做法一致的體驗。

基礎設施雲原生支撐

我們也在基礎設施層面同步推進了面向雲原生的改造,以支撐 Service Mesh 的落地。

業務全面鏡像化

首先是在螞蟻金服內部推進了全面的鏡像化,我們完成了內部核心應用的全量容器的鏡像化改造。改造點包括:

  • 基礎鏡像層面增加對於 Service Mesh 的環境變量支撐;
  • 應用 Dockerfile 對於 Service Mesh 的適配;
  • 推進解決了存量前後端分離管理的靜態文件的鏡像化改造;
  • 推進了大量使用前端區塊分發的應用進行了推改拉的改造;
  • 大批量的 VM 模式的容器升級與替換;

容器 POD 化

除了業務鏡像層面的改造,Sidecar 模式還需要業務容器全部跑在 POD 上,來適應多容器共享網絡。由於直接升級的開發和試錯成本很高,我們最終選擇將接入 Service Mesh 的 數百個應用的數万個非 K8s 容器,通過大規模擴縮容的方式,全部更換成了 K8s PODs。

經過這兩輪改造,我們在基礎設施層面同步完成了面向雲原生的改造。

資源的演進

Sidecar 模式的帶來一個重要的問題,如何分配資源。

理想比例的假設

最初的資源設計基於內存無法超賣的現實。我們做了一個假設:

  • MOSN 的基本資源佔用與業務選擇的規格同比例這一假設。

CPU 和 Memory 申請與業務容器相應比例的額外資源。這一比例最後設定在了 CPU 1/4,Memory 1/16。

此時一個典型 Pod 的資源分配如下圖示:

螞蟻金服 Service Mesh 大規模落地系列 - 運維篇 2

這一方式帶來了兩個問題:

  • 螞蟻金服已經實現了業務資源的 Quota 管控,但 Sidecar 並不在業務容器內,Service Mesh 容器成為了一個資源洩漏點;
  • 業務很多樣,部分高流量應用的 Service Mesh 容器出現了嚴重的內存不足和 OOM 情況;

完美分割的不完美

不止於此,為了快速支撐 Service Mesh 在非雲環境的鋪開,上線了原地接入 Service Mesh。而原地接入 Service Mesh 的資源無法額外分配,在內存不能超賣的情況下,採取了二次分割的分配方式。此時的 POD 內存資源被切分為1/16內存給 Sidecar,與15/16給業務容器。除了以上兩個問題,還帶來一些新的問題:

  • 業務可見內存不一致,業務監控偏差,業務進程 OOM 風險。

討論之後,我們追加了一個假設:

  • Service Mesh 容器佔用的資源實質是在接入 Service Mesh 之前業務已使用的資源。接入 Service Mesh 的過程,同時也是一次資源置換。

共享

基於這個假設,推進了調度層面支持 POD 內的資源超賣,新的資源分配方案如下圖,Service Mesh 容器的 CPU、MEM 都從 POD 中超賣出來,業務容器內仍然可以看到全部的資源。

螞蟻金服 Service Mesh 大規模落地系列 - 運維篇 3

考慮到內存超賣也引入了 POD OOM 的風險,因此對於 Sidecar 容器還調整了 OOM Score,保證在內存不足時,Service Mesh 進程能夠發揮啟動比 Java 業務進程更快的優勢,降低影響。新的分配方案解決了同時解決了以上兩個問題,並且平穩支持了大促前的多輪壓測。

重建

但新的分配方案上線時,Service Mesh 已經在彈性建站時同步上線。同時我們還發現在一些場景下,Service Mesh 容器無法搶占到 CPU 資源,導致業務 RT 出現了大幅抖動,原因是在 CPU Share 模式下,POD 內默認並沒有等額的分配 CPU Quota 給 Sidecar。

於是還有兩個問題待解決:

  • 存量的已分配 Sidecar 仍有 OOM 風險;
  • Sidecar 無法搶占到 CPU;

我們已經無法承受更換全部 POD 的代價。最終在調度的支持下,通過對 Pod Annotation 的手動重新計算+修改,在 POD 內進行了全部資源的重分配,來修復這兩個風險。最終的修復容器總數約 25w 個。

變更與規模化下的運維挑戰

Service Mesh 的變更包括了接入與升級,所有變更底層都是由 Operator 組件來接受上層寫入到 POD annotation 上的標識,對相應 POD Spec 進行修改來完成,這是典型的雲原生的方式。由於螞蟻金服的資源現狀與運維需要,又發展出了原地接入與平滑升級。與 Operator 有關的具體細節在 Operator 篇中會詳細介紹,請持續關注本公眾號。

接入

最初的 Service Mesh 接入只提供了創建時注入 Sidecar。之後引入原地接入的原因,是為了支撐大規模的快速接入與回滾。

  • 創建接入:
    • 資源替換過程需要大量 Buffer;
    • 回滾困難;
  • 原地接入:
    • 不需要重新分配資源;
    • 可原地回滾;

原地接入/回滾需要對 POD Spec 進行精細化的修改,實踐中發現了很多問題,當前能力只做了小範圍的測試。

升級

Service Mesh 是深度參與業務流量的,因此最初的 Sidecar 的升級方式也需要業務伴隨重啟。看似簡單的這個過程中,我們也遇到了一個嚴重問題:

  • Pod 內的容器啟動順序隨機導致業務無法啟動。

這個問題最終依賴於調度層修改了啟動邏輯,POD 內需要優先等待所有 Sidecar 啟動完成,於是帶來第二個問題:

  • Sidecar 啟動慢了,上層超時。

此問題仍在解決中。 Sidecar 中,MOSN 提供了更為靈活的平滑升級機制:由 Operator 控制啟動第二個 MOSN Sidecar,完成連接遷移,再退出舊的 Sidecar。小規模測試顯示,整個過程業務可以做到流量不中斷,幾近無感。目前平滑升級同樣涉及到 POD Spec 的大量操作,考慮到大促前的穩定性,目前此方式未做大規模使用。

規模化的問題

在逐漸達到大促狀態的過程中,接入 Service Mesh 的容器數量開始大爆炸式增加。容器數量從千級別迅速膨脹到10w+,最終達到全站數十萬容器規模,並在膨脹後還經歷了數次版本變更。

快速奔跑的同時,缺少相應的平台能力也給大規模的 Sidecar 運維帶來了極大挑戰:

  • 版本管理混亂:
    • Sidecar 的版本與應用/ Zone 的映射關係維護在內部元數據平台的配置中。大量應用接入後,全局版本,實驗版本,特殊 Bugfix 版本等混雜在多個配置項中,統一基線被打破,難於維護。
  • 元數據不一致:
    • 元數據平台維護了 POD 粒度的 Sidecar 版本信息,但是由於 Operator 是面向終態的,會出現元數據與底層實際不一致的情況,當前仍依賴巡檢發現。
  • 缺少完善的 Sidecar ops 支撐平台:
    • 缺少多維度的全局視圖;
    • 缺少固化的灰度發布流程;
    • 依賴於人工經驗配置管理變更;
  • 監控噪聲巨大;

當然,Service Mesh 與 PaaS 的開發團隊都已經在建設相應的一些能力,這些問題正得到逐步的緩解。

技術風險建設

監控能力

我們的監控平台為 Service Mesh 提供了基礎的監控能力和大盤,以及應用維度的 Sidecar 的監控情況。包括:

  • 系統監控:
    • CPU;
    • MEM;
    • LOAD;
  • 業務監控:
    • RT;
    • RPC 流量;
    • MSG 流量;
    • Error 日誌監控;

Service Mesh 進程還提供了相應的 Metrics 接口,提供服務粒度的數據採集與計算。

巡檢

在 Service Mesh 上線後,巡檢也陸續被加入:

  • 日誌 Volume 檢查;
  • 版本一致性;
  • 分時調度狀態一致;

預案與應急

Service Mesh 自身俱備按需關閉部分功能的能力,當前通過配置中心實現:

  • 日誌分級降級;
  • Tracelog 日誌分級降級;
  • 控制面(Pilot)依賴降級;
  • 軟負載均衡長輪詢降級;

對於 Service Mesh 依賴的服務,為了防止潛在的抖動風險,也增加了相應的預案:

  • 軟負載均衡列表停止變更;
  • 服務註冊中心高峰期關閉推送;

Service Mesh 是非常基礎的組件,目前的應急手段主要是重啟:

  • Sidecar 單獨重啟;
  • POD 重啟;

變更風險防控

除了傳統的變更三板斧之外,我們還引入了無人值守變更,對 Service Mesh 變更做了自動檢測,自動分析與變更熔斷。

無人值守變更防控主要關注變更後對系統和業務和影響,串聯了多層檢測,主要包括:

  • 系統指標:包括機器內存、磁盤、CPU;
  • 業務指標:業務和 Service Mesh 的 RT、QPS 等;
  • 業務關聯鏈路:業務上下游的的異常情況;
  • 全局的業務指標;

經過這一系列防控設施,可以將全站性的 Service Mesh 變更風險在單一批次變更內發現和阻斷,避免了風險放大。

未來

Service Mesh 在快速落地的過程中,遇到並解決了一系列的問題,但同時也要看到還有更多的問題還亟待解決。做為下一代云原生化中間件的核心組件之一,Service Mesh 的技術風險能力還需要持續的建議與完善。未來需要在下面這些方面持續建設:

  • 大規模高效接入與回滾能力支撐;
  • 更靈活的變更能力,包括業務無感的平滑/非平滑變更能力;
  • 更精準的變更防控能力;
  • 更高效,低噪聲的監控;
  • 更完善的控制面支持;
  • 應用維度的參數定制能力;

本文轉載自公眾號金融級分佈式架構(ID:Antfin_SOFA)。

原文鏈接

https://mp.weixin.qq.com/s/BXhW7r8Dvgm-PPOlFvnlwg