螞蟻金服 Service Mesh 實踐探索

ServiceMesher發表於2018-10-31

作者 | 敖小劍

本文整理自螞蟻金服高階技術專家在 QCon 上海 2018 上的演講。

大家好,我是來自螞蟻金服中介軟體團隊的敖小劍,目前是螞蟻金服 Service Mesh 專案的PD。我同時也是 Servicemesher中國技術社群 的創始人,是 Service Mesh 技術在國內最早的佈道師。我今天給大家帶來的主題是”長路漫漫踏歌而行:螞蟻金服Service Mesh實踐探索”。

在去年的QCon上海,我曾經做過一個名為 “Service Mesh:下一代微服務” 的演講,不知道今天現場是否有當時聽過去年這場演講的同學?(備註:現場調查的結果,大概十幾位聽眾聽過去年的演講。)

當然,今天我們的內容不是繼續做 Service Mesh 的佈道,按秀濤的要求,今年要好好講一講實踐。所以今天我不會像去年那樣給大家詳細解釋 Service Mesh 是什麼,能做什麼,有什麼優勢。而是結合過去一年中螞蟻金服的實踐經驗,結合螞蟻金服的 SOFAMesh 產品,幫助大家更深刻的理解 Service Mesh 技術。

在開始今天的內容分享之前,我們先來熱個身,溫習一下去年的內容。去年我是來QCon佈道的,而佈道的核心內容就是告訴大家:Service Mesh 是什麼?

為了幫忙大家回答,我給出一個提示圖片,瞭解 Service Mesh 的同學對這張圖片應該不會陌生。

這裡我們一起回顧一下Service Mesh 的正式定義:

Service Mesh是一個基礎設施層,用於處理服務間通訊。現代雲原生應用有著複雜的服務拓撲,服務網格負責在這些拓撲中實現請求的可靠傳遞

在實踐中,服務網格通常實現為一組輕量級網路代理,它們與應用程式部署在一起,而對應用程式透明

黑色加粗部分是重點:

  • 基礎設施層:這是 Service Mesh 的定位,今天內容的最後一個部分我會和大家詳細展開這個話題
  • 服務間通訊:這是 Service Mesh 的功能和範圍
  • 實現請求的可靠傳遞:是 Service Mesh 的目標
  • 輕量級網路代理:是 Service Mesh 的部署方式
  • 對應用程式透明:是 Service Mesh 的重要特性,零侵入,Service Mesh 的最大優勢之一。

今天的內容會有這些:

  • 先給大家快速介紹一下我們的 SOFAMesh 專案,讓大家對故事的背景有個大致的瞭解
  • 然後給大家介紹一下為什麼我們選擇了用 Golang 語言來實現資料平面,這個是過去一年中各方對我們產品方案最大的疑惑
  • 再繼續給大家分享一下過去一年中我們在 Service Mesh 落地中遇到的典型問題和解決方案,給大家一些比較實際感受
  • 然後我們將探索一下服務間通訊的範圍,看看 Service Mesh 可以在哪些領域得到應用
  • 再接下來,給大家介紹一下在這一年實踐中的最大感悟,和大家聊聊基礎設施對服務網格的意義,這也是今年最想和大家分享的內容。
  • 最後,總結一下今天的內容,分享一些資訊

OK,讓我們開始今天的第一個部分,給大家快速介紹一下 SOFAMesh,目標在展開我們的各種實踐和探索之前,讓大家瞭解一下背景。

SOFAMesh 是螞蟻金服推出的 Service Mesh 開源產品,大家可以簡單的理解為是 Istio 的落地增強版本。我們有兩個原則:

  1. 跟隨社群

    體現在 SOFAMesh 是 fork 自 Istio,而且緊跟 Istio 的最新版本,確保和上游保持同步。

    我們在 Istio 上的改動都在 SOFAMesh 專案中開源出來,而且在驗證完成後我們也會聯絡 Istio,反哺回上游。

  2. 實踐檢驗

    一切從實踐出發,不空談,在實際生產落地中,發現問題,解決問題。在解決問題的過程中,不將就,不湊合,努力挖掘問題本質,然後追求以技術創新的方式來解決問題。

原則上:Istio 做好的地方,我們簡單遵循,保持一致;Istio 做的不好或者疏漏的地方,我們努力改進和彌補。

所有這一切,以實際落地為出發點,同時滿足未來的技術大方向。

SOFAMesh 的產品規劃,這是目前正在進行的第一階段。架構繼續延續 Istio 的資料平面和控制平面分離的方式,主要工作內容是:

  1. 用 Golang 開發 Sidecar,也就是我們的 SOFAMosn 專案,替代 Envoy。
  2. 整合 Istio 和 SOFAMosn,同時針對落地時的需求和問題進行擴充套件和補充,這是我們的 SOFAMesh 專案

在這個架構中,和 Istio 原版最大的不同在於我們沒有選擇 Istio 預設整合的 Envoy,而是自己用 Golang 開發了一個名為 SOFAMosn 的 Sidecar 來替代 Envoy。

為什麼?

我們的第二部分內容將給大家解答這個問題。

MOSN 的全稱是 “Modular Observable Smart Network”,正如其名所示,這是一個模組化可觀察的智慧網路。這個專案有非常巨集大的藍圖,由螞蟻金服的系統部門和中介軟體部門聯手UC大文娛基礎架構部門推出,準備將原有的網路和中介軟體方面的各種能力在 Golang 上重新沉澱,打造成為未來新一代架構的底層平臺,承載各種服務通訊的職責。

