精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

使用 WebAssembly 對 Istio 進行擴展

開發 前端
對于 Istio 來說,WebAssembly 也使得 Istio 的擴展能力得到了極大的提升,Isstio 從 1.12 版本開始引入 WASM 擴展 Envoy,當你需要添加 Envoy 或 Istio 不支持的自定義功能時,那么我們就可以使用 Wasm 插件,比如使用 Wasm 插件來添加自定義驗證、認證、日志或管理配額等等。

WebAssembly(簡稱為 Wasm)的誕生源自前端,是一種為了解決日益復雜的 Web 前端應用以及有限的 JavaScript 性能而誕生的技術。它本身并不是一種語言,而是一種字節碼標準。WASM 字節碼和機器碼非常接近,因此可以非??焖俚难b載運行。任何一種語言,都可以被編譯成 WASM 字節碼,然后在 WASM 虛擬機中執行,理論上,所有語言,包括 JavaScript、C、C++、Rust、Go、Java 等都可以編譯成 WASM 字節碼并在 WASM 虛擬機中執行。當然不僅可以嵌入瀏覽器增強 Web 應用,也可以應用于其他的場景。

WebAssembly

WebAssembly 是為下列目標而生的:

  • 快速、高效、可移植 —— 通過利用常見的硬件能力,WebAssembly 代碼在不同平臺上能夠以接近本地速度運行。
  • 可讀、可調試 —— WebAssembly 是一門低階語言,但是它也有一種人類可讀的文本格式,這允許通過手工來寫代碼,看代碼以及調試代碼。
  • 保持安全 —— WebAssembly 被限制運行在一個安全的沙箱執行環境中。像其他網絡代碼一樣,它遵循瀏覽器的同源策略和授權策略。
  • 不破壞網絡 —— WebAssembly 的設計原則是與其他網絡技術和諧共處并保持向后兼容。

Istio WASM

對于 Istio 來說,WebAssembly 也使得 Istio 的擴展能力得到了極大的提升,Isstio 從 1.12 版本開始引入 WASM 擴展 Envoy,當你需要添加 Envoy 或 Istio 不支持的自定義功能時,那么我們就可以使用 Wasm 插件,比如使用 Wasm 插件來添加自定義驗證、認證、日志或管理配額等等。

Envoy 架構

首先我們再回顧下 Envoy 的過濾機制,Envoy 通過過濾器來實現各種功能,比如路由、負載均衡、TLS、認證、日志、監控等等。Envoy 提供了進程外架構、支持 L3/L4 filter、HTTP L7 filter,過濾器包括偵聽器過濾器(Listener Filters)、網絡過濾器(Network Filters)、HTTP 過濾器(HTTP Filters)三種類型。

偵聽器過濾器

偵聽器過濾器在初始連接階段訪問原始數據并操作 L4 連接的元數據。例如,TLS 檢查器過濾器標識連接是否經過 TLS 加密,并解析與該連接關聯的 TLS 元數據;HTTP Inspector Filter 檢測應用協議是否是 HTTP,如果是的話,再進一步檢測 HTTP 協議類型 (HTTP/1.x or HTTP/2) ,這兩種過濾器解析到的元數據都可以和 FilterChainMatch 結合使用。

網絡過濾器

網絡過濾器訪問和操作 L4 連接上的原始數據,即 TCP 數據包。例如,TCP 代理過濾器將客戶端連接數據路由到上游主機,它還可以生成連接統計數據。此外,MySQL proxy、Redis proxy、Dubbo proxy、Thrift proxy 等都屬于網絡過濾器。

HTTP 過濾器

HTTP 過濾器在 L7 上運行,由網絡過濾器(即 HTTP 連接管理器,HTTP Connection Manager)創建。這些過濾器用于訪問、操作 HTTP 請求和響應,例如,gRPC-JSON 轉碼器過濾器可以為 gRPC 后端提供一個 REST API,并將請求和響應轉換為相應的格式。此外,還包括 JWT、Router、RBAC 等多種過濾器。

WASM 插件

有很多編程語言都支持編寫 WASM 插件,比如 C、C++、Rust、Go、Java 等等,這里我們以 Go 語言為例來編寫一個簡單的 WASM 插件,編寫 WASM 的工具有 Solo.io 團隊的 wasme、tinygo等,目前應用比較多是 tinygo,tinygo 支持的包可以查看 https://tinygo.org/docs/reference/lang-support/stdlib/ 進行了解。

TinyGo 是 Go 編程語言規范的一個編譯器實現,為什么不使用官方的 Go 編譯器?目前官方編譯器無法生成可以在瀏覽器外部運行的 WASM 二進制文件,因此也無法生成與 Proxy-Wasm 兼容的二進制文件。

Proxy-Wasm

Proxy-Wasm是開源社區針對「網絡代理場景」設計的一套 ABI 規范,定義了網絡代理和運行在網絡代理內部的 Wasm 虛擬機之間的接口,屬于當前的事實規范。當前支持該規范的網絡代理軟件包括 Envoy、MOSN 和 ATS(Apache Traffic Server),支持該規范的 Wasm 擴展 SDK 包括 C++、Rust 和 Go。采用該規范的好處在于能讓 Wasm 擴展程序在不同的網絡代理產品上運行,比如 MOSN 的 Wasm 擴展程序可以運行在 Envoy 上,而 Envoy 的 Wasm 擴展程序也可以運行在 MOSN 上。

