<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          用 WebAssembly 為 Istio 擴展插上靈活的翅膀

          共 18068字,需瀏覽 37分鐘

           ·

          2023-08-17 07:03

          Sealos 公眾號已接入了 GPT-4,完全免費!歡迎前來調(diào)戲??


          ?

          作者:cuisongliu。Sealos 核心 Maintainer,Kubernetes、Helm、Sealer、Openyurt和 NVIDIA 等項目 commiter。

          Istio 引入了 WebAssembly 擴展的概念,允許開發(fā)者通過將自定義的 WebAssembly 模塊插入 Istio 的 Envoy 代理來擴展 Istio 的功能。這為 Istio 帶來了更高的靈活性和可擴展性,開發(fā)者可以在不改變 Istio 核心代碼的情況下添加自定義功能。

          WebAssembly 在 Istio 中的工作原理

          WebAssembly 是一種沙盒技術(shù),可以用于擴展 Istio 代理(Envoy)的能力。 Proxy-Wasm 沙盒 API 取代了 Mixer 作為 Istio 主要的擴展機制。

          WebAssembly 沙盒的目標(biāo):

          • 效率 - 這是一種低延遲,低 CPU 和內(nèi)存開銷的擴展機制。
          • 功能 - 這是一種可以執(zhí)行策略,收集遙測數(shù)據(jù)和執(zhí)行有效荷載變更的擴展機制。
          • 隔離 - 一個插件中程序的錯誤或是崩潰不會影響其它插件。
          • 配置 - 插件使用與其它 Istio API 一致的 API 進行配置??梢詣討B(tài)的配置擴展。
          • 運維 - 擴展可以以僅日志,故障打開或者故障關(guān)閉的方式進行訪問和部署。
          • 擴展開發(fā)者 - 可以用多種編程語言編寫。

          高級架構(gòu)

          Istio 擴展(Proxy-Wasm 插件)有幾個組成部分:

          • 過濾器服務(wù)提供方接口(SPI) 用于為過濾器構(gòu)建 Proxy-Wasm 插件。
          • 沙盒 在 Envoy 中嵌入 V8 Wasm 運行時。
          • 主機 API 用于處理請求頭,尾和元數(shù)據(jù)。
          • 調(diào)出 API 針對 gRPC 和 HTTP 請求。
          • 統(tǒng)計和記錄 API 用于度量統(tǒng)計和監(jiān)控。

          應(yīng)用場景

          • 自定義流量管理:開發(fā)者可以使用 WebAssembly 模塊實現(xiàn)自定義的流量控制策略,如 AB 測試、灰度發(fā)布等。
          • 安全策略:通過 WebAssembly 模塊,可以實現(xiàn)自定義的安全策略,例如訪問控制、防火墻規(guī)則等。
          • 日志和監(jiān)控:開發(fā)者可以使用 WebAssembly 模塊來收集特定流量的指標(biāo)或日志。

          ABI 規(guī)范定義 (Application Binary Interface)

          應(yīng)用程序二進制接口(ABI)規(guī)范定義了 L4/L7 代理與作為 WebAssembly 模塊交付的擴展之間使用的約定。這些規(guī)范最初為 Envoy 項目中的 WebAssembly 開發(fā)而創(chuàng)建,但在代理無關(guān),使用者可以在不同的代理之間使用相同的 Proxy-Wasm 擴展。

          SDKs

          Istio 提供了多種 WebAssembly SDK,方便開發(fā)者使用不同編程語言編寫插件:

          • C++ SDK[1]
          • Rust SDK[2]
          • AssemblyScript SDK[3]
          • TinyGo SDK[4]

          Istio Wasm Plugin 介紹

          Istio Wasm Plugin[5]是一種通過 WebAssembly 過濾器來擴展 Istio 代理功能的機制。通過設(shè)置插件的階段(phase)和優(yōu)先級(priority),可以在用戶提供的 Wasm 插件和 Istio 內(nèi)部過濾器之間配置復(fù)雜的交互。

          以下是一些使用示例:

          1. 使用本地文件讀取 wasm 插件:
          apiVersion: extensions.istio.io/v1alpha1
          kind: WasmPlugin
          metadata:
            name: openid-connect
            namespace: istio-ingress
          spec:
            selector:
              matchLabels:
                istio: ingressgateway
            url: file:///opt/filters/openid.wasm
            sha256: 1ef0c9a92b0420cf25f7fe5d481b231464bc88f486ca3b9c83ed5cc21d2f6210
            phase: AUTHN
            pluginConfig:
              openid_server: authn
              openid_realm: ingress
          1. 使用 OCI 鏡像讀取 wasm 插件并設(shè)置拉取的 secret:
          apiVersion: extensions.istio.io/v1alpha1
          kind: WasmPlugin
          metadata:
            name: openid-connect
            namespace: istio-ingress
          spec:
            selector:
              matchLabels:
                istio: ingressgateway
            url: oci://private-registry:5000/openid-connect/openid:latest
            imagePullPolicy: IfNotPresent
            imagePullSecret: private-registry-pull-secret
            phase: AUTHN
            pluginConfig:
              openid_server: authn
              openid_realm: ingress
          1. 使用環(huán)境變量讀取變量:
          apiVersion: extensions.istio.io/v1alpha1
          kind: WasmPlugin
          metadata:
            name: openid-connect
            namespace: istio-ingress
          spec:
            selector:
              matchLabels:
                istio: ingressgateway
            url: oci://private-registry:5000/openid-connect/openid:latest
            imagePullPolicy: IfNotPresent
            imagePullSecret: private-registry-pull-secret
            phase: AUTHN
            pluginConfig:
              openid_server: authn
              openid_realm: ingress
            vmConfig:
              env:
              - name: POD_NAME
                valueFrom: HOST
              - name: TRUST_DOMAIN
                value: "cluster.local"
          1. 使用 http 讀取 wasm 插件:
          apiVersion: extensions.istio.io/v1alpha1
          kind: WasmPlugin
          metadata:
            name: openid-connect
            namespace: istio-ingress
          spec:
            selector:
              matchLabels:
                istio: ingressgateway
            url: https://private-bucket/filters/openid.wasm
            imagePullPolicy: Always
            phase: AUTHN
            pluginConfig:
              openid_server: authn
              openid_realm: ingress
            vmConfig:
              env:
              - name: POD_NAME
                valueFrom: HOST
              - name: TRUST_DOMAIN
                value: "cluster.local"

          Wasm Plugin 與 Istio 執(zhí)行順序

          Wasm 插件的執(zhí)行順序由階段(phase)和優(yōu)先級(priority)設(shè)置決定。在 Istio 代理收到請求時,根據(jù) Wasm 插件的設(shè)置,將它們按照階段進行分組,并在每個階段內(nèi)按優(yōu)先級值進行排序。然后,Istio 代理按照階段和優(yōu)先級的順序依次調(diào)用每個 Wasm 插件的邏輯,從而實現(xiàn)個性化處理和功能擴展。

          WasmPlugin 支持字段

          WasmPlugins 提供了一種通過 WebAssembly 過濾器擴展 Istio 代理功能的機制。以下是 WasmPlugins 支持的字段以及它們的描述:

          • selector: 用于選擇將應(yīng)用該插件配置的特定 pod/ 虛擬機集合的條件。
          • url: Wasm 模塊或 OCI 容器的 URL。支持 file://,oci:// 和 http[s]:// 等協(xié)議。
          • sha256: SHA256 校驗和,用于驗證 Wasm 模塊或 OCI 容器。
          • imagePullPolicy: 在通過 OCI 鏡像或 http/https 獲取 Wasm 模塊時應(yīng)用的拉取行為。
          • imagePullSecret: 用于 OCI 鏡像拉取的憑據(jù)。
          • pluginConfig: 傳遞給插件的配置信息。
          • pluginName: 在 Envoy 配置中使用的插件名稱。
          • phase: 確定將 WasmPlugin 插入過濾器鏈的位置。
          • priority: 確定在同一階段中多個 WasmPlugin 的執(zhí)行順序。
          • vmConfig: 配置 Wasm 虛擬機(VM)的信息。
          • match: 用于指定哪些流量將傳遞給 WasmPlugin 的條件。

          環(huán)境準(zhǔn)備

          wget https://github.com/labring/sealos/releases/download/v4.3.0/sealos_4.3.0_linux_amd64.tar.gz
          tar -zxvf sealos_4.3.0_linux_amd64.tar.gz sealos
          chmod a+x sealos 
          mv sealos /usr/bin/
          sealos run labring/kubernetes-docker:v1.23.0 labring/helm:v3.12.0 labring/calico:v3.24.1

          部署 Istio

          sealos run labring/istio:1.16.2-min

          安裝 rust 語言環(huán)境

          curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
          ?

          如果使用的國內(nèi)環(huán)境,可以使用以下命令操作

          export RUSTUP_DIST_SERVER="https://rsproxy.cn"
          export RUSTUP_UPDATE_ROOT="https://rsproxy.cn/rustup"
          curl --proto '=https' --tlsv1.2 -sSf https://rsproxy.cn/rustup-init.sh | sh
          cat > ~/.cargo/config <<EOF
          [source.crates-io]
          replace-with = 'rsproxy-sparse'
          [source.rsproxy]
          registry = "https://rsproxy.cn/crates.io-index"
          [source.rsproxy-sparse]
          registry = "sparse+https://rsproxy.cn/index/"
          [registries.rsproxy]
          index = "https://rsproxy.cn/crates.io-index"
          [net]
          git-fetch-with-cli = true
          EOF

          初始化 rust wasm 項目

          使用 JetBrains 插件

          打開 Goland 并安裝插件 Rust 后創(chuàng)建項目

          1. 新增配置 istio-wasm-rust 模板 :
          ?

          填寫模板地址 : https://github.com/labring-actions/istio-wasm-template.git

          1. 新建項目選擇 istio-wasm-rust 模板

          使用命令行

          cargo install cargo-generate
          cargo generate --git https://github.com/labring-actions/istio-wasm-template.git --name my-project
          cd my-project

          編譯

          本地編譯:

          make build 

          容器編譯:

          REPO=sealos.hub:5000 IMG=wasm/wasm-auth:latest make docker-build

          部署

          本地編譯后部署

          sealos login sealos.hub:5000
          REPO=sealos.hub:5000 IMG=wasm/wasm-auth:v1 make oci-build
          REPO=sealos.hub:5000 IMG=wasm/wasm-auth:latest make sealos-push
          sealos run sealos.hub:5000/wasm/wasm-auth:latest

          容器編譯后部署

          REPO=sealos.hub:5000 IMG=wasm/wasm-auth:latest make sealos-push
          sealos run sealos.hub:5000/wasm/wasm-auth:latest

          驗證部署

          kubectl get pod -n istio-system
          NAME READY STATUS RESTARTS AGE
          istio-ingressgateway-556959fc6f-prbbg 1/1 Running 0 4d15h
          istiod-5b9c4f9bf9-w6xns 1/1 Running 0 4d15h

          kubectl logs -f -n istio-system istio-ingressgateway-556959fc6f-prbbg
          ...
          2023-08-05T08:06:22.020843Z info wasm fetching image wasm/wasm-auth from registry sealos.hub:5000 with tag v1
          2023-08-05T08:06:22.049991Z info wasm fetching image with plain text from sealos.hub:5000/wasm/wasm-auth:v1

          注意事項:

          • 默認(rèn)配置是過濾的 istio-ingressgateway 的所有請求。如果需要調(diào)整,請修改 wasmplugin 的 selector 即可。
          • 默認(rèn)是看不到 wasm 相關(guān)的日志,需要修改 istio-ingressgateway 的日志級別,添加 proxyComponentLogLevel 配置 wasm:debug 或者 wasm:info
            - proxy
            - router
            - --domain
            - $(POD_NAMESPACE).svc.cluster.local
            - --proxyLogLevel=warning
            - --proxyComponentLogLevel=misc:error,wasm:debug
            - --log_output_level=default:info,wasm:debug

          再看日志,可以看到已經(jīng)打印了默認(rèn)配置

          2023-08-05T08:15:05.751195Z	debug	envoy wasm	wasm log: #on_configure -> {"password":"passw0rd","username":"admin"}
          2023-08-05T08:15:05.751208Z debug envoy wasm ~Wasm 12 remaining active
          2023-08-05T08:15:05.752986Z debug envoy wasm wasm log: #on_configure -> {"password":"passw0rd","username":"admin"}
          2023-08-05T08:15:05.753243Z debug envoy wasm wasm log: #on_configure -> {"password":"passw0rd","username":"admin"}
          2023-08-05T08:15:05.753372Z debug envoy wasm wasm log: #on_configure -> {"password":"passw0rd","username":"admin"}

          Rust SDK 說明

          這里講解一下 Rust SDK 的使用方法和一些常見問題。

          1. 如何獲取 pluginConfig 的配置:
          impl RootContext for HttpHeadersRoot {
              fn get_type(&self) -> Option<ContextType> {
                  Some(ContextType::HttpContext)
              }

              fn create_http_context(&self, context_id: u32) -> Option<Box<dyn HttpContext>> {
                  Some(Box::new(HttpHeaders { context_id }))
              }

              // 讀取pluginConfig配置,直接解析json即可
              fn on_configure(&mut self, _plugin_configuration_size: usize) -> bool {
                  if let Some(config_bytes) = self.get_plugin_configuration() {
                      if let Ok(config_str) = std::str::from_utf8(&config_bytes) {
                          debug!("#{} -> {}""on_configure", config_str);
                      } else {
                          error!("Failed to convert configuration bytes to string");
                          return false;
                      }
                  }
                  true
              }
          }
          1. 如何獲取 HTTP 所有的請求頭:
          fn on_http_response_headers(&mut self, _: usize, _: bool) -> Action {
             for (name, value) in &self.get_http_response_headers() {
                info!("#{} <- {}: {}"self.context_id, name, value);
             }
             Action::Continue
          }
          1. 如何獲取 HTTP 的某個請求頭:
          if let Some(path) = self.get_http_request_header(":path")  {
              // TODO: do something with the path
          }
          1. 如何強制修改請求頭:
          self.set_http_request_header(key, value);
          1. 如何終止請求并發(fā)送 401 響應(yīng):
          fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action {
              if let Some(path) = self.get_http_request_header(":path") {
                  self.send_http_response(
                      401,
                      sdk::headers(),
                      None,
                  );
                  return Action::Pause;
              }
              return Action::Continue;
          }
          1. 如何發(fā)送請求給其他服務(wù),并解析請求返回

          參考代碼 : https://github.com/proxy-wasm/proxy-wasm-rust-sdk/blob/master/examples/http_auth_random/src/lib.rs

          ?

          這里需要說明一下,它其實是支持的 wasm 的 enovy 的負(fù)載均衡的請求,并不支持直接請求 http 服務(wù)。所以我們需要先獲取當(dāng)前集群所支持的服務(wù)列表,然后再發(fā)送請求

          找到你要查看 istio 的 istio-ingressgateway pod 名稱

          istioctl proxy-config clusters istio-ingressgateway-556959fc6f-prbbg.istio-system --fqdn sealos.hub -o yaml

          找到其名字規(guī)則為 outbound|5000||sealos.hub 既 :  DIRECTION|PORT||SERVICE_ALL_ADDR

          fn on_http_request_headers(&mut self, _: usize, _: bool) -> Action {
              let upstream = format!("outbound|{}||{}"5000"sealos.hub");
                  self.dispatch_http_call(
                      &upstream,
                      vec![
                          (":method""GET"), //設(shè)置請求方式
                          (":path""/bytes/1"), //設(shè)置請求路徑
                          (":authority""sealos.hub:5000"), //設(shè)置請求地址
                          (":scheme""http"), 
                      ],
                      None,
                      vec![],
                      Duration::from_secs(5),
                  )
                  .unwrap();
                  Action::Pause
              }

          fn on_http_call_response(&mut self, _: u32, _: usize, body_size: usize, _: usize) {
                  if let Some(body) = self.get_http_call_response_body(0, body_size) {
                      if !body.is_empty() && body[0] % 2 == 0 {
                          info!("Access granted.");
                          self.resume_http_request();
                          return;
                      }
                  }
                  info!("Access forbidden.");
                  self.send_http_response(
                      403,
                      vec![("Powered-By""proxy-wasm")],
                      Some(b"Access forbidden.\n"),
                  );
              }
              

          總結(jié)一下:

          1. 使用 dispatch_http_call 方法向其他服務(wù)發(fā)送異步請求,在 on_http_call_response 方法中接收返回結(jié)果。
          2. on_http_call_response 方法中,可以解析返回的結(jié)果,根據(jù)需要進行相應(yīng)的處理。
          3. 如果需要根據(jù)請求結(jié)果來繼續(xù)執(zhí)行之前的數(shù)據(jù),可以調(diào)用 self.resume_http_request()

          以上就是關(guān)于 Rust SDK 的使用方法的簡要說明。通過這些方法,您可以輕松地擴展和定制 Istio 的功能,并在請求的不同階段對流量進行個性化處理。

          引用鏈接

          [1]

          C++ SDK: https://github.com/proxy-wasm/proxy-wasm-cpp-sdk

          [2]

          Rust SDK: https://github.com/proxy-wasm/proxy-wasm-rust-sdk

          [3]

          AssemblyScript SDK: https://github.com/solo-io/proxy-runtime

          [4]

          TinyGo SDK: https://github.com/tetratelabs/proxy-wasm-go-sdk

          [5]

          Istio Wasm Plugin: https://istio.io/latest/zh/docs/reference/config/proxy_extensions/wasm-plugin/


          關(guān)于 Sealos

          Sealos 是一款以 Kubernetes 為內(nèi)核的云操作系統(tǒng)發(fā)行版。它以云原生的方式,拋棄了傳統(tǒng)的云計算架構(gòu),轉(zhuǎn)向以 Kubernetes 為云內(nèi)核的新架構(gòu),使企業(yè)能夠像使用個人電腦一樣簡單地使用云。

          ??GitHub:https://github.com/labring/sealos

          ??官網(wǎng):https://sealos.io

          ??開發(fā)者論壇:https://forum.laf.run

          關(guān)注 Sealos 公眾號與我們一同成長??????

          瀏覽 1036
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产一级内射视频 | 操逼达人 | 国产欧美日韩久久 | 国内一级免费黄色视频在线网展览器的封 | 亚洲不卡在线观看 |