Categories
程式開發

Service Mesh 淺析:從概念、產品到實踐


近幾年,微服務架構逐漸發展成熟,從最初的星星之火到現在大規模的落地和實踐,幾乎已經成為分佈式環境下的首選架構。然而軟件開發沒有銀彈,基於微服務構建的應用系統在享受其優勢的同時,痛點也越加明顯。 Service Mesh 技術也因此而生,受到越來越多的開發者關注,並擁有了大批擁躉。本文會從概念介紹開始,讓大家理解Service Mesh 技術出現的原因以及願景;接著會對目前最主流的兩個產品Istio 和AWS App Mesh 進行詳細的比較;最後簡要介紹一下我們目前在該領域的一些探索與實踐。

Service Mesh – 服務通信的濟世良方

Service Mesh 是什麼?

Service Mesh(中文譯做服務網格)這一概念由 Buoyant 公司的 CEO,William Morg」n 首先提出。 2017 年 4 月該公司發布了第一個 Service Mesh 產品 Linkerd,這篇同一時間發表的文章 What’s a service mesh? And why do I need one? 也被業界公認是 Service Mesh 的權威定義。

“A service mesh is a dedicated infrastructure layer for handling service-to-service communication. It's responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the service mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware.”

其定義翻譯為:Service Mesh 是一個處理服務通訊的專門的基礎設施層。它的職責是在由雲原生應用組成服務的複雜拓撲結構下進行可靠的請求傳送。在實踐中,它是一組和應用服務部署在一起的輕量級的網絡代理,對應用服務透明。這段話有點晦澀難懂,但只要抓住下面 4 個關鍵點就能輕鬆理解:

  • 本質:基礎設施層
  • 功能:請求分發
  • 部署形式:網絡代理
  • 特點:透明

如果用一句話來總結,我個人對它的定義是:Service Mesh 是一組用來處理服務間通訊的網絡代理。

為什麼需要 Service Mesh?

上面晦澀抽象的定義很難讓你真正理解 Service Mesh 存在的意義。你可能會想,服務間通信(service-to-service communication)無非就是通過 RPC、HTTP 這些方式進行,有什麼可處理的?沒錯,服務間只需要遵循這些標準協議進行交互就可以了,但是在微服務這樣的分佈式環境下,分散的服務勢必帶來交互的複雜性,而規模越大的系統其通信越加錯綜複雜。分佈式計算下的 8 個謬論很好的歸納了分佈式環境下存在的網絡問題。而為了解決這些問題,提高系統的容錯能力和可用性,出現了服務註冊與發現、負載均衡、熔斷、降級、限流等等和通信相關的功能,而這些才是 Service Mesh 要真正處理的問題。

Pattern:Service Mesh 這篇文章詳細的講述了微服務架構下通訊處理的演進,由此引出 Service Mesh 出現的意義和核心價值。下圖為服務通信演變的過程:

Service Mesh 淺析:從概念、產品到實踐 1

  1. 最初,流量管理和控制能力(比如圖例中的熔斷、服務發現)是和業務邏輯耦合在一起,即便以引用包的方式被調用,依然解決不了異構系統無法重用的問題。
  2. 流控功能和業務耦合相當不美好,於是出現了提供這些功能的公共庫和框架。但這些庫通常比較複雜,無論是學習使用,與業務系統整合、維護都會帶來很大的成本。
  3. 為避免花費太多時間開發和維護這些通用庫,人們希望流量控制能力可以下沉到網絡通訊棧的層面,但幾乎無法實現。
  4. 於是另一種思路出現,就是將這些功能獨立成一個代理,由它先接管業務服務的流量,處理完成後再轉發給業務服務本身,這就是 Sidecar 模式。
  5. 為統一管理 Sidecar,該模式進一步進化,形成網絡拓撲,增加了控制平面,演變成 Service Mesh(最後的網格圖中,綠色代表業務服務,藍色代表 sidecar 服務)。

可以說,Service Mesh 就是 Sidecar 的網絡拓撲形態,Mesh 這個詞也由此而來。 (關於 Sidecar 模式這裡不做討論,你可以自行 Google)。