Proxy-Wasm 規范定義了宿主機與 Wasm 擴展程序之間的交互細節,包括 API 列表、函數調用規范以及數據傳輸規范這幾個方面。其中,API 列表包含了 L4/L7、property、metrics、日志等方面的擴展點,涵蓋了網絡代理場景下所需的大部分交互點。目前實現該規范的 Wasm 擴展 SDK 包括 AssemblyScript、C++、Rust 和 Go:

  • AssemblyScript SDK
  • C++ SDK
  • Go (TinyGo) SDK
  • Rust SDK

為了方便,我們也直接選擇已有的 proxy-wasm-go-sdk 這個 SDK 進行開發。這個 Proxy-Wasm Go SDK 是用于使用 Go 編程語言在 Proxy-Wasm ABI 規范之上擴展網絡代理(例如 Envoyproxy)的 SDK,有了這個 SDK,每個人都可以輕松地生成與 Proxy-Wasm 規范兼容的 Wasm 二進制文件,而無需了解低級且對于沒有專業知識的人來說難以理解的 Proxy-Wasm ABI 規范。

環境準備

首先安裝 tinygo 工具,前往 https://github.com/tinygo-org/tinygo/releases/tag/v0.30.0 下載對應的版本,比如我們這里是 Linux 系統,可以使用下面的命令進行安裝:

# linux
$ wget https://github.com/tinygo-org/tinygo/releases/download/v0.30.0/tinygo0.30.0.linux-amd64.tar.gz
$ tar -xvf tinygo0.30.0.linux-amd64.tar.gz
$ export PATH=$PATH:~/tinygo/bin
$ tinygo version
tinygo version 0.30.0 linux/amd64 (using go version go1.17 and LLVM version 16.0.1)

當然我們也可以直接使用 docker 鏡像來進行編譯。

編寫插件

接下來我們就可以來編寫一個 WASM 插件,這里我們將包含一個 Envoy 過濾器,將來自 http://service/banana/X 的請求重定向到 http://service/status/X,這里我們使用 Go 語言來編寫插件,首先初始化項目:

$ mkdir wasm-go-demo && cd wasm-go-demo
$ go mod init github.com/cnych/wasm-go-demo
$ go get github.com/tetratelabs/proxy-wasm-go-sdk

然后創建 main.go 文件,內容如下:

package main

import (
 "regexp"

 "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
 "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
)

type vmContext struct {
 // 嵌入默認的 VM 上下文,這樣我們就不需要重新實現所有方法
 types.DefaultVMContext
}

func (ctx *vmContext) NewPluginContext(contextID uint32) types.PluginContext {
 return &pluginContext{}
}

type pluginContext struct {
 // 嵌入默認的插件上下文,這樣我們就不需要重新實現所有方法
 types.DefaultPluginContext

 pattern     string
 replaceWith string
 configData  string // 保存插件的一些配置信息
}

// 注入額外的 Header
var additionalHeaders = map[string]string{
 "who-am-i":    "go-wasm-demo",
 "injected-by": "istio-api!",
 "site":        "youdianzhishi.com",
 "author":      "陽明",
 // 定義自定義的header,每個返回中都添加以上header
}

// NewHttpContext 為每個 HTTP 請求創建一個新的上下文。
func (ctx *pluginContext) NewHttpContext(contextID uint32) types.HttpContext {
 return &httpRegex{
  contextID:     contextID,
  pluginContext: ctx,
 }
}

// OnPluginStart 在插件被加載時調用。
func (ctx *pluginContext) OnPluginStart(pluginCfgSize int) types.OnPluginStartStatus {
 proxywasm.LogWarnf("regex/main.go OnPluginStart()")
 // 獲取插件配置
 data, err := proxywasm.GetPluginConfiguration()
 if data == nil {
  return types.OnPluginStartStatusOK
 }
 if err != nil {
  proxywasm.LogWarnf("failed read plug-in config: %v", err)
  return types.OnPluginStartStatusFailed
 }

 proxywasm.LogWarnf("read plug-in config: %s\n", string(data))

 // 插件啟動的時候讀取配置
 ctx.configData = string(data)
 ctx.pattern = "banana/([0-9]*)"
 ctx.replaceWith = "status/$1"

 return types.OnPluginStartStatusOK
}

// OnPluginDone 在插件被卸載時調用。
func (ctx *pluginContext) OnPluginDone() bool {
 proxywasm.LogWarnf("regex/main.go OnPluginDone()")
 return true
}

type httpRegex struct {
 // 嵌入默認的 HTTP 上下文,這樣我們就不需要重新實現所有方法
 types.DefaultHttpContext
 // contextID 是插件上下文的 ID,它是唯一的。
 contextID     uint32
 pluginContext *pluginContext
}

// OnHttpResponseHeaders 在收到 HTTP 響應頭時調用。
func (ctx *httpRegex) OnHttpResponseHeaders(numHeaders int, endOfStream bool) types.Action {
 proxywasm.LogWarnf("%d httpRegex.OnHttpResponseHeaders(%d, %t)", ctx.contextID, numHeaders, endOfStream)

 // 添加 Header
 for k, v := range additionalHeaders {
  if err := proxywasm.AddHttpResponseHeader(k, v); err != nil {
   proxywasm.LogWarnf("failed to add response header %s: %v", k, err)
  }
 }

 //為了便于演示觀察,將配置信息也加到返回頭里
 proxywasm.AddHttpResponseHeader("configData", ctx.pluginContext.configData)
 return types.ActionContinue
}

// OnHttpRequestHeaders 在收到 HTTP 請求頭時調用。
func (ctx *httpRegex) OnHttpRequestHeaders(numHeaders int, endOfStream bool) types.Action {
 proxywasm.LogWarnf("%d httpRegex.OnHttpRequestHeaders(%d, %t)", ctx.contextID, numHeaders, endOfStream)

 re := regexp.MustCompile(ctx.pluginContext.pattern)
 replaceWith := ctx.pluginContext.replaceWith

 s, err := proxywasm.GetHttpRequestHeader(":path")
 if err != nil {
  proxywasm.LogWarnf("Could not get request header: %v", err)
 } else {
  result := re.ReplaceAllString(s, replaceWith)
  proxywasm.LogWarnf("path: %s, result: %s", s, result)

  err = proxywasm.ReplaceHttpRequestHeader(":path", result)
  if err != nil {
   proxywasm.LogWarnf("Could not set request header to %q: %v", result, err)
  }
 }

 return types.ActionContinue
}

func (ctx *httpRegex) OnHttpStreamDone() {
 proxywasm.LogWarnf("%d OnHttpStreamDone", ctx.contextID)
}

func main() {
 proxywasm.LogWarnf("regex/main.go main() REACHED")
 // 設置 VM 上下文,這樣我們就可以在插件啟動時讀取配置。
 proxywasm.SetVMContext(&vmContext{})
}

在上面的代碼中,我們主要關注 pluginContext 和 httpRegex 這兩個結構體,其中 pluginContext 結構體主要用于插件的初始化,而 httpRegex 結構體主要用于處理 HTTP 請求,這里我們主要關注 OnHttpRequestHeaders 和 OnHttpResponseHeaders 這兩個方法,這兩個方法分別用于處理 HTTP 請求頭和響應頭,我們在這兩個方法中添加了一些自定義的 Header,然后在 Istio 中就可以看到這些 Header 了。

部署插件

代碼編寫完成后,我們就可以使用 tinygo 來編譯了,執行以下命令:

tinygo build -o main.wasm -scheduler=none -target=wasi main.go

上面的命令會生成一個 main.wasm 文件,這個文件就是我們的 WASM 插件,接下來我們就可以將這個插件部署到 Istio 中了。

部署 WASM

我們可以將這個 main.wasm 文件放到一個 ConfigMap 中,然后掛載到 Envoy 中,這樣就可以在 Envoy 中使用了,比如我們可以使用下面的命令來創建一個 ConfigMap:

kubectl create configmap new-filter --from-file=new-filter.wasm=main.wasm

然后接下來我們以 httpbin 為例來測試下,這里我們需要修改下 httpbin 的部署文件,將 ConfigMap 掛載到 Envoy 中。

部署 WASM

修改后的部署文件如下所示:

# httpbin.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
    service: httpbin
spec:
  ports:
    - name: http
      port: 8000
      targetPort: 80
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
      annotations:
        # 不能在容器上使用 volume 掛載,因為它來自 injector。
        # NOTE: 我們這個示例始終掛在 "new-filter" ConfigMap 到 /var/local/wasm/new-filter.wasm
        sidecar.istio.io/userVolume: '[{"name":"new-filter","configMap":{"name":"new-filter"}}]'
        sidecar.istio.io/userVolumeMount: '[{"mountPath":"/var/local/wasm","name":"new-filter"}]'
    spec:
      serviceAccountName: httpbin
      containers:
        - image: docker.io/kennethreitz/httpbin
          imagePullPolicy: IfNotPresent
          name: httpbin
          ports:
            - containerPort: 80

直接應用上面的資源對象即可:

kubectl apply -f httpbin.yaml
# 當然要需要創建 VirtualService,在 Istio 根目錄下面
kubectl apply -f samples/httpbin/httpbin-gateway.yaml

部署完成后接下來我們先訪問下 httpbin 服務,看下是否正常:

$ export GATEWAY_URL=$(kubectl get po -l istio=ingressgateway -n istio-system -o 'jsnotallow={.items[0].status.hostIP}'):$(kubectl get svc istio-ingressgateway -n istio-system -o 'jsnotallow={.spec.ports[?(@.name=="http2")].nodePort}')
$ curl -v http://$GATEWAY_URL/status/418
> GET /status/418 HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 192.168.0.20:31896
> Accept: */*
>
< HTTP/1.1 418 Unknown
< server: istio-envoy
< date: Fri, 08 Dec 2023 07:28:57 GMT
< x-more-info: http://tools.ietf.org/html/rfc2324
< access-control-allow-origin: *
< access-control-allow-credentials: true
< content-length: 135
< x-envoy-upstream-service-time: 2
<

    -=[ teapot ]=-

       _...._
     .'  _ _ `.
    | ."` ^ `". _,
    \_;`"---"`|//
      |       ;/
      \_     _/
        `"""`

上面我們編寫的插件邏輯是當我們訪問 http://service/banana/X 時,會將請求重定向到 http://service/status/X,所以我們可以使用下面的命令來測試下:

$ curl -v http://$GATEWAY_URL/banana/418
> GET /banana/418 HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 192.168.0.20:31896
> Accept: */*
>
< HTTP/1.1 404 Not Found
< server: istio-envoy
< date: Fri, 08 Dec 2023 07:30:19 GMT
< content-type: text/html
< content-length: 233
< access-control-allow-origin: *
< access-control-allow-credentials: true
< x-envoy-upstream-service-time: 9
<
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server.  If you entered the URL manually please check your spelling and try again.</p>

