基於 Wasm 和 ORAS 簡化擴展服務網格功能

頭圖.png

做者 | 王夕寧  阿里雲高級技術專家
來源 | 阿里巴巴雲原生公衆號c++

本文將介紹如何使用 ORAS 客戶端將具備容許的媒體類型的 Wasm 模塊推送到 ACR 註冊庫(一個 OCI 兼容的註冊庫)中,而後經過 ASM 控制器將 Wasm Filter 部署到指定工做負載對應的 Pod 中。Wasm Filter 部署中的全部步驟都使用聲明方式,也就是說能夠建立一個自定義資源 CRD 來描述 Wasm Filter 的部署。一旦該 CRD 建立以後,ASM 控制器能夠將 Wasm 模塊加載到數據平面層中的相應 Envoy 代理中,同時在控制平面層中也會建立相應的 Istio EnvoyFilter 自定義資源。git

Envoy Filter 介紹

首先回顧一下 EnvoyProxy 的實現機制。Envoy 的核心是一個 L3/L4 網絡代理,並支持 L7 代理,經過提供可插入 filter chain 機制容許開發人員編寫 filter 來執行不一樣的任務,譬如咱們經常使用到的 HTTP connection manager,將原始字節轉換爲 HTTP 級別的消息和事件,還處理全部 HTTP 鏈接和請求共有的功能包括訪問日誌、tracing 等。github

1.png

上圖能夠看到:Downstream 做爲鏈接到 Envoy 併發送請求以及接收響應的客戶端部分, 監聽器 Listener 組件用於綁定到 IP 地址/端口並接收來自 Downstream 下游的鏈接。經過配置 Listener,用戶能夠啓用經過代理的流量管理能力,而後使用多個 Filter 加強數據流,多個 Filter 構成了一個 Filter Chain。能夠看到通過這些 Filter chain 處理以後, 會把請求映射到相應的 Cluster(此處的 Cluster 集羣是指 Envoy 鏈接到的邏輯上相同的一組上游主機,與下文中提交的 Kubernetes 集羣沒有關係),而 Cluster 的做用是負責鏈接到一組上游節點服務, 並使用關聯的負載均衡策略轉發這些請求。docker

根據處理任務的不一樣,Envoy Filter 分爲三類:編程

  • Listener Filter:用於操做處理 L4 鏈接中的元數據。
  • Network Filter:用於操做處理 L4 鏈接中的原始數據。
  • HTTP Filter:用於操做處理 L7 鏈接中的 HTTP 請求與響應。

除了這些 built-in Filter 以外,還能夠開發自定義的 Filter,可以使用 native c++ 編譯方式,或是經過 wasm 技術構建 Filter。json

此外,Envoy 提供了一組 API,也就是咱們常說的 xDS API。經過這些 API,控制平面能夠動態地配置 Envoy 代理。api

2.png

如上圖所示,與進站流量相似,對於出站流量來講,監聽器在配置的地址或者端口進行監聽網絡流量的請求。每一個監聽器一樣會定義一組位於數據路徑中的 Filter,並造成一組過濾器鏈 Filter Chain。經過這樣的一組過濾器,用戶能夠配置 Envoy 來針對出站流量作特定的任務,包括數據協議處理、生成調用的統計信息、執行 RBAC 權限等。跨域

3.png