Sidecar 模式是 MOSN 目前的主要形式之一,參照 Envoy 專案的定位。我們實現了 Envoy 的 xDS API,和 Istio 保持相容。

在 Istio 和 Envoy 中,對通訊協議的支援,主要體現在 HTTP/1.1 和 HTTP/2 上,這兩個是 Istio / Envoy 中的一等公民。而基於 HTTP/1.1 的 REST 和基於 HTTP/2 的 gRPC,一個是目前社群最主流的通訊協議,一個是未來的主流,Google 的寵兒,CNCF 御用的 RPC 方案,這兩個組成了目前 Istio 和 Envoy(乃至 CNCF 所有專案)的黃金組合。

而我們 SOFAMesh,在第一時間就遇到和 Istio/Envoy 不同的情況,我們需要支援 REST 和 gRPC 之外的眾多協議:

  • SOFARPC:這是螞蟻金服大量使用的 RPC 協議(已開源)
  • HSF RPC:這是阿里集團內部大量使用的 RPC 協議(未開源)
  • Dubbo RPC: 這是社群廣泛使用的 RPC 協議(已開源)
  • 其他私有協議:在過去幾個月間,我們收到需求,期望在 SOFAMesh 上執行其他 TCP 協議,大部分是私有協議

為此,我們需要考慮在 SOFAMesh 和 SOFAMosn 中增加這些通訊協議的支援,尤其是要可以讓我們的客戶非常方便的擴充套件支援各種私有TCP協議。

為什麼不直接使用 Envoy?

幾乎所有了解 SOFAMesh 產品的同學,都會問到這個問題,也是 SOFAMesh 被質疑和非議最多的地方。因為目前 Envoy 的表現的確是效能優越,功能豐富,成熟穩定。

我們在技術選型時也是重點研究過 Envoy,可以說 Envoy 非常符合我們的需求,除了一個地方:Envoy是c++

這裡有個選擇的問題,就是資料平面應該選擇什麼樣的程式語言?

圖中列出了目前市場上主要的幾個 Service Mesh 類產品在資料平面上的程式語言選擇。

  • 首先,基於 Java 和 Scala 的第一時間排除,實踐證明,JDK/JVM/位元組碼這些方式在部署和執行時都顯得太重,不適合作為 Sidecar
  • Nginmesh 的做法有些獨特,通過 Golang 的 agent 得到資訊然後生成配置檔案塞給 nginx,實在不是一個正統的做法
  • Conduit(後更名為Linkerd2.0)選擇的 Rust 是個劍走偏鋒的路子,Rust 本身極其適合做資料平面,但是 Rust 語言的普及程度和社群大小是個極大的欠缺,選擇 Rust 意味著基本上無法從社群借力
  • Envoy 選擇的 c++
  • 國內華為和新浪微博選擇了 Golang

我們在選擇之前,內部做過深入討論,焦點在於:未來的新一代架構的底層平臺,程式語言棧應該是什麼?最終一致覺得應該是 Golang,配合部分 Java。

對於 Sidecar 這樣一個典型場景:

  • 要求高效能,低資源消耗,有大量的併發和網路程式設計
  • 要能被團隊快速掌握,尤其新人可以快速上手
  • 要和底層的 k8s 等基礎設施頻繁互動,未來有 Cloud Native 的大背景
  • 非常重要的:要能被社群和未來的潛在客戶接受和快速掌握,不至於在語言層面上有過高的門檻

不考慮其他因素,滿足 Sidecar 場景的最理想的程式語言,自然是非 Golang 莫屬。

但是到具體的技術選型時,面對要不要使用 Envoy,決策依然是非常艱難:關鍵在於,c++有 Envoy 這樣成熟的產品存在,可以直接拿來用;而 Golang 沒有可以和 Envoy 分庭抗禮的產品可以選擇,需要白手起家。

兩個選擇各有優劣,短期看:

  • 直接使用 Envoy,優勢在於這是一個成熟專案,表現穩定,而且也是 Isto 預設的 Sidecar,本身速度快,資源消耗低。可以直接拿來用,上手超簡單,投入少而收益快
  • 開發自己的 Golang 版本的 Sidecar,全是劣勢:這是一個全新專案,工作量非常大,而且技術上很有挑戰,還有需要自行完成和 Istio 整合的額外工作量以及維護成本,最大的挑戰還在於 Envoy 豐富甚至繁多的功能,要向 Envoy 對齊需要非常大的努力

可以說,短期內看,選擇 Envoy 遠比自行開發 Golang 版本要現實而明智。

但是,前面我們有說到,對於 MOSN 專案,我們有非常巨集大的藍圖:準備將原有的網路和中介軟體方面的各種能力重新沉澱和打磨,打造成為未來新一代架構的底層平臺,承載各種服務通訊的職責。這是一個需要一兩年時間打造,滿足未來三五年乃至十年需求的長期規劃專案,我們如果選擇以 Envoy 為基礎,短期內自然一切OK,快速獲得各種紅利,迅速站穩腳跟。

但是:後果是什麼?Envoy 是C++的,選擇 Envoy 意味著我們後面沉澱和打磨的未來通訊層核心是c++的,我們的語言棧將不得不為此修改為以c++為主,這將嚴重偏離既定的 Golang + Java 的語言棧規劃。

而一旦將時間放到三五年乃至十年八年這個長度時,選擇Envoy的劣勢就出來了:

  • C++ 帶來的開發和維護成本時遠超 Golang,時間越長,改動越多,參與人數越多,使用場景越多,差別越明顯
  • 從目前的需求上看,對 Envoy 的擴充套件會非常多,包括通訊協議和功能。考慮到未來控制平面上可能出現的各種創新,必然需要資料平面做配合,改動會長期存在
  • Golang 還是更適合雲原生時代,選擇 Golang,除了做 Sidecar,鍛煉出來的團隊還可以用 Golang 去完成其他各種產品。當然選擇 Envoy 也可以這麼幹,但是這樣一來以後系統中就真的都是c++的產品了。
  • 另外 Envoy 目前的官方定位只有 Sidecar 一種模式,而我們規劃中的 MSON 專案覆蓋了各種服務通訊的場景
  • 日後如何和 Envoy 協調是個大難題。尤其我們後續會有非常多的創新想法,也會容許快速試錯以鼓勵創新,選擇 Envoy 在這方面會有很多限制。

所以,最後我們的選擇是:先難後易,著眼未來。忍痛(真的很痛)捨棄 Envoy,選擇用 Golang 努力打造我們的SOFAMosn 專案。

對於同樣面臨要不要選擇 Envoy 的同學,我給出的建議是:Envoy 是否適合,取決於是不是想“動”它。

  • 如果只是簡單的使用,或者少量的擴充套件,那麼其實你接觸到的只是 Envoy 在冰山上的這一小部分,這種情況下建議你直接選擇 Envoy
  • 如果你和我們一樣,將 Service Mesh 作為未來架構的核心,預期會有大量的改動和擴充套件,同時你又不願意讓自己的主流程式語言技術棧中 c++ 佔據主流,那麼可以參考我們的選擇

當然,對於原本就是以 c/c++ 為主要程式語言棧的同學來說,不存在這個問題。

今天的第三部分,給大家介紹一下 SOFAMesh 在落地期間遇到的典型問題。

這裡給大家列出了三個主要問題:

  1. 通訊協議擴充套件

    前面也剛談到過,就是我們會需要支援非常多的TCP協議,包括各種私有協議。當然這個其實更應該歸為需求,後面詳細展開。

  2. 平滑遷移傳統架構

    所謂傳統架構指的是傳統的 SOA 架構,如基於 Dubbo 的很多現有應用,我們希望它們能夠在 Service Mesh 中直接跑起來,而不必一定要先進行微服務改造。

  3. 適配異構體系

    異構體系指的是,當我們進行 Service Mesh 落地時,會存在新舊兩條體系,比如說新的應用是基於 Service Mesh 開發的,而舊的應用是基於傳統框架比如說 Dubbo 或者是 Spring Cloud。

    當我們做應用遷移的時候,考慮到原來的存量應用會有很多的,比如上千個應用,這些應用肯定不可能說一個晚上全部切過去。中間必然會有一個過渡階段,在這個過渡階段新舊體系中的應用應該怎麼通訊,如何才能做到最理想。

    我們現在正在做方案,就是現在POC中。我們現在給自己設定的目標,就是希望給出一套方案,可以讓現有應用不做程式碼改動,然後可以在新舊兩邊隨便切,以保證平滑遷移。

    當然這套方案現在正在做POC,方案還未最終定型,所以今天我們不會包含這一塊的細節。大家如果有興趣的話可以稍後關注我們的這個方案。

今天給大家主要分享前面兩個部分,我們詳細展開。

第一個要解決的問題是如何快速的擴充套件支援一個新的通訊協議。

這個問題主要源於現在 Istio 的設計,按照 Istio 現在的方式,如果要新增一個新的通訊協議,是有幾大塊工作要做的:

  • 新增協議的 Encoder 和 Decoder

也就是協議的編解碼,這個沒得說,肯定要加的。

  • 修改 Pilot 下發 Virtual Host 等配置

  • 修改 Sidecar 如 Envoy,MOSN 去實現請求匹配

後兩者是大量重複的,就技術實現而言,需要修改的內容和現有的東西差不多,但是必須要再改出一份新的來。因為我們協議比較多,由此帶來的改動量非常大。根據我們之前的實踐,以這樣的方式加一個新的通訊協議可能需要幾天的工作量,而且每次改動都重複大量程式碼。

在這裡我們最後給出了一個名為 x-protocol 的通用解決方案,細節我們這裡不展開,只給大家看個結果。根據我們最新的驗證情況,如果我們要新增一個新的通訊協議,大概就是一兩百行程式碼,一兩個小時就能完成。即使加上測試,基本上也可以控制在一天之內,我們就能夠為 SOFOMesh 新增一個通訊協議的支援。

第二個要解決的問題就是讓傳統架構的存量應用上 Service Mesh 的問題。

就是剛才說的現有大量的基於 SOA 框架的程式,這些應用以傳統的 SOA 方式開發,如果直接挪到 Service Mesh 下,如Istio,會遇到問題:因為 Istio 用的服務註冊是通過 k8s 來進行,而 k8s 的服務註冊模型和原有的 SOA 模型是不匹配的。

SOA 框架當中,通常是以介面為單位來做服務註冊,也就是一個應用裡面部署多個介面的,在執行時是一個程式裡面有多個介面(或者說多個服務)。實際上是以介面為粒度,服務註冊和服務發現,包括服務的呼叫都是以介面為粒度。但是有個問題,部署到 Istio 中後,Istio 做服務註冊是以服務為粒度來做服務註冊,這個時候不管是註冊模型,還是按介面呼叫的方式都不一致,就是說通過 Interface 呼叫是調不通的。

左邊的程式碼例項,大家可以看得到,一般情況下 Dubbo 程式是按照 Interface 來註冊和發現,呼叫時也是通過 Interface 來呼叫。另外,在這個地方,除了通過介面呼叫之外,還有另外一個問題:服務註冊和服務發現的模型,從原來的一對N,也就是一個程式N個介面,變成了要一對一,一個程式一個服務。

怎麼解決這個問題?最正統的做法是,是先進行微服務改造:把原有的 SOA 的架構改成微服務的架構,把現有應用拆分為多個微服務應用,每個應用裡面一個服務(或者說介面),這樣應用和服務的關係就會變成一對一,服務註冊模型就可以匹配。

但是在執行時會有難處,因為微服務改造是一個比較耗時間的過程。我們遇到的實際的需求是:能不能先不做微服務改造,而先上 Service Mesh ?因為 Service Mesh 的功能非常有吸引力,如流量控制,安全加密。那能不能先把應用搬遷到 Service Mesh 上來,先讓應用跑起來,後面再慢慢的來做微服務改造。

這就是我們實際遇到的場景,我們需要找到方案來解決問題:註冊模型不匹配,原有用介面呼叫的程式碼調不通。

我們設計了一個名為 DNS通用選址方案 的解決方案,用來支援 Dubbo 等SOA框架,容許通過介面名來呼叫服務。

細節不太適合展開,給大家介紹最基本的一點,就是說我們會在 DNS 中增加記錄,如圖上左下角所示標紅的三個介面名,我們會在DNS中把這個三個介面指向當前服務的 Cluster IP。k8s 的 Cluster IP 通常是一個非常固定的一個IP,每個服務在k8s部署時都會分配。

在增加完DNS記錄之後,再通過 Interface 的方式去呼叫,中間在我們的 Service Mesh 裡面,我們會基於 Cluster IP 資訊完成實際的定址,並跑通 Istio 的所有功能,和用服務名呼叫等同。

這個功能在現有的 SOFAMesh 中已經完全實現,大家可以去試用。稍後我們會將這個方案提交給 k8s 或者 Istio 社群,看看他們是否願意接受這樣一個更通用的定址方式。

在這裡我們提出這樣一個設想:先上車後補票。所謂”先上車”是指說先上 Service Mesh 的車,”後補票”是指後面再去補微服務拆分的票。好處是在微服務拆分這個巨大的工作量完成之前,提前受益於 Service Mesh 提供的強大功能;同時也可以讓部署變得舒服,因為不需要強制先全部完成微服務拆分才能上 Service Mesh 。有了這個方案,就可以在應用不做微服務拆分的情況下執行在 Service Mesh 上,然後再從容的繼續進行微服務拆分的工作,這是我們提出這個解決方案的最大初衷。

當然,這裡面有比較多的技術實現細節,裡面有很多細節的東西實在是不適合在這裡一一展開。同時也涉及到比較多的 k8s 和 Istio 底層技術細節,需要大家對 k8s kubeproxy 網路轉發方案和 Istio 的實現有比較深的認知才能完全理解。這裡給出了幾篇文章,大家如果對這幾個技術有興趣,可以通過這些文章來了解裡面的技術細節,今天就不在這裡繼續展開了。

MOSN 和 x-protocol 介紹:

X-protocol 特性的詳細講解:

總結一下,我們解決了如下幾個問題:

  1. 可以快速的用幾個小時就在 SOFAMesh 中新增一個新的通訊協議
  2. 可以讓 SOA 應用在 SOFAMesh 上繼續通過介面進行呼叫,不需要改程式碼
  3. 可以實現不做 SOA 程式的微服務改造,就直接搬遷到 SOFAMesh,提前受益

第四塊,涉及到流量劫持的方案。

Service Mesh 有一個很重要的特性,就是無侵入,而無侵入通常是通過流量劫持來實現的。通過劫持流量,在客戶端伺服器端無感知的情況下,可以將 Service Mesh 的功能插進去。通常特別適合於類似安全加密等和現有應用的業務邏輯完全分離的場合。

但 Istio 的流量劫持方案做的還不夠好,目前 Istio 只給了一個方案就是 iptables。這個方案有比較多的問題,所以我們有幾個思路:

  1. 優化 iptables

    優化 iptables 主要是為了減少對Host主機的影響。

    用 iptables 有兩種思路:一個是 pod only,就是說在pod裡面做 iptables,這個Istio的官方做法,但是這樣需要ROOT許可權以便修改iptables配置;還有一種思路用Host主機上的 iptables,這個話可以不用ROOT許可權。我們對比之後,還是覺得放在pod裡面更好一點,因為效能損耗比較小一些,所以暫時我們用的是在pod中方案,但我們會進行優化,比如把 iptables 的模組簡化到最小。

  2. 調研IPVS方案

    我們現在正在調研IPVS方案。主要是 iptables 方案存在部署問題,就是 iptables 這個模組經常被限制使用。現場有沒有做運維的同學?你們的機器上開啟了 iptables 嗎?我能告訴大家的是,到目前為止,螞蟻金服內部的機器上,iptables不僅僅是禁用,而是整個 iptables 模組都被解除安裝。原因是效能、安全、維護等大家周知的原因,總之我們螞蟻金服內部是沒有這個模組的。

    為了解決這個問題,我們現在正在調研IPVS的方案,準備用IPVS來替換 iptables。這塊工作正在進行,目前方案已經驗證,但是還有一些細節沒有完善,後面有更多的訊息也給大家繼續介紹。

  3. 輕量級客戶端的實踐

    另外還有一個實踐是考慮不做流量劫持。比如說,最典型的RPC方案,因為RPC通常來說總是會有一個客戶端的。在上 Service Mesh 之後,可以將原來的客戶端的一些功能如服務發現、負載均衡、限流等精簡,形成一個新的輕量級客戶端,但此時終究還是有一個客戶端在的。

    這個時候,如果能知道 Sidecar 的訪問地址,是可以不進行流量劫持的,由客戶端直接將請求發給 Sidecar 就好了。所以,最基本的想法就是通過環境變數或者配置給出 Sidecar 的地址,告訴客戶端 Sidecar 就在 localhost 的8080埠。然後客戶端SDK簡單讀取一下,接下來直接將請求發過去就好了。這個方案可以輕鬆的繞開流量劫持的問題。

    這個方案我們內部也實踐過,早期用來替代多語言客戶端的版本用的是這個方案。當然,實踐中發現流量劫持還是有必要的,這是另外一個話題,後面有機會再詳細解釋。