從結果可以看到,我們定義的插件并沒有生效,其實也能預料到,現在我們只是將編譯后的 WASM 文件掛載到了 Envoy 中,但是 Envoy 并不知道這個文件是用來做什么的,或者說 Envoy 并不知道要將這個文件當成 WASM 插件來使用。

$ kubectl get pods -l app=httpbin
NAME                       READY   STATUS    RESTARTS   AGE
httpbin-55db5999b4-qtlcg   2/2     Running   0          8m23s
$ kubectl exec -it httpbin-55db5999b4-qtlcg -c istio-proxy -- ls /var/local/wasm
new-filter.wasm

wasm 插件

這個時候我們還需要使用到一個名為 EnvoyFilter 的 CRD 資源對象,EnvoyFilter 提供了一種機制,可以自定義 Istio Pilot 生成的 Envoy 配置,使用 EnvoyFilter 可以修改某些字段的值、添加特定的過濾器,甚至添加全新的監聽器、集群等。需要注意的是這個功能必須小心使用,因為不正確的配置可能會導致整個網格不穩定。與其他 Istio 網絡對象不同,EnvoyFilters 是附加應用的。對于特定命名空間中給定工作負載來說,可以存在任意數量的 EnvoyFilters,這些 EnvoyFilters 的應用順序如下:首先是配置根命名空間中所有的 EnvoyFilters,然后是工作負載所在命名空間中匹配到的所有 EnvoyFilters。

比如我們可以使用下面的配置來將我們的 WASM 插件掛載到 Envoy 中:

# httpbin-wasm-filter.yaml
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: httpbin-wasm-filter
spec:
  workloadSelector:
    labels:
      app: httpbin
  configPatches:
    - applyTo: HTTP_FILTER
      match:
        context: SIDECAR_INBOUND # 僅對入站流量進行過濾
        listener:
          filterChain:
            filter:
              name: envoy.filters.network.http_connection_manager
              subFilter:
                name: envoy.filters.http.router
      patch:
        operation: INSERT_BEFORE # 在 router 之前插入
        value:
          name: mydummy
          typed_config:
            "@type": type.googleapis.com/udpa.type.v1.TypedStruct
            type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
            value:
              config:
                configuration:
                  "@type": type.googleapis.com/google.protobuf.StringValue
                  value: dummy
                root_id: "regex_replace"
                vm_config:
                  code:
                    local:
                      filename: /var/local/wasm/new-filter.wasm
                  runtime: envoy.wasm.runtime.v8
                  vm_id: myvmdummy

上面的 EnvoyFilter 對象中,首先我們通過 workloadSelector 來指定要對哪些 Pod 進行過濾,這里我們指定了 app: httpbin,表示只對 httpbin 這個 Pod 進行過濾,然后主要關注 configPatches 字段,這個字段用于配置 Envoy 的過濾器,其中的 match 字段用于匹配 Envoy 的過濾器,這里我們匹配的是 envoy.filters.network.http_connection_manager,然后 patch 字段用于指定要掛載的 WASM 插件,在 value.config 中指定了插件的配置信息以及 WASM 插件的路徑。

然后直接應用上面的這個資源對象即可:

kubectl apply -f httpbin-wasm-filter.yaml

部署完成后我們可以先查看 httpbin 應用的 sidecar 日志:

$ kubectl logs -f httpbin-55db5999b4-qtlcg -c istio-proxy
# ......
2023-12-08T07:48:03.605802Z     warning envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1151 wasm log: regex/main.go main() REACHED  thread=25
2023-12-08T07:48:03.606902Z     warning envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1151 wasm log regex_replace myvmdummy: read plug-in config: dummy
        thread=25
2023-12-08T07:48:03.729847Z     info    Readiness succeeded in 1.025422807s
2023-12-08T07:48:03.730148Z     info    Envoy proxy is ready

正?,F在就可以看到上面我們在插件中添加的一些日志了,然后我們再來測試下 httpbin 服務,訪問 http://service/banana/X,看下是否能夠正常重定向到 http://service/status/X:

$ curl -v http://$GATEWAY_URL/banana/418
> GET /banana/418 HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 192.168.0.20:31896
> Accept: */*
>
< HTTP/1.1 418 Unknown
< server: istio-envoy
< date: Fri, 08 Dec 2023 08:11:17 GMT
< x-more-info: http://tools.ietf.org/html/rfc2324
< access-control-allow-origin: *
< access-control-allow-credentials: true
< content-length: 135
< x-envoy-upstream-service-time: 10
< who-am-i: go-wasm-demo
< injected-by: istio-api!
< site: youdianzhishi.com
< author: 陽明
< configdata: dummy
<

    -=[ teapot ]=-

       _...._
     .'  _ _ `.
    | ."` ^ `". _,
    \_;`"---"`|//
      |       ;/
      \_     _/

從上面的結果可以看到,我們的插件已經生效了,當我們訪問 http://service/banana/X 時,會將請求重定向到 http://service/status/X,并且在響應頭中添加了我們定義的一些 Header。到這里我們就實現了一個簡單的 WASM 插件,當然這個插件只是一個簡單的示例,實際上我們可以實現更加復雜的邏輯,比如可以實現自定義認證、自定義日志、自定義路由等等。

WasmPlugin API

需要注意的是這里我們的部署方式是創建一個包含已編譯的 Wasm 插件的 ConfigMap,將 ConfigMap 掛載到 Pod 的 Envoy Sidecar 中去,然后通過 EnvoyFilter 配置 Envoy,從本地文件加載 Wasm 插件。這種方法的確可以實現我們的需求,但是配置 EnvoyFilter 對象有點復雜,功能豐富的 Wasm 插件可能超出 ConfigMap 1MB 的大小限制。為了解決這個問題,Istio 便引入了一個新的用于自定義 Wasm 插件對 Istio 代理功能進行擴展的新頂層 API - WasmPlugin CRD,不再需要使用 EnvoyFilter 資源向代理添加自定義 Wasm 模塊,取而代之的是使用 WasmPlugin 資源:

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: your-filter
spec:
  selector:
    matchLabels:
      app: server
  phase: AUTHN
  priority: 10
  pluginConfig:
    someSetting: true
    someOtherSetting: false
    youNameIt:
      - first
      - second
  url: docker.io/your-org/your-filter:1.0.0

WasmPlugin 和 EnvoyFilter 之間有不少相似的地方,但也存在一些不同之處。比如在上面的示例中是將 Wasm 模塊部署到與 selector 字段匹配的所有工作負載 —— 這與 EnvoyFilter 是完全相同的。

接下來的字段是 phase,該字段決定了 Wasm 模塊將被注入到代理過濾器鏈中的哪個位置。我們為其定義了四個不同的階段:

  • AUTHN:在所有 Istio 身份驗證和授權過濾器之前。
  • AUTHZ:在 Istio 身份驗證過濾器之后以及所有一級授權過濾器之前,即應用于 AuthorizationPolicy 資源之前。
  • STATS:在所有授權過濾器之后,以及 Istio 統計過濾器之前。
  • UNSPECIFIED_PHASE:讓控制平面決定注入的位置,通常位于過濾器鏈的末端,也就是在路由之前。這也是該 phase 字段的默認值。

pluginConfig 字段用于 Wasm 插件的具體配置。在此字段中輸入的任何內容都將通過 JSON 格式進行編碼并傳遞到過濾器中,我們可以在 Proxy-Wasm SDK 的配置回調中訪問它,比如在 Go SDK 中的 OnPluginStart 回調中可以獲取這些配置信息。

url 字段指定了 Wasm 模塊的拉取位置,這里的 url 是一個 docker URI,除了通過 HTTP、HTTPS 和本地文件系統 (使用 file://)方式加載 Wasm 模塊之外,還可以使用 OCI 鏡像格式作為分發 Wasm 插件,這也是推薦的方式。

接下來我們按照上面的要求在代碼根目錄中新建一個 Dockerfile,用來將我們的 Wasm 插件打包到 Docker 鏡像中:

# Dockerfile for building "compat" variant of Wasm Image Specification.
# https://github.com/solo-io/wasm/blob/master/spec/spec-compat.md

FROM scratch

COPY main.wasm ./plugin.wasm

當然也可以將構建的動作放到 Dockerfile 中,進行多階段構建:

FROM tinygo/tinygo as build
WORKDIR /src

COPY . .
RUN go env -w GOPROXY=https://goproxy.cn,direct
RUN tinygo build -o main.wasm -scheduler=none -target=wasi ./main.go

FROM scratch

COPY --from=build /src/main.wasm ./plugin.wasm

直接使用 docker build 命令來構建鏡像即可,構建完成后推送到鏡像倉庫:

docker build -t cnych/wasm-go-demo:v0.1 .
docker.io/cnych/wasm-go-demo:v0.1

接下來就可以使用 WasmPlugin 資源對象來部署我們的 WASM 插件了,創建如下所示的 WasmPlugin 資源對象:

# httpbin-wasm-plugin.yaml
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: httpbin-wasm-plugin
  namespace: default
spec:
  selector:
    matchLabels:
      app: httpbin
  url: oci://docker.io/cnych/wasm-go-demo:v0.1
  pluginConfig:
    testConfig: abcd
    website: youdianzhishi.com
    listconfig:
      - abc
      - def

先刪除之前的 EnvoyFilter 資源:

$ kubectl delete cm new-filter
configmap "new-filter" deleted
$ kubectl delete envoyfilter httpbin-wasm-filter
envoyfilter.networking.istio.io "httpbin-wasm-filter" deleted

記得將 httpbin.yaml 中的 sidecar.istio.io/userVolume 和 sidecar.istio.io/userVolumeMount 字段刪除:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
      # annotations: # 去掉這里的注解
    spec:
      serviceAccountName: httpbin
      containers:
        - image: docker.io/kennethreitz/httpbin
          imagePullPolicy: IfNotPresent
          name: httpbin
          ports:
            - containerPort: 80

然后直接應用上面的 WasmPlugin 資源對象:

$ kubectl apply -f httpbin-wasm-plugin.yaml
$ kubectl get wasmplugins
NAME                  AGE
httpbin-wasm-plugin   5s

部署完成后我們可以先查看 httpbin 應用的 sidecar 日志:

$ kubectl logs -f httpbin-86869bccff-6wqdc -c istio-proxy
# ......
2023-12-08T08:43:11.360127Z     warning envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1151 wasm log: regex/main.go main() REACHED  thread=25
2023-12-08T08:43:11.360757Z     warning envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1151 wasm log: regex/main.go OnPluginStart() thread=25
2023-12-08T08:43:11.360895Z     warning envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1151 wasm log: read plug-in config: {"listconfig":["abc","def"],"testConfig":"abcd","website":"youdianzhishi.com"}
        thread=25
2023-12-08T08:43:12.692961Z     info    Readiness succeeded in 6.774251572s
2023-12-08T08:43:12.693263Z     info    Envoy proxy is ready

可以看到我們的插件已經生效了,然后我們再來測試下 httpbin 服務,訪問 http://service/banana/X,看下是否能夠正常重定向到 http://service/status/X:

$ curl -v http://$GATEWAY_URL/banana/418
> GET /banana/418 HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 192.168.0.20:31896
> Accept: */*
>
< HTTP/1.1 418 Unknown
< server: istio-envoy
< date: Fri, 08 Dec 2023 08:45:29 GMT
< x-more-info: http://tools.ietf.org/html/rfc2324
< access-control-allow-origin: *
< access-control-allow-credentials: true
< content-length: 135
< x-envoy-upstream-service-time: 8
< who-am-i: go-wasm-demo
< injected-by: istio-api!
< site: youdianzhishi.com
< author: 陽明
< configdata: {"listconfig":["abc","def"],"testConfig":"abcd","website":"youdianzhishi.com"}
<

    -=[ teapot ]=-

       _...._
     .'  _ _ `.
    | ."` ^ `". _,
    \_;`"---"`|//
      |       ;/
      \_     _/
        `"""`