爲了更好地理解這些 Envoy Filter 以及 Filter Chain,下面來看一個實際的例子。這個就是 Istio 官方示例 bookinfo 中的第一個服務 productpage。首先, productpage pod 中 Envoy Proxy 配置了一個監聽 9080 端口的監聽器,進入這個 pod 的端口 9080 上的流量請求都會被攔截到這個 proxy 中,而後請求就會通過這些 Filter Chain 進行處理。具體以下:安全

  • 第一個 filter 是 envoy.filters.network.metadata_exchange,它的主要做用顧名思義,用來在 filter 之間交換元數據。網絡

  • 第二個 filter: envoy.http_connection_manager,它下面一般會有如下幾個跟 http 特定的 filter,包括:

    • envoy.filters.http.wasm/envoy.wasm.metadata_exchange(用於元數據交互)

    • Istio_authn filter(用於受權認證)

    • envoy.filters.http.cors(處理跨域資源共享的 filter)

    • envoy.filters.http.fault(故障注入過濾器,能夠用來測試微服務架構中容錯能力,用戶能夠自定義錯誤代碼來實現延時注入或者終止請求,在不一樣的失敗場景下提供錯誤處理的能力,例如服務失敗、服務過載、服務高延時等狀況,這個也是較爲經常使用的 filter)

    • envoy.filters.http.wasm/envoy.wasm.stats、envoy.filters.http.wasm/xxx-wasmfilter(用戶自定義的 wasm 實現的filter)

    • envoy.filters.http.router(實現 HTTP 轉發,幾乎全部 HTTP 場景下都會使用到這一過濾器)

備註:能夠經過請求這個 URL 地址獲取配置信息:kubectl exec -it [productpage-xxx] -c istio-proxy curl localhost:15000/config_dump

添加新的 Filter

Envoy 社區已經提供了若干個 Built-in Filters,具體參見:https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/http_filters

在服務網格中,能夠經過 API 啓用這些 Built-in Filter 能力。

若是這些 Built-in Filter 沒法知足需求,還能夠經過自定義 Filter 實現,有如下兩種方式:

  • 靜態預編譯
    • 將其餘過濾器集成到 Envoy 的源代碼中,並編譯新的 Envoy 版本。
    • 這種方法的缺點是您須要維護 Envoy 版本,並不斷使其與官方發行版保持同步。
    • 因爲 Envoy 是用 C++ 實現的,所以新開發的過濾器也必須用 C++ 實現。 
  • 動態運行時加載
    • 在運行時將新的過濾器動態加載到 Envoy 代理中。
    • 爲了簡化擴展 Envoy 的過程, 經過引入 WebAssembly 技術 - 它是一種有效的可移植二進制指令格式,提供了可嵌入和隔離的執行環境。

使用 Wasm 擴展 Envoy Proxy 的優缺點

在實際應用中,會根據如下優缺點來決定是否使用 Wasm 這種方式擴展 Envoy Filter。

Pros

  • 敏捷性:過濾器能夠動態加載到正在運行的 Envoy 進程中,而無需中止或從新編譯。
  • 可維護性:沒必要更改 Envoy 自身基礎代碼庫便可擴展其功能。
  • 多樣性:能夠將流行的編程語言(例如 C/C++ 和 Rust)編譯爲 WASM,所以開發人員能夠選擇實現過濾器的編程語言。
  • 可靠性和隔離性:過濾器會被部署到 VM 沙箱中,所以與 Envoy 進程自己是隔離的;即便當 WASM Filter 出現問題致使崩潰時,它也不會影響 Envoy 進程。
  • 安全性:過濾器經過預約義 API 與 Envoy 代理進行通訊,所以它們能夠訪問並只能修改有限數量的鏈接或請求屬性。

Cons

  • 性能約爲 C++ 編寫的原生靜態編譯的 Filter 的 70%。
  • 因爲須要啓動一個或多個 WASM 虛擬機,所以會消耗必定的內存使用量。
  • The WebAssembly ecosystem is still young。

envoy-wasm 運行機制

以下圖所示,envoy-wasm 運行機制包括如下幾個步驟:

4.png

  • Wasm 二進制代碼須要可以被動態加載進來,不管是經過 local file 方式仍是 xds 遠程獲取方式。
  • 一個 Wasm filter 是否被容許加載,須要一致性校驗:https://github.com/proxy-wasm/spec
  • 一旦被加載以後,Wasm filter 就成爲 filter chain 的一部分,當新的請求進來以後,仍是先進入到原生的 filter,以後進入到 Proxy-Wasm 擴展控制器。
  • Proxy-Wasm 擴展控制器會根據在 filter chain 中定義的 configuration 信息,調用並執行註冊的校驗過的這些 Wasm filter。
  • 內置的 Wasm runtime 支持:LLVM-based WAVM ~20MB, and V8 ~10MB。
  • 事件驅動模型。
  • 兼容 native filter 調用方式。

以下所示,是下發到 Envoy Proxy 側的一個 Wasm Filter 的配置內容。

5.png

以上講述了 Envoy Filter 以及經過 Wasm 擴展的方式,引出了 Wasm filter 機制,這將是將來的主流方式。

在一個服務網格體系中,如何以有效而且簡單的方式來管理 Wasm filter 的部署運行,將是雲產品須要解決的一個問題。

OPAS 及 Wasm filter 註冊庫

在 Cloud Native 生態系統中,如何管理一個 Artifact 文件,相信絕大多數人會想到 oci 規範標準,是否能夠像管理 Docker 鏡像那樣去管理這些 Wasm filter。

ORAS 項目就是用來解決這個問題的,它的全稱爲 OCI Registry As Storage。ORAS 是 OCI Artifacts 項目的參考實現,能夠顯著地簡化 OCI 註冊庫中任意內容的存儲。

使用 ORAS API/SDK Library 能夠構建自定義工具,完成如下功能:

  • 將 WebAssembly 模塊推入到 OCI 註冊庫中。
  • 從 OCI 註冊庫中拉取 WebAssembly 模塊。

oras cli 的使用相似於 docker cli,以下所示:

6.png

以阿里雲容器鏡像服務企業版 ACR EE 爲例,做爲企業級雲原生應用製品管理平臺,已經提供了容器鏡像、Helm Chart 以及符合 OCI 規範的製品的生命週期管理。開通以後,建立一個鏡像倉庫,會分配一個地址,提供了 vpc 和公網兩種方式。

使用 oras login 命令行登陸, 執行如下命令:

oras login --username=<登陸帳號> acree-1-registry.cn-hangzhou.cr.aliyuncs.com

經過oras push命令推送, 執行如下命令:

oras push acree-1-registry.cn-hangzhou.cr.aliyuncs.com/**/asm-test:v0.1 --manifest-config runtime-config.json:application/vnd.module.wasm.config.v1+json  example-filter.wasm:application/vnd.module.wasm.content.layer.v1+wasm

注意參數 --manifest-config,能夠參考 Wasm Artifact 鏡像規範。

Wasm filter 被推送到 ACR EE 註冊庫中以後,能夠查看相關信息,以下:

7.png

阿里雲服務網格 ASM 架構

在阿里雲服務網格 ASM 產品中是如何使用 Wasm 技術呢?首先咱們瞭解一下 ASM 產品的技術架構,以下圖所示。做爲業內首個全託管 Istio 兼容的服務網格產品,ASM 的定位是專一打造全託管、安全、穩定、易用的服務網格,以及支持跨地域多集羣、多雲混合雲服務的統一治理。控制平面的組件託管在阿里雲側,與數據面側的用戶集羣解耦獨立,下降用戶使用的複雜度,用戶只須要專一於業務應用的開發部署。在託管模式下,保持與 Istio 的兼容,支持聲明式的方式定義靈活的路由規則,支持多個 Kubernetes 集羣的統一流量管理。

8.png

服務網格 ASM 做爲鏈接上層應用和下層計算基礎設施的重要環節,能夠分爲 3 個角度來理解:

  • 從向下與基礎設施融合的角度
  • 服務網格自身的能力建設的角度
  • 向上支持應用層以及被集成能力的角度