業務系統的核心價值應該是業務本身,而不是服務,微服務只是一種實現手段,實現業務才是目標。現有的微服務架構下,為解決可能出現的網絡通信問題,提升系統的彈性,開發人員不得不花費大量時間和精力去實現流量控制相關的非業務需求,不能聚焦在業務本身。而 Service Mesh 的出現解決了這一問題,帶來了下面 2 個變革:

  • 解決了微服務框架中的服務流量管理的痛點,使開發人員專注於業務本身;
  • 將服務通信及相關管控功能從業務程序中分離並下層到基礎設施層,使其和業務系統完全解耦。

在雲原生應用中,面對數百個服務或數千個實例,單個業務鏈路的請求經由服務的拓撲路徑可能會非常複雜,單獨處理非常必要。這就是 Service Mesh 的意義所在。

Service Mesh 的主要功能

那麼 Service Mesh 到底能帶來哪些實用的功能呢?可以把它們歸納為下面 4 個部分:

  • 流量控制:流控是最主要也是最重要的功能,通過Service Mesh,我們可以為應用提供智能路由(藍綠部署、金絲雀發布、A/B test)、超時重試、熔斷、故障注入、流量鏡像等各種控制能力;
    -安全:在安全層面上,授權和身份認證也可以託管給 Service Mesh;
  • 策略:可以為流量設置配額、黑白名單等策略;
  • 可觀察性:服務的可觀察性一般是通過指標數據、日誌、追踪三個方式展現的,目前的 Service Mesh 產品可以很容易和和主流的後端設施整合,提供給應用系統完整的監控能力。

通過上面的講述,我相信 Service Mesh 的概念大家都已經有所了解。接下來我們來介紹兩個重要的網格產品,讓大家進一步了解 Service Mesh 的產品形態是什麼樣的。

Istio vs AWS App Mesh – 開源與閉環之爭

目前市面上比較成熟的開源服務網格主要有下面幾個:Linkerd,這是第一個出現在公眾視野的服務網格產品,由Twitter 的finagle 庫衍生而來,目前由Buoyant 公司負責開發和維護;Envoy,Lyft 開發並且是第一個從CNCF 孵化的服務網格產品,定位於通用的數據平面或者單獨作為Sidecar 代理使用;Istio,由Google、IBM、Lyft 聯合開發的所謂第二代服務網格產品,控制平面的加入使得服務網格產品的形態更加完整。

從今年的風向看,作為構建雲原生應用的重要一環,Service Mesh 已經被各大雲廠商認可,並看好它的發展前景。在 Istio 紅透半邊天的情況下,作為和 Google 在雲服務市場競爭的 Amazon 來說,自然不願錯失這塊巨大的蛋糕。他們在今年 4 月份發布了自己的服務網格產品:AWS App Mesh。這一部分內容我們會聚焦於 Istio 和 App Mesh 這兩個產品,通過橫向的對比分析讓大家對 Service Mesh 的產品形態和兩大雲廠商的策略有一個更深入的認識。

產品定位

從官方的介紹來看,Istio 和 App Mesh 都明確的表示自己是一種服務網格產品。 Istio 強調了自己在連接、安全、控制和可視化4 個方面的能力;而App Mesh 主要強調了一致的可見性和流量控制這兩方面能力,當然也少不了強調作為雲平台下的產品的好處:託管服務,無需自己維護。

從某種程度上講,Istio 是一個相對重一點的解決方案,提供了不限於流量管理的各個方面的能力;而App Mesh 是更加純粹的服務於運行在AWS 之上的應用並提供流控功能。筆者認為這和它目前的產品形態還不完善有關(後面會具體提到)。從與 AWS 技術支持團隊的溝通中可以感覺到,App Mesh 應該是一盤很大的棋,目前只是初期階段。

核心術語