但上面這三個都不是今天的重點,今天的重點是下面這個 Cilium + eBPF 的思路,這是我們目前最密切關注的一個方案。

Cilium是一個很新的專案,Cilium的思路中會涉及到底層通訊中TCP堆疊的問題。

這裡的圖片顯示了用 iptables 和輕量級客戶端方案的網路呼叫細節,左邊是客戶端 Service 和它的 Sidecar 之間的呼叫過程,可以看到它走了兩次的TCP堆疊。然後還有 iptables 的攔截。輕量級客戶端方案和流量劫持方案的差別在於減少一次iptables,避開了iptables的效能消耗。但是即使沒有 iptables,最終還是要走整個呼叫流程,雖然 Loopback 環回地址比network 網路通訊快很多,但是它終究還是走了兩次TCP堆疊,兩次TCP堆疊這裡是有效能消耗的。

而Cilium則給出了一個很好的思路:想辦法繞開TCP堆疊。

Cilium方案的好處,就在於在 socket 這個層面就完成了請求的轉發,通過 sockmap 技術實現 redirect,當然這個技術細節我們們就不在這裡展開。今天主要是講一下這個思路的好處和價值。Cilium 方案最大的好處,是可以繞開兩次TCP堆疊,繞開兩次TCP堆疊的好處,則會帶來一個出乎意外甚至違背常識的結果:Cilium 劫持可以比輕量級客戶端不劫持更快!這可能顛覆大家的觀念。

我們來體會一下。流量劫持,如 iptables,是要在原來的呼叫鏈當中插入一段,增加消耗導致效能下降,對吧?這是流量劫持最容易給人的留下的負面印象,就是流量劫持是有消耗的,所以優化的思路通常都在於減少這個消耗,或者選擇不做劫持從而避開這個消耗。那 Cilium 的做法則是給出另外一種解決流量劫持問題的思路:通過繞開兩次TCP堆疊和其他底層細節,更快的將請求轉發給 Sidecar!

Cilium的這個思路是我們非常讚賞的,通過這樣的方式減少服務和 Sidecar 之間的效能損失,可以解決 Service Mesh 中至關重要的一個問題:效能與架構的取捨

熟悉 Service Mesh 技術的同學,應該多少都有這樣的認知: Service Mesh 是一門中庸的藝術。在效能與架構之間, Service Mesh 選擇犧牲效能來換取架構。在傳統的侵入式框架中,客戶端業務程式碼和框架程式碼之間是通過函式來進行呼叫的,速度非常快完全可以忽略。而 Service Mesh 是強行把框架和類庫剝離出來,將上述的方法呼叫變成一個遠端呼叫,以犧牲了一次遠端呼叫的開銷為代價來換取整個架構的優化空間。這是 Service Mesh 技術和傳統侵入式框架的一個本質差異,也是 Service Mesh 技術和傳統侵入式框架所有差異的源頭。

這是 Service Mesh 技術最為重要的一次取捨:捨棄一次遠端呼叫的開銷,換取更富有彈性的架構和更豐富的功能。

Service Mesh 技術的發展,也由此出現兩個大方向:一方面是繼續在架構上獲取好處,更多的功能,更豐富的使用場景,各種創新,竭盡可能的獲取紅利;另一方面,是在舍字上下功夫,儘可能的將效能損失降到最低,以求得到前面的最大好處而將付出的代價降到最低。

我們在前面列出的這四個實踐,都可以說是在這條貪心的路上一步一步的探索和嘗試,希望可以將 Service Mesh 架構上的捨棄的部分再儘可能多的要回一部分。

當然,Cilium 在實際落地的時候還是會有一些問題,比如說現在最大的問題是 Cilium 對 Linux 核心的版本要求特別高,最低要求是4.9推薦4.10,然後裡面的部分特性要求是4.14。Linux 核心4.14是2017年底才釋出的,而目前 Linux 核心最新版本才4.18。Cilium 要求的 Linux 核心的版本實在太新了,部署時很難滿足。另外就是 Cilium 還是存在一些安全問題,主要是 eBPF 是將程式碼直接注入到核心執行,效率好是好,但是肯定會存在安全隱患。

我們接下來會重點跟蹤 Cilium 技術,也有可能會給出其它的類似方案,有興趣的同學可以關注我們的進展。

