試駕 Open Service Mesh

上周微軟發(fā)布了全新的服務網(wǎng)格(Service Mesh)輕量級解決方案:Open Service Mesh(簡稱 OSM),OSM 是 Service Mesh Interface(SMI)規(guī)范的一個實現(xiàn),同樣使用 Envoy 作為 sidecar 代理。對于一些初學者來說,這些概念可能比較陌生,下面我們從頭開始來介紹下服務網(wǎng)格。
什么是服務網(wǎng)格?
我記得第一次聽說服務網(wǎng)格的時候,是在一個”Introduction to Istio and onto 1.0“ 的 meetup 上,來自 Google 的 Dan Curuli 介紹了Istio 和它所解決的問題,從那以后服務網(wǎng)格和 Istio 越來越受歡迎。
那么什么是服務網(wǎng)格呢?服務網(wǎng)格是一種基礎設施組件,有助于管理服務間的通信。換句話說,它是一種透明的技術,它將服務間通信的某些邏輯從你的應用代碼中剝離出來,轉(zhuǎn)移到了服務網(wǎng)格中。一個很好的例子就是我們調(diào)用 API 時的重試邏輯,如果沒有服務網(wǎng)格,我們就必須把這些邏輯寫到應用代碼中去,但是有了服務網(wǎng)格過后,我們就可以將重試邏輯轉(zhuǎn)移到網(wǎng)格中來,利用網(wǎng)格中的重試策略來實現(xiàn)這個功能(參考 Istio 中的示例)。
服務網(wǎng)格通常使用在 Kubernetes 環(huán)境下,雖然也可以在非 Kubernetes 環(huán)境中使用。在 Kubernetes 集群中,服務網(wǎng)格通常使用 sidecar 模式來實現(xiàn),sidecar 是一個伴生容器,被添加到應用程序的 Pod 中去,以實現(xiàn)服務網(wǎng)格中的額外功能。

這個 sidecar 容器可以是很多種容器,不過作為 sidecar 使用 Envoy 是一個非常流行的代理,Istio 就是使用的這個 sidecar(OSM 也是使用的 Envoy)。Envoy 最初是由 Lyft 開發(fā)的代理工具,在功能上與 Nginx 或者 HAProxy 比較類似,但是 Envoy 有一些明顯的優(yōu)勢,包括高性能處理和集中式配置管理系統(tǒng)。當然 Envoy 并不是唯一可以使用的 sidecar,你也可以使用 Nginx,通常情況下,每個服務網(wǎng)格都會有一個默認的 sidecar 代理。
目前最流行的服務網(wǎng)格實現(xiàn)要數(shù) Istio 了,Istio 最初是由 Google、IBM 和 Lyft 共同創(chuàng)建的項目,雖然它是目前最流行的服務網(wǎng)格,但是最近在開源社區(qū)也引起了一些小騷動,因為 Google 將 Istio 捐獻給了一個新的基金會:Open Usage Commons,而不是將 Istio 捐獻給 CNCF 基金會。當然 Istio 也不是唯一的服務網(wǎng)格,其他流行的網(wǎng)格包括 Linkerd、Consul、Maesh 等。
服務網(wǎng)格領域目前仍然還處于早期階段,每種服務網(wǎng)格都有自己的優(yōu)勢和劣勢。但是從一個網(wǎng)格切換到另一個網(wǎng)格并不是很直接,有一定成本,這是因為每個網(wǎng)格都有自己的配置語言語法,這就是 SMI 規(guī)范視圖解決的問題。
SMI 規(guī)范
Serivce Mesh Interface(SMI)規(guī)范是運行在 Kubernetes 上的服務網(wǎng)格的標準接口。如果你熟悉 Kubernetes 中的 Ingress 資源,SMI 對于服務網(wǎng)格,就類似于 Ingress 對于反向代理,它是一種配置多個后端實現(xiàn)的標準化方式。這樣做的好處是,你不必學習特定實現(xiàn)的具體內(nèi)容,就可以簡單使用 SMI 規(guī)范來配置你的服務網(wǎng)格了。
微軟最初在2019年5月創(chuàng)建了 SMI 規(guī)范,并在2020年4月將該規(guī)范捐獻給了 CNCF 基金會。到目前為止,已經(jīng)有4個服務網(wǎng)格實現(xiàn)了 SMI 規(guī)范:
Istio ( 通過適配器 )
Linkerd
Consul Connect ( 通過適配器 )
Maesh
當然現(xiàn)在又有一個新的服務網(wǎng)格實現(xiàn)實現(xiàn)了 SMI 規(guī)范,那就是 OSM。
Open Service Mesh
Open Service Mesh(OSM)是一個新的服務網(wǎng)格,同樣使用 Envoy 作為 sidecar 代理,并使用 SMI 規(guī)范進行配置。雖然這個服務網(wǎng)格才剛剛推出,但是已經(jīng)實現(xiàn)了一些功能(摘自 OSM 官網(wǎng):https://openservicemesh.io/):
輕松、透明地配置應用的流量移動
通過啟用 mTLS 確保端到端服務間的通信安全
定義并執(zhí)行精細的服務訪問控制策略
可觀測性和應用指標,用于服務調(diào)試和監(jiān)控
通過可插拔的接口與外部證書管理服務/解決方案集成
可以啟用自動注入 Envoy sidecar 代理,將應用程序納入到網(wǎng)格
足夠靈活,可以通過 SMI 和 Envoy XDS API 來處理簡單和復雜的各種場景
接下來我們就去 Kubernetes 集群中來安裝體驗下 OSM。
使用 OSM
我將在 Azure 中的現(xiàn)有集群上安裝 OSM,OSM 需要一個 v1.15.0 版本或以上的 Kubernetes 集群。

然后下載 OSM 二進制文件,這里我們下載 GitHub 上的最新版本 v0.2.0:
wget https://github.com/openservicemesh/osm/releases/download/v0.2.0/osm-v0.2.0-linux-amd64.tar.gztar -xvzf osm-v0.2.0-linux-amd64.tar.gzsudo mv linux-amd64/osm /usr/local/bin/osmrm -rf linux-amd64
然后直接執(zhí)行 osm install 命令安裝 OSM 即可,安裝結(jié)果如下圖所示:

當安裝完 OSM 過后,我們就可以來探索下如何使用了~
OSM 演示應用程序
基本設置
OSM 團隊為我們提供了一個非常友好的完整演示應用程序,這里我們將創(chuàng)建幾個 namespace 并部署幾個應用。

首先將 OSM 的代碼倉庫 Clone 到本地:
git clone https://github.com/openservicemesh/osm.gitcd osm
接下來我們創(chuàng)建4個 namespace,并將這4個 namespace 加入到 OSM 中:
for i in bookstore bookbuyer bookthief bookwarehouse; do kubectl create ns $i; donefor i in bookstore bookbuyer bookthief bookwarehouse; do osm namespace add $i; done
然后部署4個應用程序,它們的配置在目錄 docs/example/manifests/apps/ 中:

我們可以看到有4個應用的 YAML 資源清單文件,還有一個 traffic-split.yaml 的文件,這個文件中就包含了服務網(wǎng)格的配置,文件內(nèi)容如下所示:
apiVersion: split.smi-spec.io/v1alpha2kind: TrafficSplitmetadata:name: bookstore-splitnamespace: bookstorespec:service: bookstore.bookstore #. backends:service: bookstore-v1weight: 100
這就是 SMI 配置,并沒有 OSM 的特殊配置,因為 OSM 是遵循 SMI 規(guī)范的,我們直接部署這個示例應用,看看會發(fā)生什么。
kubectl create -f docs/example/manifests/apps/
可以看到會部署一堆資源對象,部署完成后我們可以通過設置端口轉(zhuǎn)發(fā)來查看應用程序:
cp .env.example .env./scripts/port-forward-all.sh
這會在本地開啟如下幾個端點綁定在應用程序上:
http://localhost:8080?–?Bookbuyer
http://localhost:8081?–?bookstore-v1
http://localhost:8083?–?bookthief
可以默認訪問服務的樣子如下所示:

允許請求
正常情況下,如果服務之間能夠互相通信,我們就可以看到頁面上的計數(shù)器會增加。但是現(xiàn)在這三個服務之間不允許有任何流量,意味著沒有 book 會被 buy 或者 stolen,我們可以通過應用訪問控制策略來修改。在上面?zhèn)}庫代碼的 docs/example/manifests/access/ 目錄下面就有一個策略文件,內(nèi)容如下所示:
kind: TrafficTargetapiVersion: access.smi-spec.io/v1alpha2metadata:name: bookstore-v1namespace: bookstorespec:destination:kind: ServiceAccountname: bookstore-v1namespace: bookstorerules:kind: HTTPRouteGroupname: bookstore-service-routesmatches:buy-a-bookbooks-boughtsources:kind: ServiceAccountname: bookbuyernamespace: bookbuyer#- kind: ServiceAccount#name: bookthief#namespace: bookthief---apiVersion: specs.smi-spec.io/v1alpha3kind: HTTPRouteGroupmetadata:name: bookstore-service-routesnamespace: bookstorespec:matches:name: books-boughtpathRegex: /books-boughtmethods:GETheaders:host: "bookstore.bookstore""user-agent": ".*-http-client/*.*""client-app": "bookbuyer"name: buy-a-bookpathRegex: ".*a-book.*new"methods:GETheaders:host: "bookstore.bookstore"
首先,bookthief 這個 ServiceAccount 被注釋掉了,意味著這個 sa 下面的應用不能訪問其他服務
然后,可以看到我們創(chuàng)建了兩個對象:
TrafficTarget與HTTPRouteGroup。HTTPRouteGroup用于描述 HTTP/1 和 HTTP/2 的流量,它枚舉了可以通過應用程序進行服務的路由。TrafficTarget將一組流量定義(規(guī)則)與服務關聯(lián)起來,服務和一組 Pods 進行關聯(lián)。在我們這個示例,可以看到:
現(xiàn)在的源只是 bookbuyer 這個 ServiceAccount,而不是 thief(被注釋掉了)。
我們創(chuàng)建了一個通往目標 bookstore-v1 的
TrafficGroup匹配了兩個HTTPRouteGroup。
下面我們直接創(chuàng)建 HTTPRouteGroups 來查看流量請求:
kubectl create -f docs/example/manifests/access/一旦創(chuàng)建了訪問策略,我們就會看到計數(shù)器遞增,這意味著書籍正在被買進或賣出,但沒有被盜。

