微服務發展的這幾年,新的技術和概念層出不窮,這些技術的引入本質上都是在圍繞服務穩定性和業務開發效率提升,最近兩年服務網格越來越被廣大的微服務使用者所認知。
在 Kubernetes 已經成為雲原生時代的作業系統的今天,如何更好的擁抱 Kubernetes 生态,實作業務快速上雲,享受雲計算帶來的能力,其中服務網格是一個必須要提的關鍵技術,但是在服務網格使用過程中我們會碰到很多的問題,比如:如何讓現有的應用遷移到服務網格,如何支援多種語言、架構的互通和治理,如何使用可觀測産品排查問題,接下來我将從如何接入服務網格、異構服務架構、語言的互通和可觀測三個方面回答這個問題。
遷移應用到服務網格中
服務網格
服務網格是用于處理服務間通信的專用基礎設施層,它負責通過包含現代雲原生應用程式的複雜服務拓撲來可靠地傳遞請求。實際上,服務網格通常通過一組輕量級網絡代理來實作,這些代理與應用程式代碼一起部署,而不需要感覺應用程式本身。
目前主流的服務網格開源軟體是 Istio,其整體架構如下:

從圖中可以看到服務網格與業務容器是在同一個 Pod 中的不同容器,帶來的優勢有如下三點:
1.微服務治理與業務邏輯的解耦。服務網格把 SDK 中的大部分能力從應用中剝離出來,拆解為獨立程序,以 Sidecar 的模式進行部署,服務網格通過将服務通信及相關管控功能從業務程式中分離并下沉到基礎設施層,使其和業務系統完全解耦,使開發人員更加專注于業務本身。
2.異構語言/架構的統一治理。随着新技術的發展和人員更替,在同一家公司中往往會出現不同語言、不同架構的應用和服務,為了能夠統一管控這些服務,以往的做法是為每種語言、每種架構都開發一套完整的 SDK,維護成本非常之高,而且給公司的中間件團隊帶來了很大的挑戰,有了服務網格之後,通過将主體的服務治理能力下沉到基礎設施,多語言的支援就輕松很多了。
3.服務網格不但可以承擔流量代理,對于業務共用的、通用的場景和需求都可以成為服務網格的一部分,這樣能有效提高業務開發效率。
應用接入服務網格
目前服務網格對 Kubernetes 支援最完整,同時也支援了 VM 的應用接入,但是需要較多的配置,我們推薦首先将 VM 上的服務容器化後在接入網格中,逐漸遷移已有的應用,通過網關來打通服務網格中的應用和 VM 中沒有接入服務網格的應用。
服務網格的接入首先是需要安裝 Istiod,然後通過對 Namespace 打标來完成 Sidecar 的自動注入,可以選擇性的對一些服務不進行 Sidecar 的注入,比如類似 MySQL、Redis 等中間件應用,主要是減少 Envoy 帶來的延遲,在 EDAS 中可以針對每個應用進行打标,對需要加入服務網格的應用才進行 Sidecar 的注入。
異構微服務的互通、治理
由于業務的發展,基于業務産品的選擇,業務開發語言越來越多種多樣,這些語言之間的互通成為大家關注的問題,目前常見的場景如 Java 語言和非 Java 語言的互通,互通中最重要的問題就是服務發現和通信協定的支援。
服務發現
通常我們在使用 Kubernetes 上部署服務如下,其中定義了 Kubernetes Service 用于服務間請求的域名:
apiVersion: apps/v1
kind: Deployment
metadata:
name: details-v1
labels:
app: details
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: details
version: v1
template:
metadata:
labels:
app: details
version: v1
spec:
containers:
- name: details
image: docker.io/istio/examples-bookinfo-details-v1:1.16.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080
apiVersion: v1
kind: Service
metadata:
name: details
labels:
app: details
service: details
spec:
ports:
- port: 9080
name: http
selector:
app: details
Istio 監聽 Kubernetes Api Server,擷取服務的 Service、Pod 等資料,通過 XDS 方式提供給 Envoy,Envoy 會通過擷取的資料做負載均衡。
很多微服務架構都在使用如 Nacos、Consul、Zookeeper 等注冊中心,這部分微服務如何在不進行大規模改造下使用服務網格呢,這就設計到 Istiod 跟注冊中心的打通,目前社群提供了以下的幾種方式實作注冊中心資料打通:
1.MCP Server
編寫自定義的 MCP Server 從第三方注冊中心擷取服務資料,轉換為 ServiceEntry 和 WorkloadEntry 資源,通過 MCP 協定提供給 Istio 中的 MCP Config Controller, Istiod 需要配置MCP Server位址,目前在開源項目中包含 MCP Server 的注冊中心的有很多,阿裡雲 MSE 提供托管的 Nacos 注冊中心,直接提供 MCP Server 能力。
2.ServiceEntry 和 WorkloadEntry
編寫獨立的第三方元件,該元件從注冊中心中擷取服務資料,然後轉換為 Istio 中 ServiceEntry 和 WorkloadEntry CRD,寫入到 Kubernetes API Server 中。Pilot 的 Kube Controller 會監聽 Kubernetes API Server 中和 Istio 相關資源的變化,并将 ServiceEntry 和 WorkloadEntry 轉換為内部Service模型,通過Xds協定同步給Sidecar。
3.自定義擴充卡
編寫自定義的 Adapter 來內建第三方注冊中心,該擴充卡從注冊中心中擷取服務和服務執行個體,轉換為 Pilot 内部的Service模型,內建到 Service Controller 中,類似現有的Consul Service Registry的适配方式,這種方式的優點就是不需要通過第三方進行轉換,但是跟Istio耦合在一起,在 Istio 版本更新較快的時候,需要不斷的适配對應的新版本。
MSE 注冊中心
第一種方式需要注冊中心提供支援,第二種方式需要獨立的三方元件進行同步,可用性、維護是一個負擔,第三種需要對 Istio 非常熟悉,維護更新成本很高,目前 MSE 注冊中心已經支援 MCP Over XDS 的方式對接 Istio,可用性高,免維護。
我們通過 Java Agent 支援Xds協定的方式對接 Istio,同時 Istio 也通過 MCP Over XDS 對接 Nacos 注冊中心,這樣服務發現的資料在 Java Agent 和 Sidecar 中都能拿到, Java 和非 Java 的服務可以互相發現,互相調用。
服務網格的服務治理
服務網格 Sidecar 通過容器的方式與業務容器共享網絡,通過Iptables的方式将 inbound 和 outbound 流量都劫持到 Sidecar 上,Sidecar 解析資料包,擷取請求後通過比對服務發現資料找到對應的服務端,然後比對對應的路由規則找到滿足條件的服務端發送請求。
服務網格的服務治理中Istio的路由規則最關鍵的兩個CRD是VirtualService和DestinationRule,他們描述了請求比對、路由的過程,如下所示:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
- name: v3
labels:
version: v3
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1
DestinationRule 中包含了 reviews 服務的三個版本,VirtualService 描述了對 reviews 服務的請求會發送到 subset 為 v1 的版本中。其他的服務治理能力還包括了故障注入、服務鑒權、服務逾時、熔斷等,可以通過寫入對應的規則來完成,目前Istio也沒有提供非常好使用的白屏化服務治理界面,在 EDAS/MSE 中提供白屏界面操作如服務鑒權、服務查詢、離群摘除、金絲雀釋出等,保證在操作過程中流量不丢失,路由規則的操作需要遵循以下幾個原則:
1、通常使用服務網格服務治理的最佳實踐方式是從一開始就為每一個服務建立具有預設路由的 VirtualService,即當你隻有一個版本的時候,就寫入該版本的 VirtualService 規則,這樣在你部署第二個版本中,不至于流量會打到第二個版本中,需要配置路由規則才可以,保證新版本驗證過程中不會出現由于新版本自身問題導緻的大規模報錯。
2、VirtualService 和 DestinationRule 在使用的過程中,Envoy 會首先檢視 VirtualService 中的路由規則,以決定是否路由到特定的子集去,隻有路由到對應的子集才會激活在 DestinationRule 中對應子集配置的如熔斷、離群摘除等規則,同時可以看出 VirtualService 和DestinationRule 的配置也是有順序的,首先配置 DestinationRule,然後在配置 VirtualService,否則會導緻找不到對應的 Subset 報錯。
3、更新 DestinationRule 添加一個新的 Subset 後,需要等待 DestinationRule 傳播到 Envoy Sidecar,然後再更新對應的 VirtualService。
雙模微服務治理
互通的問題通過對接注冊中心的方式解決了,那異構架構的服務治理則通過 MSE 來支援,MSE 的服務治理中心可以對接 Java 服務,同時也可以支援服務網格的服務。
MSE 在控制面上支援雙模微服務治理,即 Java 服務治理和非 Java 服務治理,控制面對外提供統一的治理模型,我們參考 Istio 的路由規則設計模型,提出一個統一的服務治理規則模型,模型的設計主要考慮到 Dubbo、Spring Cloud 和服務網格治理的通用性。
{
"RegisterConfig":Object{...},
"protocol":"springcloud",
"rule_type":"fault_inject",
"rule":{
"hosts":Array[1],
"rule_policy":[
{
"match":Array[1],
"fault":Object{...},
"route":Array[1],
"Timeout":"10s",
"retries":Object{...},
"mirror":Object{...},
"mirror_percent":100,
"headers":Object{...},
"tls":Object{...}
},
{
"route":[
{
"destination":Object{...},
"weight":"100",
"headers":Object{...}
}
]
}
]
}
}
上述模型中包含了注冊中心、協定、規則類型、路由規則,路由規則中包含了比對的規則和路由的目的地,MSE通過生成對應這樣的CRD來定義不同類型的路由規則,Java Agent 的和服務網格都可以通過監聽這樣的 CRD 來管理自己的流量,後續我們也會在 OAM 中推出這一套微服務治理規則,用于統一服務治理模型。
MSE微服務治理
服務查詢:
标簽路由:
離群執行個體摘除:
可觀測
社群開源方案
可觀測是微服務能力的重要組成部分,服務網格可以跟目前開源的可觀測産品結合,可觀測性上主要圍繞 Metrics、Tracing 和 Logging 來展開,在 Metrics 上提供資料供 Prometheus 采集,在 Tracing上,Istio 支援 Apache SKyWalking、Zipkin、Jaeger 的鍊路追蹤,這三個中間件都支援 OpenTracing 協定,在 Logging 上,對于日志采集元件的要求也越來越高,目前比較流行的方案是使用 Fluentd 或者 Filebeat 替代 Logstash。
阿裡雲 EDAS 方案
阿裡雲 Xtrace 為服務網格提供可觀測能力,包含鍊路追蹤、應用概覽、拓撲、Metrics 統計,在應用釋出後直接可以通過應用詳情檢視,如下圖所示:
拓撲圖如下:
可以通過鍊路追蹤檢視每個請求過程中的問題,協助問題定位,同時 Xtrace 也提供了不同語言的 SDK,接入 SDK 後可以檢視更細粒度的資料。
釘釘掃碼加入阿裡雲 EDAS/MSE 服務網格交流群:
掃碼了解更多技術内容與客戶案例: