
作者 | 王夕甯 阿裡雲進階技術專家
來源 |
阿裡巴巴雲原生公衆号本文将介紹如何使用 ORAS 用戶端将具有允許的媒體類型的 Wasm 子產品推送到 ACR 注冊庫(一個 OCI 相容的注冊庫)中,然後通過 ASM 控制器将 Wasm Filter 部署到指定工作負載對應的 Pod 中。Wasm Filter 部署中的所有步驟都使用聲明方式,也就是說可以建立一個自定義資源 CRD 來描述 Wasm Filter 的部署。一旦該 CRD 建立之後,ASM 控制器可以将 Wasm 子產品加載到資料平面層中的相應 Envoy 代理中,同時在控制平面層中也會建立相應的 Istio EnvoyFilter 自定義資源。
Envoy Filter 介紹
首先回顧一下 EnvoyProxy 的實作機制。Envoy 的核心是一個 L3/L4 網絡代理,并支援 L7 代理,通過提供可插入 filter chain 機制允許開發人員編寫 filter 來執行不同的任務,譬如我們常用到的 HTTP connection manager,将原始位元組轉換為 HTTP 級别的消息和事件,還處理所有 HTTP 連接配接和請求共有的功能包括通路日志、tracing 等。
上圖可以看到:Downstream 作為連接配接到 Envoy 并發送請求以及接收響應的用戶端部分, 監聽器 Listener 元件用于綁定到 IP 位址/端口并接收來自 Downstream 下遊的連接配接。通過配置 Listener,使用者可以啟用通過代理的流量管理能力,然後使用多個 Filter 增強資料流,多個 Filter 構成了一個 Filter Chain。可以看到經過這些 Filter chain 處理之後, 會把請求映射到相應的 Cluster(此處的 Cluster 叢集是指 Envoy 連接配接到的邏輯上相同的一組上遊主機,與下文中送出的 Kubernetes 叢集沒有關系),而 Cluster 的作用是負責連接配接到一組上遊節點服務, 并使用關聯的負載均衡政策轉發這些請求。
根據處理任務的不同,Envoy Filter 分為三類:
- Listener Filter:用于操作處理 L4 連接配接中的中繼資料。
- Network Filter:用于操作處理 L4 連接配接中的原始資料。
- HTTP Filter:用于操作處理 L7 連接配接中的 HTTP 請求與響應。
除了這些 built-in Filter 之外,還可以開發自定義的 Filter,可使用 native c++ 編譯方式,或是通過 wasm 技術建構 Filter。
此外,Envoy 提供了一組 API,也就是我們常說的 xDS API。通過這些 API,控制平面可以動态地配置 Envoy 代理。
如上圖所示,與進站流量類似,對于出站流量來說,監聽器在配置的位址或者端口進行監聽網絡流量的請求。每個監聽器同樣會定義一組位于資料路徑中的 Filter,并形成一組過濾器鍊 Filter Chain。通過這樣的一組過濾器,使用者可以配置 Envoy 來針對出站流量做特定的任務,包括資料協定處理、生成調用的統計資訊、執行 RBAC 權限等。
為了更好地了解這些 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 運作機制包括以下幾個步驟:
- 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 的配置内容。
以上講述了 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,如下所示:
以阿裡雲容器鏡像服務企業版 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 注冊庫中之後,可以檢視相關資訊,如下:
阿裡雲服務網格 ASM 架構
在阿裡雲服務網格 ASM 産品中是如何使用 Wasm 技術呢?首先我們了解一下 ASM 産品的技術架構,如下圖所示。作為業内首個全托管 Istio 相容的服務網格産品,ASM 的定位是專注打造全托管、安全、穩定、易用的服務網格,以及支援跨地域多叢集、多雲混合雲服務的統一治理。控制平面的元件托管在阿裡雲側,與資料面側的使用者叢集解耦獨立,降低使用者使用的複雜度,使用者隻需要專注于業務應用的開發部署。在托管模式下,保持與 Istio 的相容,支援聲明式的方式定義靈活的路由規則,支援多個 Kubernetes 叢集的統一流量管理。
服務網格 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 元件, 可以支援動态加載插件、簡單易用、以及支援熱更新等能力。
通過這種過濾器擴充機制,可以輕松擴充 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 中呢?
阿裡雲服務網格 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 資源如下所示:
其中,match 片段中定義了 envoy.router 這個 filter、patch 片段中定義了 INSERT_BEFORE 操作,插入一個 Wasm filter,如下:
挂載了 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 鏡像倉庫中。
在部署運作階段:
首先确認已經在 ASM 中開啟 Wasm 支援能力,然後建立一個 ASMFilterDeployment 自定義資源,注意這個 CR 是在服務網格 ASM 執行個體對應的 apiserver 中建立。一旦建立,相應的 crd controller 會監聽同步相應的資源,一方面生成一個 Istio EnvoyFilter CR 并發送到 ASM 執行個體的控制面 apiserver 中,使用者可以檢視生成的這個 Istio Envoyfilter CR 是否滿足期望。
另一方面,确認 Workload 部署變更生效,包括:
- 可以登入到 proxy container 進行檢視 Wasm filter 是否挂載成功。
- 通過調整 wasm log level 來列印相關資訊。
作為業内首個全托管 Istio 相容的服務網格産品,阿裡雲服務網格(簡稱 ASM)是一個統一管理微服務應用流量、相容 Istio 的托管式平台,專注打造全托管、安全、穩定、易用的服務網格,支援跨地域多叢集、多雲混合雲服務的統一治理。通過流量控制、網格觀測以及服務間通信安全等功能,服務網格 ASM 可以全方位地簡化您的服務治理,并為運作在異構計算基礎設施上的服務提供統一的管理能力,适用于 Kubernetes 叢集、Serverless Kubernetes 叢集、ECS 虛拟機以及自建叢集。
歡迎登入到
阿裡雲服務網格 ASM 産品官網進行體驗!
作者簡介
王夕甯 阿裡雲進階技術專家,阿裡雲服務網格 ASM 技術負責人,專注于 Kubernetes、服務網格以及其他雲原生領域。之前曾在 IBM 中國開發中心工作,曾擔任專利技術評審委員會主席,作為架構師和主要開發人員負責或參與了一系列在 SOA 中間件、雲計算等領域的工作,擁有 50 多項相關領域的國際技術專利。曾在多個技術大會如 Kubecon、ArchSummit、雲栖大會等參與技術分享。編寫《服務網格技術解析與實踐》并在多個技術社群釋出文章若幹。