繼續給大家介紹今天的第四部分內容,對服務間通訊範圍的探索。

Service Mesh 起初關注的是東西向通訊,即系統內部各個服務之間的通訊,而這通常都是同步的,走REST或者RPC協議。

在Service Mesh的實踐過程中,我們發現,Service Mesh 可以提供的功能:

  • 請求轉發:如服務發現,負載均衡等
  • 路由能力:如強大的 Content Based Routing 和 Version Based Routing
  • 服務治理:基於路由能力而來的灰度釋出,藍綠部署,版本管理和控制
  • 糾錯能力:限流,熔斷,重試,測試目的的錯誤注入
  • 安全類:身份,認證,授權,鑑權,加密等

可以適用於 Service Mesh 之外的其他領域,也就是說我們可以在其他領域引入並重用這些能力,實現比單純的東西向通訊更廣泛的服務間通訊。

第一個探索的方向是 API Gateway,和東西向通訊直接對應的南北向通訊。

主要原因是南北向通訊和東西向通訊在功能上高度重疊,如服務發現,負載均衡,路由,灰度,安全,認證,加密,限流,熔斷……因此,重用東西向通訊的這些能力就成為自然而然的想法。

傳統侵入式框架下,重用這些能力的方式是基於類庫方式,也就是在 API Gateway 的實現中,典型如 Zuul,引入東西向通訊中的類庫。而 Service Mesh下,思路有所不同,重用的不再是類庫,而是 Sidecar:通過將 Sidecar 用於南北向通訊,重用 Sidecar 的請求轉發和服務治理功能。

將 Service Mesh 引入 API Gateway 的優勢在於:

  • 統一微服務和 API Gateway 兩套體系
  • 大量節約學習/開發/維護的成本
  • 可以在南北向通訊中獲得 Service Mesh 的各種特性
  • 可以通過 Service Mesh 的控制平面加強對南北向通訊的控制力

這個方向上,業界也有一些探索:

  • Ambassador: Kubernetes-native microservices API gateway,基於Envoy構建,開源專案
  • Gloo: The Function Gateway built on top of Envoy,同樣是基於Envoy,不過這個不僅僅用於傳統的微服務API Gateway,也可以用於Serverless架構的Function
  • Kong:在最近宣佈,即將釋出的1.0版本,kong將不再是單純的 API Gateway,而是轉型為服務控制平臺。可謂是一個反向的探索案例:從 API Gateway 向 Service Mesh 切。

而我們的思路也非常明確:在 SOFAMesh 和 SOFAMosn 的基礎上,打造新的 API Gateway 產品,以此來統一東西向通訊和南北向通訊。目前該專案已經啟動,後續也會作為開源專案公佈出來,對這個話題有興趣的同學可以保持關注。

前段時間我們在考慮 Serverless 方向時,剛好看到 Google 新推出了它的 Serverless 新專案 Knative,時間點非常的巧。和其他 Serverless 專案不同的是,Knative 專案關注的是 Serverless 平臺的標準化和規範化。

Knative 專案是基於 kubernetes 和 Istio 的,在 Knative 中 Istio 用於實現部分元件之間的通訊。在 Knative 專案中,對於是否應該引入 Istio 存在很大爭議,因為覺得 Istio 太重了,為了少量需求引入 Istio 有些興師動眾。不過這個問題對於本來就已經在用 Istio 的我們來說不是問題。

目前在 Serverless,尤其 Knative 方面,我們還在探索,目前的初步想法是這樣:

  • Serverless 很重要

    尤其 Knative 的出現,昭示著 Serverless 領域新的玩法出現,Serverless 平臺出現標準化和統一化的契機

  • Kubernetes + Serverless + Service Mesh(尤其是擴充套件範圍之後的 Service Mesh)是一個很好的組合

    從下向上,從底層基礎設施到服務間通訊再到 Function,在應用和系統之間形成了一套完整的支撐體系。

後續我們的產品策略,會繼續深入調研 knative,一邊POC一邊規劃產品,當然結合實際業務需要以落地為目標依然是基本要求。然後,非常自然的,我們會將標準版本的 Istio 替換為我們的 SOFAMesh 和 SOFAMosn。

舉例,目前我們在計劃嘗試使用 Serverless 的典型場景:

  • 小程式
  • AI:Serverless AI Layer,一站式機器學習平臺
  • Databus: 大資料處理

這是我們目前探索和規劃中的服務間通訊的完整藍圖:

  • Service Mesh

    負責東西向通訊,實踐中就是我們的 SOFAMesh 產品,基於 Istio 的擴充套件增強版

  • API Gateway

    負責南北向通訊,還在探索中,我們在嘗試基於 SOFAMosn 和 SOFAMesh 開發新的 API Gateway 產品

  • Serverless

    負責非同步通訊,事件驅動模型,粒度也從服務級別細化到Function級別,目前在積極探索和實踐 knative

這裡給出一個我們的預測:在雲原生的時代,服務間通訊的未來都會是 Service Mesh 這種方式,將服務間通訊的職責剝離並下沉。

這是今天的最後內容。前面四個部分的內容基本上都是給大家介紹我們的產品實踐,落地遇到的問題,以及我們正在做的一些探索,比較偏實際。第五部分會特殊一點,可能就有點務虛了。這塊要講是在過去一年當中,在專案落地的過程中的特別感受,其中最關鍵的一點就是基礎設施和服務網格之間的關係,或者說基礎設施對服務網格的意義。