其中, 從服務網格自身的能力建設來看,ASM 做爲一個託管的服務網格產品,提供了柔性架構,能夠支持不一樣版本的、定製的 Istio 控制面與數據面 Proxy 代理。

  • 在託管側,將控制面核心組件進行改造託管,並負責整個控制面和數據面組件的生命週期管理。在產品能力方面,ASM 在 Mesh CA、安全審計方面作了加強提高網格實例的安全度;把客戶場景的常見問題造成了診斷規則,用戶能夠自行運行診斷分析。 

  • 在作核心託管側的建設以外,ASM 優化整合了阿里雲的多個產品服務,如:在可觀測性方面,整合了 xtrace、arms、日誌服務等;在跨 vpc 網絡打通方面整合了 cen,實現多集羣的互聯互通;在限流方面集成了 AHAS 的限流服務。

  • ASM 還集成擴展了社區開源的組件能力,包括在安全方面的 OPA 安全引擎的支持、spiffe/spire 的支持、envoyfilter 的擴展支持等。因此這一部分須要提供一種簡單有效的方式幫助用戶輕鬆擴展這些能力。

在阿里雲 ASM 中使用 Wasm

隨着新架構的優化,WebAssembly 技術被引入服務網格中,解決代理擴展的問題。這樣一來, ASM 架構就變成了「託管的高可用彈性控制平面 + 可擴展的插件式的數據平面「的模式。

阿里雲服務網格 ASM 產品中提供了對 WebAssembly(WASM)技術的支持,服務網格使用人員能夠把擴展的 WASM Filter 經過 ASM 部署到數據面集羣中相應的 Envoy 代理中。經過 ASMFilterDeployment  Controller 組件,  能夠支持動態加載插件、簡單易用、以及支持熱更新等能力。

9.png

經過這種過濾器擴展機制,能夠輕鬆擴展 Envoy 的功能並將其在服務網格中的應用推向了新的高度。

下面咱們具體來看在 ASM 實例中是怎樣啓用這個能力的?

部署一個 ASM 實例以後,默認該功能是沒有開啓的,用戶須要主動去開啓。例如經過以下 aliyun cli 方式:

aliyun servicemesh UpdateMeshFeature  --ServiceMeshId=xxxxxx --WebAssemblyFilterEnabled=true

開啓該功能以後,ASM 實例會部署相關組件並執行以下任務:

  • 部署一個 DaemonSet(asmwasm-controller) 到 K8s 集羣中。
  • asmwasm-controller 監聽一個 configmap,該 configmap 存放要拉取的 wasm filter 的地址,例如:acree-1-registry.cn-hangzhou.cr.aliyuncs.com/***/sample:v0.1。
  • 若是須要受權認證,該 asmwasm-controller 會根據定義的 pullSecret 值得到相應的 secret 值。
  • 而後,調用 oras API 從註冊庫中動態拉取 Wasm filter。
  • 該 asmwasm-controller 使用 HostPath 方式掛載 volume,因此拉取的 Wasm filter 會落盤到對應的節點上。

啓用了該功能以後,如何開始部署一個 Wasm filter 並掛載到對應 workload 的 Envoy Proxy 中呢?

10.png

阿里雲服務網格 ASM 產品提供了一個新的 CRD ASMFilterDeployment 以及相關的 controller 組件。這個 controller 組件會監聽 ASMFilterDeployment 資源對象的狀況,會作 2 個方面的事情:

  • 建立出用於控制面的 Istio EnvoyFilter Custom Resource,並推送到對應的 asm 控制面 istiod 中。
  • 從 OCI 註冊庫中拉取對應的 wasm filter 鏡像,並掛載到對應的 workload pod 中。

如下是一個 ASMFilterDeployment CR 示例:

apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMFilterDeployment
metadata:
  name: details-v1-wasmfiltersample
spec:
  workload:
    kind: Deployment
    labels:
      app: details
      version: v1
  filter:
    parameters: '{"name":"hello","value":"hello details"}'
    image: 'acree-1-registry.cn-hangzhou.cr.aliyuncs.com/asm/asm-test:v0.1'
    imagePullOptions: 
      pullSecret: 'asmwasm-cache'
    rootID: 'my_root_id'
    id: 'details-v1-wasmfiltersample.default'