和 AWS 裡很多產品一樣,App Mesh 也不是獨創,而是基於 Envoy 開發的。 AWS 這樣的閉環生態必然要對其進行改進和整合。同時,也為了把它封裝成一個對外的服務,提供適當的 API 接口,在 App Mesh 這個產品中提出了下面幾個重要的技術術語,我們來一一介紹一下。

  • 服務網格(Service mesh):服務間網絡流量的邏輯邊界。這個概念比較好理解,就是為使用 App mesh 的服務圈一個虛擬的邊界。
  • 虛擬服務(Virtual services):是真實服務的抽象。真實服務可以是部署於抽象節點的服務,也可以是間接的通過路由指向的服務。
  • 虛擬節點(Virtual nodes):虛擬節點是指向特殊工作組(task group)的邏輯指針。例如 AWS 的 ECS 服務,或者 Kubernetes 的 Deployment。可以簡單的把它理解為是物理節點或邏輯節點的抽象。
  • Envoy:AWS 改造後的 Envoy(未來會合併到 Envoy 的官方版本),作為 App Mesh 裡的數據平面,Sidecar 代理。
  • 虛擬路由器(Virtual routers):用來處理來自虛擬服務的流量。可以理解為它是一組路由規則的封裝。
  • 路由(Routes):就是路由規則,用來根據這個規則分發請求。

Service Mesh 淺析:從概念、產品到實踐 2

上面的圖展示了這幾個概念的關係:當用戶請求一個虛擬服務時,服務配置的路由器根據路由策略將請求指向對應的虛擬節點,這些節點最終會與集群中某個對外提供服務的DNS或者服務名一一對應。

那麼這些 App Mesh 自創的術語是否能在 Istio 中找到相似甚至相同的對象呢?我歸納了下面的表格來做一個對比:

App Mesh Istio
服務網格(Service mesh) Istio並未顯示的定義這一概念,我們可以認為在一個集群中,由Istio管理的服務集合,它們組成的網絡拓撲即是服務網格。
虛擬服務(Virtual services) Istio中也存在虛擬服務的概念。它的主要功能是定義路由規則,使請求可以根據這些規則被分發到對應的服務。從這一點來說,它和App Mesh的虛擬服務的概念基本上是一致的。
虛擬節點(Virtual nodes) Istio沒有虛擬節點的概念,可以認為類似Kubernetes裡的Deployment。
虛擬路由器(Virtual routers) Istio也沒有虛擬路由器的概念。
路由(Routes) Istio中的目標規則(DestinationRule)和路由的概念類似,為路由設置一些策略。從配置層面講,其中的子集(subset)和App Mesh路由里選擇的目標即虛擬節點對應。但Istio的目標規則更加靈活,也支持更多的路由策略。

從上面的對比看出,App Mesh 目前基本上實現了最主要的流量控制(路由)的功能,但像超時重試、熔斷、流量複製等高級一些的功能還沒有提供,有待進一步完善。

架構

AWS App Mesh 是一個商業產品,目前還沒有找到架構上的技術細節,不過我們依然可以從現有的​​、公開的文檔或介紹中發現一些有用的信息。

Service Mesh 淺析:從概念、產品到實踐 3

從這張官網的結構圖中可以看出,每個服務的橙色部分就是 Sidecar 代理:Envoy。而中間的 AWS App Mesh 其實就是控制平面,用來控制服務間的交互。那麼這個控制平面具體的功能是什麼呢?我們可以從今年的 AWS Summit 的一篇 PPT 中看到這樣的字樣:

控制平面用來把邏輯意圖轉換成代理配置,並進行分發。

Service Mesh 淺析:從概念、產品到實踐 4

熟悉 Istio 架構的朋友有沒有覺得似曾相識?沒錯,這個控制平面的職責和 Pilot 基本一致。由此可見,不管什麼產品的控制平面,也必須具備這些核心的功能。

那麼在平台的支持方面呢?下面這張圖展示了 App Mesh 可以被運行在如下的基礎設施中,包括 EKS、ECS、EC2 等等。當然,這些都必須存在於 AWS 這個閉環生態中。

Service Mesh 淺析:從概念、產品到實踐 5

而 Istio 這方面就相對弱一些。儘管 Istio 宣稱是支持多平台的,但目前來看和 Kubernetes 還是強依賴。不過它並不受限於單一的雲平台,這一點有較大的優勢。

Service Mesh 淺析:從概念、產品到實踐 6

Istio 的架構大家都比較熟悉,數據平面​​由 Envoy sidecar 代理組成,控制平麵包括了 Pilot、Mixer、Citadel、Galley 等控件。它們的具體功能這裡就不再贅述了,感興趣的同學可以直接去官網查看詳細信息。

功能與實現方式

部署