裡面有一個時代背景:Cloud Native,雲原生。而在今年6月,CNCF 技術監督委員會通過了 Cloud Native 的定義,中文翻譯如上。

這裡我們將關注點放在標紅的這一句來:雲原生的代表技術包括容器、服務網格、微服務、不可變基礎設施和宣告式API。

對於雲原生架構,螞蟻金服的策略是:積極擁抱! 我們未來的架構也會往這個方向演進。

對於前面列舉的雲原生代表技術:

  • 容器:大阿里在容器技術上有非常深度的積累,實踐多年,而新版本的 Sigma3.* 版本也將基於 k8s。
  • 微服務:微服務的前身,SOA 服務化,在大阿里也是實踐多年, Dubbo / HSF / SOFA 可謂名滿江湖,目前也在陸陸續續的微服務改造中。
  • 不可變基礎設施和宣告式API:也是高度認可和長期實踐的技術。

對於Service Mesh的定位,我們是這樣理解的:

  • Service Mesh 是承上啟下的重要一環
  • 一方面充分利用底層系統能力
  • 一方面為上層應用提供堅實的底座

對於 Service Mesh,我們有一個重要判斷,這也是今天最想和大家分享的一點:Service Mesh 的歸宿,或者說最終的形態,是下沉到基礎設施!

從 Service Mesh 的發展看,從簡單的 Proxy,到功能完善的Sidecar(如Linkerd和Envoy),再到以 Istio 為代表的第二代Service Mesh,演進的方式如上圖:

  1. 第一步:從應用剝離

    通過將原有的方法呼叫改為遠端呼叫,將類庫的功能套上 Proxy 的殼子,Service Mesh 成功的將服務間通訊從程式中剝離出來,從此服務間通訊不再是應用程式的一部分。

    這一點是大家最容易接受的,對吧?這一步也是最容易實現的,只要搭起來一個 Sidecar 或者說 Proxy,將原有類庫的功能塞進去就好了。

  2. 第二步:下沉為抽象層

    這些剝離出來的服務間通訊的能力,在剝離之後,開始下沉,在應用程式下形成一個單獨的抽象層,成為服務間通訊專用基礎設施層。此時,這些能力以一個完成的形態出現,不再存在單獨的類庫或者框架形式。

    第二步和第一步往往是一脈相承的,一旦走出了第一步,自然而然會繼續。因為服務間通訊被抽取出來之後,繼續往前發展,就會很自然地把它就變成一個基礎設施層。

  3. 第三步:融入基礎設施

    繼續下沉,和底層基礎設施密切聯絡,進而融為一體,成為平臺系統的一部分,典型就是和 kubernetes 結合。

    Istio在這方面做了一個非常大的創新,Istio的創新,不僅僅在於增加控制平面,也在於和 kubernetes 的結合。

如果大家有在去年QCon聽過我的演講,會發現我在去年的時候對 Service Mesh 的理解和現在不太一樣。在去年的這個時候,我認為 Istio 最大的創新是增加了控制平面。但是,今年我覺得還再加一個關鍵點,除了控制平面的增加之外,Istio很重要的一點是開始跟k8s融合,充分利用 k8s 的能力。k8s 代表的是底層基礎設施,所有的各種能力在k8s上沉澱。在Istio上,已經能夠看到這樣一個非常明顯的趨勢: Service Mesh 已經開始和底層基礎設施密切聯絡,融為一體,成為整個平臺系統的一部分。

大家注意體會這中間的細微差異,第一步和第二步,將服務間通訊的能力抽取出來沉澱成一個抽象層,而如果止步於第二步的話,這個抽象層和底層基礎設施是沒有任何關係的。注意,比如說 Linkerd 或者 Envoy,在部署的時候,不管是物理機、虛擬機器或者容器,都沒有任何關係,本身也不利用底層的任何能力,可謂涇渭分明。但是一旦演進到了Istio,包括現在的Linkerd 2.0,就會發現轉為第三步的這種形態。

今天想跟大家說的是,Service Mesh 的未來,是將服務間通訊的能力下沉到基礎設施,然後充分利用底層基礎設施的能力來架構整個體系。而不再將底層基礎設施抽象成為就是一個簡單的作業系統抽象:給我cpu,給我記憶體,給我網路,給我IO,其他的事情和底層沒有任何關係,我自己上面全部搞定。這個思路在 Service Mesh 的未來發展中是不合適的, Service Mesh 未來一定是通過和基礎設施融合的方式來實現。

注意這個方式跟傳統方式的差異,不僅僅在於技術,而是這個方式會混淆兩個傳統的部門:一個叫做中介軟體,就像我所在的部門,或者有些公司叫做基礎架構部門;還有一個部門通常是運維部門或者叫做系統部門,負責維護底層基礎設施。大部分公司一般這兩個部門在組織架構上是分離的。做k8s的同學,和做微服務框架比如 Dubbo,Spring Cloud 的同學,通常是兩個不同的組織架構,彼此涇渭分明。第三步要走通的話,就會要求中介軟體部門和基礎設施部門關係要協調的特別好,要密切的合作,才能將事情做好。

這是在過去這一年當中,我們在實踐中得到的最大的一個感受,也是今天整個演講中最希望給大家分享的內容。

這裡丟擲一個問題,和傳統的 Spring Cloud,Dubbo等侵入式框架相比:

Service Mesh的本質差異在哪裡?