從上面的結果可以看到結果是符合我們的預期的,證明我們的插件已經生效了。

性能數據

參考阿里云性能測試結果(僅供參考):

1000 并發 1000QPS 持續 10 秒鐘

基準

WASM

LUA

平均延遲

0.6317 secs

0.6395 secs

0.7012 secs

延遲 99%分布

0.9167 secs

0.9352 secs

1.1355 secs

QPS

1541

1519

1390

Total

16281

16109

1390

相對于基準版本,增加 Wasm 插件的兩個版本,平均延遲多出幾十個到幾百個毫秒,增加耗時比為:

  • wasm:1.2% (0.6395-0.6317)/0.6317和 1% (1.3290-1.2078)/1.2078
  • lua:11%(0.7012-0.6317)/0.6317和 20% (1.4593-1.2078)/1.2078

可以看出 WASM 版本的性能明顯優于 LUA 版本。

責任編輯:姜華 來源: k8s技術圈
相關推薦

2021-12-27 10:46:07

WebAPIserver簽名

2009-08-31 14:45:10

C#擴展方法

2021-05-06 09:33:32

OperatorKubernetes開源

2022-06-02 08:01:11

云原生工具

2018-07-30 13:29:04

WebAssemblyGo語言

2021-05-09 22:48:40

SQL數據庫變量

2024-01-02 07:37:52

FlaggerKubernetesIstio

2021-06-15 20:59:14

Kubernetes調試容器

2022-08-30 08:00:00

架構數據庫Postgres

2021-03-05 00:06:12

Docker容器內存

2022-08-15 15:16:20

機器學習圖片深度學習

2009-10-22 09:32:51

ghostlinux系統備份

2023-07-13 11:24:14

SQL優化賦值

2021-09-27 16:39:10

PythonGif壓縮

2010-12-15 15:30:45

組策略

2021-08-30 14:23:05

BlazorHTTP請求

2023-11-20 07:19:33

2022-11-07 07:54:05

微服務數據庫網關

2015-09-11 15:41:08

2010-12-27 09:19:23

點贊
收藏

51CTO技術棧公眾號