接下來我們啟用 book thief,將上面文件docs/example/manifests/access/traffic-access.yaml 中的注釋取消掉:
kind: TrafficTargetapiVersion: access.smi-spec.io/v1alpha2metadata:name: bookstore-v1namespace: bookstorespec:destination:kind: ServiceAccountname: bookstore-v1namespace: bookstorerules:kind: HTTPRouteGroupname: bookstore-service-routesmatches:buy-a-bookbooks-boughtsources:kind: ServiceAccountname: bookbuyernamespace: bookbuyerkind: ServiceAccountname: bookthiefnamespace: bookthief
重新更新我們的資源清單:
kubectl apply -f docs/example/manifests/access/traffic-access.yaml
現(xiàn)在我們再去訪問我們的應用,就可以看到在 ?bookthief 中也有變化了。

我們來快速回顧下上面我們做的事情:
在集群中安裝了 OSM
創(chuàng)建了4個命名空間,并將這些命名空間加入到 OSM 網(wǎng)格中
創(chuàng)建了一個應用程序,看到流量默認被阻止
使用
TrafficTarget和HTTPRouteGroup對象創(chuàng)建了一個流量策略,以允許特定的流量在我們的網(wǎng)格中流動
下面我們將創(chuàng)建一個新版本的 bookstore(bookstore-v2),我們將能夠?qū)⒘髁繌囊粋€服務引導到另一個服務。
流量分流
在本節(jié)中,我們將部署一個新版本的 bookstore,然后慢慢將所有流量導向它,首先,讓我們部署第二版本的 bookstore:
kubectl apply -f docs/example/manifests/bookstore-v2/在我們進行端口轉(zhuǎn)發(fā)的終端窗口中,我們需要停掉腳本,然后再次啟動該腳本,就可以轉(zhuǎn)發(fā)到第二版本的 bookstore 應用了。
當我們訪問應用的時候可以看到計數(shù)器增加了,但是第二家書店沒有賣出任何副本,這是因為 TrafficSplit 被配置為將 100% 的流量導入到了主要的書店。我們可以通過檢查該對象來驗證這一點。
kubectl get trafficsplit bookstore-split -n bookstore
我們可以通過部署 docs/example/manifests/split-v2/traffic-split-v2.yaml 文件將流量重定向到 v2 版本的書店,我們先來查看該文件的內(nèi)容。
apiVersion: split.smi-spec.io/v1alpha2kind: TrafficSplitmetadata:name: bookstore-splitnamespace: bookstorespec:service: bookstore.bookstore #. backends:service: bookstore-v1weight: 0service: bookstore-v2weight: 100
我們可以看到上面定義將100%的流量重定向到了 v2,我們直接應用上面的對象:
kubectl apply -f docs/example/manifests/split-v2/traffic-split-v2.yaml然后我們再去訪問應用可以發(fā)現(xiàn)只有 v2 版本的書店計數(shù)器在增加了:

我們也可以按照權重來拆分流量,比如 50/50 拆分,直接修改上面的資源對象:
kubectl?edit?trafficsplit?bookstore-split?-n?bookstore
編輯后,現(xiàn)在我們可以看到兩個版本的書店的計數(shù)器都在增加了,而且增長的速度差不多。

同樣我們來回顧下這里我們做了些什么操作:
新建了一個新版本的 bookstore 應用
先把 100% 的流量發(fā)送到新書店,只能看到 bookstore-v2 應用有流量
然后我們做了 50/50% 的流量拆分,我們看到兩個 bookstores 應用都收到了比例大致相等的流量。
最后,我們來看看 OSM 內(nèi)置的一些監(jiān)控。
流量監(jiān)控
OSM 預安裝了 Prometheus、Grafana 和 Zipkin,這些工具允許我們創(chuàng)建關于應用的流量圖表(prometheus/grafana)和進行分布式追蹤(Zipkin)。
要訪問 Grafana,我們可以在瀏覽器中打開 localhost:3000,默認使用 admin/admin 進行登錄,在Grafna 中,打開 dashboard 的管理視圖:

我們來看下服務到服務的數(shù)據(jù)平面指標數(shù)據(jù):

同樣我們可以配置這個 dashboard,讓我們看到不同系統(tǒng)/服務之間的流量。如果我們將其配置為監(jiān)控 bookbuyer 和 bookstore-v1 之間的流量,我們就會清楚地看到哪里有 100% 的流量,哪里有 50% 的流量。此外,這個默認的 dashboard 還向我們展示了請求延遲和其他的一些指標,同樣我們也可以自由配置自己的相關指標。

我們可以清楚地看到流量從 buyer 到 bookstore-v1 的轉(zhuǎn)變,先是 100%,然后是 0%,然后是 50%。
關于 OSM 更多高級的用法可以去官方文檔(https://openservicemesh.io/)上了解更多信息。
?
原文鏈接:https://blog.nillsf.com/index.php/2020/08/11/taking-the-open-service-mesh-for-a-test-drive/
K8S進階訓練營,點擊下方圖片了解詳情