無論是 Istio 還是 App Mesh 都使用了控制平面+數據平面的模式,且 Sidecar 都使用了 Envoy 代理。 Istio 的控制平面組件較多,功能也更複雜,1.0.x 版本完整安裝後的CRD有50個左右。架構修改後Mixer的一些adapter被獨立出去,crd有所降低。下面是最新的1.4版本,安裝後仍然有24個crd。

$ kubectl get crd -nistio-system
NAME                                     CREATED AT
adapters.config.istio.io                  2019-12-24T03:46:41Z
attributemanifests.config.istio.io        2019-12-24T03:46:41Z
authorizationpolicies.security.istio.io   2019-12-24T03:46:41Z
clusterrbacconfigs.rbac.istio.io          2019-12-24T03:46:41Z
destinationrules.networking.istio.io      2019-12-24T03:46:41Z
envoyfilters.networking.istio.io          2019-12-24T03:46:42Z
gateways.networking.istio.io              2019-12-24T03:46:42Z
handlers.config.istio.io                  2019-12-24T03:46:42Z
httpapispecbindings.config.istio.io       2019-12-24T03:46:42Z
httpapispecs.config.istio.io              2019-12-24T03:46:42Z
instances.config.istio.io                 2019-12-24T03:46:42Z
meshpolicies.authentication.istio.io      2019-12-24T03:46:42Z
policies.authentication.istio.io          2019-12-24T03:46:42Z
quotaspecbindings.config.istio.io         2019-12-24T03:46:42Z
quotaspecs.config.istio.io                2019-12-24T03:46:42Z
rbacconfigs.rbac.istio.io                 2019-12-24T03:46:42Z
rules.config.istio.io                     2019-12-24T03:46:42Z
serviceentries.networking.istio.io        2019-12-24T03:46:42Z
servicerolebindings.rbac.istio.io         2019-12-24T03:46:42Z
serviceroles.rbac.istio.io                2019-12-24T03:46:42Z
sidecars.networking.istio.io              2019-12-24T03:46:42Z
templates.config.istio.io                 2019-12-24T03:46:42Z
virtualservices.networking.istio.io       2019-12-24T03:46:42Z

而 App Mesh 就簡單得多,只針對核心概念添加瞭如下3個crd,用一個controller進行管理。

$ kubectl get crd -nappmesh-system
NAME                               CREATED AT
meshes.appmesh.k8s.aws             2019-12-13T05:35:00Z
virtualnodes.appmesh.k8s.aws       2019-12-13T05:35:00Z
virtualservices.appmesh.k8s.aws    2019-12-13T05:35:00Z

儘管Istio更多的crd在一定程度上代表了更加豐富的功能,但同時也為維護和troubleshooting增加了困難。

流量控制

儘管兩者的數據平面都基於 Envoy,但它們提供的流量控制能力目前還是有比較大的差距的。在路由的設置方面,App Mesh 提供了相對比較豐富的匹配策略,基本能滿足大部分使用場景。下面是 App Mesh 控制台裡的路由配置截圖,可以看出,除了基本的 URI 前綴、HTTP Method 和 Scheme 外,也支持請求頭的匹配。

Service Mesh 淺析:從概念、產品到實踐 7

Istio 的匹配策略更加完善,除了上面提到的,還包括 HTTP Authority,端口匹配,請求參數匹配等,具體信息可以從官方文檔的虛擬服務設置查看。下面兩段 yaml 分別展示了兩個產品在虛擬服務配置上的差異。

App Mesh 配置:

apiVersion: appmesh.k8s.aws/v1beta1
kind: VirtualService
metadata:
name: my-svc-a
namespace: my-namespace
spec:
meshName: my-mesh
routes:
  - name: route-to-svc-a
    http:
      match:
        prefix: /
      action:
        weightedTargets:
          - virtualNodeName: my-app-a
            weight: 1

Istio 配置:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings-route
spec:
hosts:
- ratings.prod.svc.cluster.local
http:
- match:
  - headers:
      end-user:
        exact: jason
    uri:
      prefix: "/ratings/v2/"
    ignoreUriCase: true
  route:
  - destination:
      host: ratings.prod.svc.cluster.local

另外一個比較大的不同是,App Mesh 需要你對不同版本的服務分開定義(即定義成不同的虛擬服務),而 Istio 是通過目標規則 DestinationRule 裡的子集 subsets 和路由配置做的關聯。本質上它們沒有太大區別。

除了路由功能外,App Mesh 就顯得捉襟見肘了。就在筆者撰寫本文時,AWS 剛剛添加了重試功能。而 Istio 借助於強大的 Envoy,提供了全面的流量控制能力,如超時重試、故障注入、熔斷、流量鏡像等。

安全

在安全方面,兩者的實現方式具有較大區別。默認情況下,一個用戶不能直接訪問 App Mesh 的資源,需要通過 AWS 的 IAM 策略給用戶授權。比如下面的配置是容許用戶用任意行為去操作網格內的任意資源:

{
   "Version": "2012-10-17",
   "Statement": [
      {
           "Effect": "Allow",
           "Action": [
               "appmesh:*"
          ],
           "Resource": "*"
      }
  ]
}

因此,App Mesh的授權和認證都是基於AWS自身的IAM策略。

Istio 提供了兩種認證方式,基於mTLS的傳輸認證,和 基於JWT 的身份認證。而Istio 的授權是通過 RBAC 實現的,可以提供基於命名空間、服務和 HTTP 方法級別的訪問控制。這裡就不具體展示了,大家可以通過官網文檔來查看。

可觀察性

一般來說,可以通過三種方式來觀察你的應用:指標數據、分佈式追踪、日誌。 Istio 在這三個方面都有比較完整的支持。指標方面,可以通過 Envoy 獲取請求相關的數據,同時還提供了服務級別的指標,以及控制平面的指標來檢測各個組件的運行情況。通過內置的 Prometheus 來收集指標,並使用 Grafana 展示出來。分佈式追踪也支持各種主流的 OpenTracing 工具,如 Jaeger、Zipkin 等。訪問日誌一般都通過 ELK 去完成收集、分析和展示。另外,Istio 還擁有 Kiali 這樣的可視化工具,給你提供整個網格以及微服務應用的拓撲視圖。總體來說,Istio 在可觀察方面的能力是非常強大的,這主要是因為 Mixer 組件的插件特性帶來了巨大的靈活性。

App Mesh 在這方面做的也不錯。從最新發布的官方 repo 中,App Mesh 已經提供了集成主流監控工具的 helm chart,包括 Prometheus、Grafana、Jaeger 等。同時,AWS 又一次發揮了自己閉環生態的優勢,提供了與自家的監控工具 CloudWatch、X-Ray 的整合。總的來說,App Mesh 在對服務的可觀察性上也不落下風。

Amazon 與 Google 的棋局

AWS App Mesh 作為一個今年 4 月份才發布的產品(GA),在功能的完整性上和 Istio 有差距也是情有可原的。從 App Mesh 的 Roadmap 可以看出,很多重要的功能,比如熔斷已經在開發計劃中。從筆者與 AWS 的支持團隊了解的信息來看,他們相當重視這個產品,優先級很高,進度也比較快,之前還在預覽階段的重試功能在上個月也正式發布了。另外,App Mesh 是可以免費使用的,用戶只需要對其中的實例資源付費即可,沒有額外費用。對 AWS 來說,該產品的開發重點是和現有產品的整合,比如 Roadmap 列出的使用 AWS Gateway 作為 App Mesh 的 Ingress。借助著自己的生態優勢,這種整合即方便快捷的完善了 App Mesh,同時又讓生態內的產品結合的更緊密,使得閉環更加的牢固,不得不說是一步好棋。

和 App Mesh 目前只強調流控能力不同,Istio 更多的是把自己打造成一個更加完善的、全面的服務網格系統。架構優雅,功能強大,但性能上受到質疑。在產品的更迭上貌似也做的不盡如人意(不過近期接連發布了 1.3 到 1.4 版本,讓我們對它的未來發展又有了期待)。 Istio 的優勢在於 3 大頂級技術公司加持的強大資源,加上開源社區的反哺,利用好的話容易形成可持續發展的局面,並成為下一個明星級產品。然而 Google 目前對 Istio 的態度有一些若即若離,一方面很早就在自家的雲服務 gcloud 裡提供了 Istio 的默認安裝選項,但同時又發布了和 Istio 有競爭關係的 Traffic director 這個託管的控制平面。筆者的猜測是 Google 也意識到 Istio 的成熟不可能一蹴而就,鑑於網格技術託管需求的越發強烈,先提供一個輕量化的產品以佔領市場。