生成的 Istio Envoy Filter 資源以下所示:

11.png

其中,match 片斷中定義了 envoy.router 這個 filter、patch 片斷中定義了 INSERT_BEFORE 操做,插入一個 Wasm filter,以下:

12.png

掛載了 Wasm filter 的工做負載定義更新後以下,其中以 hostpath 方式掛載 Wasm filter 文件到 Proxy 容器中:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
.…
spec:
   ….
   template:
      metadata:
          annotations:
              sidecar.istio.io/userVolume: '[{"name":"wasmfilters-dir","hostPath":{"path":"/var/local/lib/wasm-filters"}}]’
              sidecar.istio.io/userVolumeMount: '[{"mountPath":"/var/local/lib/wasm-filters","name":"wasmfilters-dir"}]'

確認 Wasm filter 是否生效。登陸到 productpage Pod 的 istio-proxy 容器中,執行如下命令,將一些流量發送到 details 服務上。在響應中,能夠看到過濾器的頭添加到響應頭中。

kubectl exec -ti  deploy/productpage-v1 -c istio-proxy -- curl -v http://details:9080/details/123
*   Trying 172.21.9.191...
* TCP_NODELAY set
* Connected to details (172.21.9.191) port 9080 (#0)
> GET /details/123 HTTP/1.1
> Host: details:9080
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
xxxxxxx
< resp-header-demo: added by our filter
xxxxx
* Connection #0 to host details left intact
xxxxx

總結

在開發階段:

按照以下流程,使用適當的 wasm sdk/編程語言,建立編譯出一個 wasm 二進制文件,經過使用 oras cli 上傳到 oci 鏡像倉庫中。

13.png

在部署運行階段:

首先確認已經在 ASM 中開啓 Wasm 支持能力,而後建立一個 ASMFilterDeployment 自定義資源,注意這個 CR 是在服務網格 ASM 實例對應的 apiserver 中建立。一旦建立,相應的 crd controller 會監聽同步相應的資源,一方面生成一個 Istio EnvoyFilter CR 併發送到 ASM 實例的控制面 apiserver 中,用戶能夠查看生成的這個 Istio Envoyfilter CR 是否知足指望。

14.png

另外一方面,確認 Workload 部署變動生效,包括:

  • 能夠登陸到 proxy container 進行查看 Wasm filter 是否掛載成功。
  • 經過調整 wasm log level 來打印相關信息。

做爲業內首個全託管 Istio 兼容的服務網格產品,阿里雲服務網格(簡稱 ASM)是一個統一管理微服務應用流量、兼容 Istio 的託管式平臺,專一打造全託管、安全、穩定、易用的服務網格,支持跨地域多集羣、多雲混合雲服務的統一治理。經過流量控制、網格觀測以及服務間通訊安全等功能,服務網格 ASM 能夠全方位地簡化您的服務治理,併爲運行在異構計算基礎設施上的服務提供統一的管理能力,適用於 Kubernetes 集羣、Serverless Kubernetes 集羣、ECS 虛擬機以及自建集羣。

歡迎登陸到阿里雲服務網格 ASM 產品官網進行體驗!

做者簡介

王夕寧  阿里雲高級技術專家,阿里雲服務網格 ASM 技術負責人,專一於 Kubernetes、服務網格以及其餘雲原生領域。以前曾在 IBM 中國開發中心工做,曾擔任專利技術評審委員會主席,做爲架構師和主要開發人員負責或參與了一系列在 SOA 中間件、雲計算等領域的工做,擁有 50 多項相關領域的國際技術專利。曾在多個技術大會如 Kubecon、ArchSummit、雲棲大會等參與技術分享。編寫《服務網格技術解析與實踐》並在多個技術社區發佈文章若干。

相關文章
相關標籤/搜索