中国一区二区视频| 草草地址线路①屁屁影院成人| 日韩子在线观看| 国产精品资源在线看| 91精品国产91久久久久久久久| xxxxx在线观看| 国产一区二区三区亚洲综合| 红桃av永久久久| 亚洲欧美日韩另类精品一区二区三区 | 国产欧美亚洲精品a| 欧美男生操女生| 日韩免费一级视频| 快射av在线播放一区| 91免费国产在线| 亚洲综合社区网| 免费精品一区二区| 激情综合中文娱乐网| 中文字幕在线视频日韩| 亚洲国产欧美一区二区三区同亚洲| 91欧美日韩一区| 日本视频网站在线观看| 欧美视频四区| www.日韩av.com| 丰腴饱满的极品熟妇| 亚洲一二av| 欧美一区二区私人影院日本| 黄色片视频在线播放| 大桥未久在线播放| 亚洲精品少妇30p| 亚洲成人蜜桃| 黄网站在线观看| 成人黄色网址在线观看| 91精品视频在线| 嫩草影院一区二区三区| 国产精品视频| 68精品久久久久久欧美| 欧美日韩精品一区二区三区视频播放 | 欧美一级黄色片| 色噜噜狠狠永久免费| 欧美xxxxxx| 欧美午夜丰满在线18影院| 天堂8在线天堂资源bt| av网站大全在线| 国产精品久久久久久久久免费相片 | av天堂一区二区三区| 蜜桃av噜噜一区二区三区小说| 青青a在线精品免费观看| 日本一区二区欧美| 99av国产精品欲麻豆| 午夜精品蜜臀一区二区三区免费 | 91成年人网站| 最新国产一区| 亚洲人成网站色ww在线| 中文字幕丰满乱子伦无码专区| 色爱综合av| 精品一区二区三区四区| 亚洲精品成人无码熟妇在线| 日本一道高清一区二区三区| 日韩精品中文字| 女~淫辱の触手3d动漫| 国产欧美一区二区三区精品观看 | 国产精品麻豆一区| 久久视频国产| 久久国产精品亚洲| 国产亚洲第一页| 国产欧美成人| 国产精品91久久久| 91麻豆成人精品国产| 国产一区二区三区日韩| 成人免费视频观看视频| 婷婷久久久久久| 欧美国产综合色视频| 黄色一级片网址| 欧美1—12sexvideos| 精品久久久精品| 波多结衣在线观看| 久久久久久久久成人| 亚洲国产精品免费| 国产高清一区二区三区四区| 国产精品久久占久久| 欧美大荫蒂xxx| 男人日女人网站| 久久99最新地址| 成人片在线免费看| 韩国福利在线| 亚洲品质自拍视频| 无罩大乳的熟妇正在播放| 日本黄色一区| 精品国产伦一区二区三区观看方式| 黄色国产在线观看| 久久理论电影| 91精品国产91久久久久久不卡 | 理论片午夜视频在线观看| 欧美专区亚洲专区| 国产精品嫩草69影院| 欧美激情在线精品一区二区三区| 精品国产一区二区三区久久久狼| 97人人澡人人爽人人模亚洲| 免费久久99精品国产| 狠狠色噜噜狠狠狠狠色吗综合| 国产高清一区在线观看| vam成人资源在线观看| 中文字幕中文字幕一区| 国产二区视频在线| 玖玖精品在线| 亚洲国产精品成人精品 | 一区二区三区在线观看视频| 国产精品人人妻人人爽人人牛| 欧美激情精品| 国产一区二区三区在线视频 | wwwwww日本| 欧美午夜影院| 成人在线视频网站| 久久久久久青草| 亚洲高清一区二区三区| 伊人网在线综合| 国产一区二区三区探花 | 免费看日韩毛片| 国内成人自拍视频| 日韩三级电影| 中文字幕高清在线播放| 日韩女优毛片在线| 国产成人av免费在线观看| 日本欧美在线观看| 久久日韩精品| 美女91在线看| 欧美精品一区二区三区久久久| 人人艹在线视频| 日韩激情一二三区| 免费在线成人av| 国产亚洲成av人片在线观看| 日韩精品资源二区在线| 国产精品成人69xxx免费视频| 日韩不卡一区二区三区| 欧美精品一区二区三区久久| 少妇视频在线观看| 精品成人一区二区三区四区| 青娱乐国产在线视频| 国产精品综合av一区二区国产馆| 黄瓜视频免费观看在线观看www| 无人区在线高清完整免费版 一区二| 精品成人a区在线观看| 黄色一级视频在线观看| 国产乱码字幕精品高清av | 久久精品123| 久久艹中文字幕| 波多野结依一区| 精品对白一区国产伦| 日韩欧美国产亚洲| 91麻豆精品视频| 黄在线观看网站| 国产成人影院| 国产精品人人做人人爽| fc2在线中文字幕| 欧美日韩视频在线一区二区| 男女全黄做爰文章| 国产自产v一区二区三区c| 黄色小视频大全| 7777精品| 91精品国产91久久久久久不卡 | 日韩欧美另类中文字幕| 欧美成人黑人xx视频免费观看| 91在线视频国产| 国产精品大尺度| 中文字幕 欧美 日韩| 亚洲手机在线| 久久99精品久久久久久青青日本 | 亚洲免费播放| 久久久久久国产精品mv| 唐人社导航福利精品| 亚洲天堂网在线观看| 伊人久久成人网| 日韩一区在线免费观看| 国产成人av免费观看| 亚洲理论在线| 一本一道久久a久久综合精品| 国产精品一区二区三区四区在线观看| 欧美精品一区二区三区国产精品| 黄色av网站免费在线观看| 欧美日韩激情美女| 韩国一级黄色录像| 成人精品高清在线| 国产情侣av自拍| 亚洲人体av| 黄色99视频| 91欧美精品| 欧美激情第6页| 国产经典自拍视频在线观看| 欧美精品xxxxbbbb| 日韩精品在线不卡| 国产精品视频线看| 久久久久国产免费| 日本在线不卡视频| h无码动漫在线观看| 国产一区二区三区天码| 亚洲图片激情小说| 久久亚洲中文字幕无码| 色呦哟—国产精品| 精品免费二区三区三区高中清不卡| 波多野结衣久久精品| 另类专区欧美制服同性| 日本亚洲一区| 日韩欧美电影在线| 波多野结衣爱爱| 亚洲一区二区三区自拍| 国产人妻大战黑人20p| 高潮精品一区videoshd| 天天操天天爱天天爽| 亚洲激情综合| 国产盗摄视频在线观看| 九九综合久久| 国产精品久久精品视| 九九九精品视频| 日产精品99久久久久久| 高清电影在线观看免费| 在线午夜精品自拍| 天堂成人在线视频| 欧美一区二区三区喷汁尤物| 波多野结衣黄色网址| 午夜激情综合网| 五月天av网站| 国产精品拍天天在线| 国产国语性生话播放| 丁香网亚洲国际| 久久综合在线观看| 麻豆成人久久精品二区三区小说| 欧美激情 国产精品| 午夜欧美理论片| 亚洲欧洲一区二区福利| 欧美精品momsxxx| 欧美午夜精品久久久久久蜜| 亚洲开心激情| 91在线视频成人| 久久久加勒比| 国产精品久久久久久久久久三级| sm久久捆绑调教精品一区| 欧美激情精品久久久久久蜜臀| 麻豆视频在线免费观看| 色999日韩欧美国产| 成人在线免费公开观看视频| 亚洲欧美日韩中文在线| 天堂91在线| 亚洲精品自在久久| 日韩亚洲视频在线观看| 精品视频在线播放色网色视频| 色哟哟中文字幕| 亚洲国产中文字幕在线观看| 欧美亚洲精品在线观看| 欧美精品一区二区精品网| 亚洲老妇色熟女老太| 亚洲精品乱码久久久久久按摩观| 黑人精品一区二区| 亚洲国产天堂久久综合| 婷婷开心激情网| 亚洲美女久久久| 成人好色电影| 中文字幕亚洲综合久久| 日韩大片在线永久免费观看网站| 中文字幕欧美精品在线| 婷婷免费在线视频| 在线视频亚洲欧美| 欧美成人xxx| 在线视频国产日韩| 9191在线| 欧美黄色成人网| 亚洲风情在线资源| 国产精品免费网站| 日韩久久99| 91九色对白| 日韩精品丝袜美腿| 日本精品一区| 亚洲女同中文字幕| 久草热视频在线观看| 日本在线不卡视频一二三区| 在线播放av中文字幕| 成人精品视频.| 久久av无码精品人妻系列试探| 中文无字幕一区二区三区| 亚洲国产精品久| 岛国av一区二区三区| 伊人免费在线观看| 欧美大片日本大片免费观看| 日韩欧美电影在线观看| 精品国产一区av| 国产伦理精品| 国产欧美精品在线| 成人三级av在线| 亚洲春色综合另类校园电影| 欧美大片一区| 欧美三级午夜理伦三级| 精品一区二区免费| 制服丝袜第二页| 中文字幕一区二区在线播放| 国产在线观看免费视频今夜| 日本高清视频一区二区| www夜片内射视频日韩精品成人| 亚洲美女性生活视频| 毛片在线看网站| 97香蕉久久超级碰碰高清版| 九七影院97影院理论片久久| 精品婷婷色一区二区三区蜜桃| 欧美残忍xxxx极端| 北条麻妃在线视频观看| 狠狠色丁香婷婷综合| 精品无码在线视频| 亚洲激情av在线| 日本精品入口免费视频| 精品国产自在久精品国产| 国产对白叫床清晰在线播放| 97超级碰碰碰久久久| 亚洲人成777| 日本免费高清一区| 亚洲激情女人| 日本55丰满熟妇厨房伦| 欧美国产精品中文字幕| 51国产偷自视频区视频| 日韩美女视频一区二区在线观看| 97视频在线观看网站| 青青久久av北条麻妃黑人| 污色网站在线观看| 日本大胆欧美人术艺术动态| 五月天激情小说| 一区二区三区精品视频在线| 在线视频 91| 一区二区三区四区视频| 中文字幕在线直播| 黄色91av| 中日韩男男gay无套| 亚洲少妇一区二区| 亚洲欧美乱综合| 国产欧美综合视频| 日韩亚洲综合在线| 福利视频亚洲| 亚洲国产精品综合| 日韩av午夜在线观看| 成人午夜福利一区二区| 好吊成人免视频| 天堂中文在线官网| 97婷婷涩涩精品一区| 久久九九热re6这里有精品| 亚洲人成无码网站久久99热国产| 国产99久久久国产精品免费看| 乱h高h女3p含苞待放| 91精品国产综合久久久久久漫画| 天堂中文а√在线| 国产日韩精品入口| 911精品美国片911久久久| 91丨九色丨蝌蚪| 亚洲三级在线播放| 国产熟女一区二区丰满| 欧美精品在线播放| 高清一区二区三区| 日本午夜激情视频| 91免费精品国自产拍在线不卡| 国产成人在线观看网站| 日韩精品日韩在线观看| 在线观看爽视频| 图片区小说区区亚洲五月| 青青草伊人久久| 色哟哟一一国产精品| 91精品国产高清一区二区三区蜜臀 | 欧美高清hd| 免费网站永久免费观看| av电影在线观看完整版一区二区| 中文字幕第15页| 一区二区三区国产视频| 国产精品白丝久久av网站| 成年人视频网站免费| 99在线精品视频| 国产精品熟女视频| 久久精品视频亚洲| 成人激情自拍| 欧美丰满熟妇xxxxx| 综合久久久久久久| 蜜桃在线一区二区| 国产国产精品人在线视| 久久精品国内一区二区三区水蜜桃| xxxx国产视频| 日韩欧美亚洲成人| 午夜老司机在线观看| 国产一区二区精品在线| 天堂一区二区在线| 日韩女优一区二区| 精品性高朝久久久久久久| 日韩国产一二三区| av无码久久久久久不卡网站| 国产亚洲精品aa| 午夜精品久久久久久久99热黄桃| 136fldh精品导航福利| 日韩在线综合| 国产偷人妻精品一区| 欧美三区在线视频| 2021天堂中文幕一二区在线观| 性高潮久久久久久久久| 国产99久久久国产精品免费看| 7799精品视频天天看| 欧美另类第一页| 日韩一区亚洲二区| a级一a一级在线观看| 884aa四虎影成人精品一区|