目前各大廠商都意識到了網格技術的重要性並陸續推出了自己的產品(包括 AWS App Mesh,Kong 的 Kuma,國內的螞蟻金服、騰訊雲等),競爭也會逐漸激烈。未來是三分天下還是一統山河,讓我們拭目以待。

我們的實踐 – 從 Service Mesh 邁向雲原生

最後這部分給大家簡要介紹一下我們(FreeWheel)在 Service Mesh 領域的實踐。希望通過一些前瞻性的探索,總結出最佳實踐,為我們將來的微服務應用全面擁抱雲原生提供一定的經驗和指導。目前我們已經開發完成的 Data service 項目就整合了 AWS App Mesh,即將上線,並使用網格的能力進行智能路由和發布。

Data service 項目只包含兩個服務:Forecast service 和Query service,前者作為業務服務通過Query service 查詢來自持久層(ClickHouse)的數據;後者作為數據訪問代理,從持久層獲取數據並進行對象化的封裝。這個 mini 的微服務系統非常適合作為一個先行者為我們探索網格的功能、性能、易用性等方面的能力,且範圍足夠小,不會影響到其他業務系統。

選擇 AWS App Mesh 作為該項目的網格產品主要原因如下:

  • FreeWheel 是一個重度使用 AWS 各項服務的公司,未來所有的服務也都會全部託管的 AWS 上。作為一個閉環生態,App Mesh 可以和現有服務無縫整合,提高易用性;
  • 相比 Istio 這樣還不太成熟的開源產品,我們可以得到 AWS 技術團隊的全力支持;
  • 數據平面基於成熟高效的 Envoy,控制平面不存在 Istio 中的性能問題;
  • 完全免費

下圖是該項目的部署視圖。前端請求從我們的業務系統 UIF 發送到 Forecast service,它作為 App Mesh 的一個虛擬節點,調用 Data service 進行數據查詢。 Data service 作為數據平面,會注入 App Mesh 的 sidecar 代理。這兩個服務組成了一個 Mesh 網格,並無縫整合在 AWS 的 EKS 中。

Service Mesh 淺析:從概念、產品到實踐 8

下圖是網格內部的邏輯視圖,展示瞭如何利用 App Mesh 進行智能路由。 Forecast service 作為調用者被定義為虛擬節點,Data service 作為虛擬服務,掛載著虛擬路由,內部根據需要可以設定若干路由規則。用App Mesh 實現一個金絲雀發布的過程非常簡單:假設在Data service 的新版本(V2)發布前,流量都被指向V1 版本;此時我們在App Mesh 裡配置好一個新的路由規則,將10%的流量指向新的V2 版本;只需要將新的規則通過kubectl apply -f new-rule.yaml 應用到集群中,金絲雀發布就可以完成,且無縫切換,對用戶透明。

Service Mesh 淺析:從概念、產品到實踐 9

在後續的工作中,我們會先驗證App Mesh 的性能和可靠性,然後逐漸的將更多的流量控制(如超時重試、熔斷等)功能添加進來,並總結出一整套可行的實施方案,供大家參考。也歡迎對 Service Mesh 感興趣的同學加入到我們的團隊中,一起學習,共同進步。

總結

解耦是軟件開發中永恆的主題,開發人員對消除重複的偏執是推動軟件、以及架構模式演進的主要動力。而 Service Mesh 的核心價值就是將服務通信功能從業務邏輯中解耦,並下沉為基礎設施,由控制平面統一管理。有人將 Service Mesh、Kubernetes 和 Serverless 技術稱為雲原生應用開發的三駕馬車。 Kubernetes 是雲應用實際意義上的操作系統;Service Mesh 將服務通信功能剝離,實現了與業務的解耦;Serverless 讓你不用關心應用的服務器。這三項技術讓我們有能力實現應用開發的終極目標,那就是:只關注業務本身。而它們,也會引領我們通向未來雲原生應用的詩和遠方。