如果去年的我來回答這個問題,那我會告訴你:下移,沉澱,形成一個通訊層。而今天,我會告訴大家,除了這點之外,還有第二點:充分利用底層基礎設施。這是Dubbo,Spring Cloud從來沒有做到的!

這是今天最想和大家分享的觀點,也是過去一年實踐中最大的感悟:

Service Mesh 和 Spring Cloud / Dubbo 的本質差異,不僅僅在於將服務間通訊從應用程式中剝離出來,更在於一路下沉到基礎設施層並充分利用底層基礎設施的能力。

最後,我們總結一下今天的內容:

  • 給大家介紹了一下我們的 SOFAMesh 專案,如果大家有計劃應用 Service Mesh 技術,想上 Istio,可以嘗試瞭解一下我們的這個專案,會讓大家落地更舒服一些
  • 其次給大家介紹了選擇 Golang 的原因,主要是因為語言棧的長期選擇。如果有正在進行 Service Mesh 技術選擇的同學,可以作為參考。如果和我們一樣,更願意在未來保持 Golang 和 Java 為主要語言棧,則可以參考我們的方案,當然我們更希望你們可以和我們一起來共建 SOFAMesh 這個開源專案
  • 然後給大家分享了我們遇到的幾個典型問題,如何快速的支援更多通訊協議,如何讓傳統的SOA架構的應用程式在不進行程式碼修改的情況下也能從 Service Mesh 中受益,實現系統的平滑遷移。對於準備實際落地的同學會有幫助,由於時間所限未能將細節展開,大家可以會後檢視資料或者直接找我們交流
  • 對服務間通訊的範圍進行了探討,從原有的東西向通訊,擴充套件到南北向通訊,還有在 serverless 專案中的使用。希望能夠讓大家瞭解到 Service Mesh 技術可以應用的更多場景。
  • 最後談了一下切身感受:Service Mesh 技術要想完全發揮作用,需要和底層基礎設施融合,以充分發揮基礎設施的能力。這塊的認知,會影響到 Service Mesh 的技術選型,產品方案,甚至影響組織關係。可謂至關重要,希望每位有志於此的同學能認認真真的審視這個問題。

Service Mesh 是一個新生事物,新事物在剛出現時總是會遇到各種挑戰和質疑,尤其在它自身還不夠完全成熟的時候。而Service Mesh 背後的Cloud Native,更是一場前所未有的巨大變革。

我們心懷美好願景,憧憬未來的 Cloud Native 架構,那裡有我們的 Service Mesh,有k8s,有微服務……而新的架構,新的技術,從來都不是能一蹴而就的,更不存在一帆風順之類的美好而天真的想法。

道路從來都是人走出來的,或者說,趟出來的。作為國內 Service Mesh 技術的先驅者,我們坦言 Service Mesh 技術還不夠成熟,還有很多問題等待解決,還有非常多的挑戰在前面等著我們。但我們有信心相信,我們的方向是正確的,我們今天的每一份努力,每一份付出,都在讓我們離目標更近一步。

魯迅先生說:地上本沒有路,走的人多了,也便成了路。在 Service Mesh 的這個方向,相信會出現越來越多努力探索的身影。這條路,我們終究會努力趟出來!

長路漫漫,吾輩當踏歌而行!

目前 SOFAMesh 和 SOFAMosn 專案都已經在 github 開源,地址如下:

歡迎大家關注這兩個專案的進展,如果能star一下表示支援就更好了,感激不盡!

更希望可以一起來參與這兩個專案的建設,期待Issue,期待PR!

對 Service Mesh 技術感興趣的同學,可以關注servicemesher社群,這是一箇中立的純技術社群,彙集了當前國內大部分 Service Mesh 的技術人員。我本人也是 servicemesher 社群的創始人之一,這個社群的使命是傳播 Service Mesh 技術,加強行業內部交流,促進開源文化構建,推動 Service Mesh 在企業落地。

可以通過訪問社群網站 www.servicemesher.com 獲取各種技術資訊和社群活動資訊,可以關注 ServiceMesher 社群的微信公眾號得到及時的資訊推動。我們擁有一個龐大的翻譯組,除了翻譯各種 Service Mesh 相關的技術部落格和新聞,還負責 Envoy 和 Istio 兩個專案官方文件的日常維護。

也歡迎大家加入 ServiceMesher 社群的微信交流群,請按照 servicemesher.com 網站的 “聯絡我們” 頁面的要求加入微信交流群。

最後,厚顏推薦一下我自己的個人技術部落格 skyao.io ,歡迎瀏覽和交流。

今天的內容到此結束,非常感謝大家的聆聽,有緣下次再會!謝謝大家!

作者介紹

敖小劍,資深碼農,十六年軟體開發經驗,微服務專家,Service Mesh 佈道師,Servicemesher.com 社群聯合創始人。專注於基礎架構和中介軟體,Cloud Native 擁護者,敏捷實踐者,堅守開發一線打磨匠藝的架構師。曾在亞信、愛立信、唯品會等任職,目前就職螞蟻金服,在中介軟體團隊負責 Service Mesh 等產品開發。

ServiceMesher社群資訊

微信群:聯絡我入群

社群官網:www.servicemesher.com

Slack:servicemesher.slack.com 需要邀請才能加入

Twitter: twitter.com/servicemesh…

GitHub:github.com/

更多Service Mesh諮詢請掃碼關注微信公眾號ServiceMesher。

螞蟻金服 Service Mesh 實踐探索


相關文章