×

您可以使用WebAssembly扩展直接向Red Hat OpenShift Service Mesh代理添加新功能。这使您可以将更多常用功能从应用程序中移除,并使用编译为WebAssembly字节码的单一语言来实现它们。

WebAssembly扩展在IBM Z®和IBM Power®上不受支持。

WebAssembly模块概述

WebAssembly模块可以在许多平台上运行,包括代理,并具有广泛的语言支持、快速执行和默认沙箱安全模型。

Red Hat OpenShift Service Mesh扩展是Envoy HTTP过滤器,这赋予它们广泛的功能

  • 操作请求和响应的主体和标头。

  • 对请求路径中不存在的服务(例如身份验证或策略检查)进行带外HTTP请求。

  • 用于过滤器相互通信的旁路数据存储和队列。

创建新的WebAssembly扩展时,请使用WasmPlugin API。ServiceMeshExtension API已在Red Hat OpenShift Service Mesh 2.2版本中弃用,并在Red Hat OpenShift Service Mesh 2.3版本中移除。

编写Red Hat OpenShift Service Mesh扩展有两个部分

  1. 您必须使用公开proxy-wasm API的SDK编写扩展,并将其编译为WebAssembly模块。

  2. 然后,您必须将模块打包到容器中。

支持的语言

您可以使用任何编译为WebAssembly字节码的语言来编写Red Hat OpenShift Service Mesh扩展,但以下语言具有现有的SDK,这些SDK公开了proxy-wasm API,以便可以直接使用。

表1. 支持的语言
语言 维护者 仓库

AssemblyScript

solo.io

solo-io/proxy-runtime

C++

proxy-wasm团队(Istio社区)

proxy-wasm/proxy-wasm-cpp-sdk

Go

tetrate.io

tetratelabs/proxy-wasm-go-sdk

Rust

proxy-wasm团队(Istio社区)

proxy-wasm/proxy-wasm-rust-sdk

WasmPlugin容器格式

Istio在其Wasm Plugin机制中支持开放容器倡议 (OCI) 镜像。您可以将Wasm Plugin作为容器镜像分发,并且可以使用spec.url字段引用容器注册表位置。例如,quay.io/my-username/my-plugin:latest

因为WASM模块的每个执行环境(运行时)都可以具有特定于运行时的配置参数,所以WASM镜像可以由两层组成

  • plugin.wasm(必需)- 内容层。此层包含包含WebAssembly模块字节码的.wasm二进制文件,供运行时加载。您必须将此文件命名为plugin.wasm

  • runtime-config.json(可选)- 配置层。此层包含描述目标运行时模块元数据的JSON格式字符串。根据目标运行时,配置层还可以包含其他数据。例如,WASM Envoy过滤器的配置包含过滤器上可用的root_ids。

WasmPlugin API参考

WasmPlugins API提供了一种通过WebAssembly过滤器扩展Istio代理提供的功能的机制。

您可以部署多个WasmPlugins。phasepriority设置决定执行顺序(作为Envoy的过滤器链的一部分),允许配置用户提供的WasmPlugins和Istio的内部过滤器之间的复杂交互。

在以下示例中,身份验证过滤器实现 OpenID 流程并将 JSON Web 令牌 (JWT) 放入授权标头中。Istio 身份验证会使用此令牌并将其部署到入口网关。WasmPlugin 文件位于代理 sidecar 文件系统中。请注意字段url

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

以下是相同的示例,但这次使用 Open Container Initiative (OCI) 镜像而不是文件系统中的文件。请注意字段urlimagePullPolicyimagePullSecret

apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: openid-connect
  namespace: istio-system
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
表 2. WasmPlugin 字段参考
字段 类型 描述 必填

spec.selector

WorkloadSelector

用于选择应应用此插件配置的特定 Pod/VM 集的条件。如果省略,则此配置将应用于同一命名空间中的所有工作负载实例。如果WasmPlugin字段存在于配置根命名空间中,它将应用于任何命名空间中所有适用的工作负载。

spec.url

字符串

Wasm 模块或 OCI 容器的 URL。如果不存在方案,则默认为oci://,引用 OCI 镜像。其他有效方案包括file://(用于引用代理容器本地存在的 .wasm 模块文件)和http[s]://(用于引用远程托管的 .wasm 模块文件)。

spec.sha256

字符串

将用于验证 Wasm 模块或 OCI 容器的 SHA256 校验和。如果url字段已引用 SHA256(使用@sha256:表示法),则它必须与该字段的值匹配。如果通过标签引用 OCI 镜像并且设置了此字段,则在拉取后,其校验和将与该字段的内容进行验证。

spec.imagePullPolicy

PullPolicy

获取 OCI 镜像时要应用的拉取行为。仅当通过标签而不是 SHA 引用镜像时才相关。默认为IfNotPresent,但当url字段中引用 OCI 镜像且使用latest标签时,默认值为Always,这与 K8s 行为一致。如果url字段直接使用file://http[s]://引用 Wasm 模块,则忽略此设置。

spec.imagePullSecret

字符串

用于 OCI 镜像拉取的凭据。与WasmPlugin对象位于同一命名空间中的密钥名称,其中包含用于在拉取镜像时对注册表进行身份验证的拉取密钥。

spec.phase

PluginPhase

确定在此过滤器链中注入此WasmPlugin对象的位置。

spec.priority

int64

确定具有相同phase值的WasmPlugins对象的顺序。当多个WasmPlugins对象应用于同一阶段的同一工作负载时,它们将按优先级和降序应用。如果未设置priority字段,或两个WasmPlugins对象具有相同的值,则顺序将由WasmPlugins对象的名称和命名空间决定。默认为0

spec.pluginName

字符串

Envoy 配置中使用的插件名称。某些 Wasm 模块可能需要此值来选择要执行的 Wasm 插件。

spec.pluginConfig

结构体

将传递给插件的配置。

spec.pluginConfig.verificationKey

字符串

用于验证已签名 OCI 镜像或 Wasm 模块签名的公钥。必须以 PEM 格式提供。

WorkloadSelector对象指定用于确定是否可以将过滤器应用于代理的条件。匹配条件包括与代理关联的元数据、工作负载实例信息(例如附加到 Pod/VM 的标签)或代理在初始握手期间向 Istio 提供的任何其他信息。如果指定多个条件,则所有条件都必须匹配才能选择工作负载实例。目前,仅支持基于标签的选择机制。

表 3. WorkloadSelector
字段 类型 描述 必填

matchLabels

map<string, string>

指示应应用策略的特定 Pod/VM 集的一个或多个标签。标签搜索的范围仅限于资源所在的配置命名空间。

PullPolicy对象指定获取 OCI 镜像时要应用的拉取行为。

表 4. PullPolicy
描述

<empty>

默认为IfNotPresent,但对于带有 latest 标签的 OCI 镜像,默认为Always

IfNotPresent

如果之前已拉取现有版本的镜像,则将使用该版本。如果本地不存在任何版本的镜像,我们将拉取最新版本。

Always

应用此插件时始终拉取镜像的最新版本。

Struct表示结构化数据值,由映射到动态类型值的字段组成。在某些语言中,Struct可能由本机表示支持。例如,在 JavaScript 等脚本语言中,结构体表示为对象。

表 5. Struct
字段 类型 描述

fields

map<string, Value>

动态类型值的映射。

PluginPhase指定在过滤器链中注入插件的阶段。

表 6. PluginPhase
字段 描述

<empty>

控制平面决定在哪里插入插件。这通常位于过滤器链的末尾,紧接在路由器之前。如果插件与其他插件无关,请不要指定 PluginPhase。

AUTHN

在 Istio 身份验证过滤器之前插入插件。

AUTHZ

在 Istio 授权过滤器之前以及 Istio 身份验证过滤器之后插入插件。

STATS

在 Istio 统计过滤器之前以及 Istio 授权过滤器之后插入插件。

部署WasmPlugin资源

您可以使用WasmPlugin资源启用 Red Hat OpenShift Service Mesh 扩展。在此示例中,istio-system是服务网格控制平面项目的名称。以下示例创建执行 OpenID Connect 流程以对用户进行身份验证的openid-connect过滤器。

步骤
  1. 创建以下示例资源

    示例 plugin.yaml
    apiVersion: extensions.istio.io/v1alpha1
    kind: WasmPlugin
    metadata:
      name: openid-connect
      namespace: istio-system
    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
  2. 使用以下命令应用您的plugin.yaml文件

    $ oc apply -f plugin.yaml

ServiceMeshExtension容器格式

您必须有一个包含 WebAssembly 模块字节码的.wasm文件,以及容器文件系统根目录中的manifest.yaml文件,才能使您的容器镜像成为有效的扩展镜像。

创建新的WebAssembly扩展时,请使用WasmPlugin API。ServiceMeshExtension API已在Red Hat OpenShift Service Mesh 2.2版本中弃用,并在Red Hat OpenShift Service Mesh 2.3版本中移除。

manifest.yaml
schemaVersion: 1

name: <your-extension>
description: <description>
version: 1.0.0
phase: PreAuthZ
priority: 100
module: extension.wasm
表 7. manifest.yml 字段参考
字段 描述 必填

schemaVersion

用于清单模式的版本控制。目前唯一可能的值是1

这是必填字段。

name

您的扩展名。

此字段仅为元数据,当前未使用。

描述

您的扩展程序的描述。

此字段仅为元数据,当前未使用。

版本

您的扩展程序的版本。

此字段仅为元数据,当前未使用。

阶段

您的扩展程序的默认执行阶段。

这是必填字段。

优先级

您的扩展程序的默认优先级。

这是必填字段。

模块

从容器文件系统的根目录到您的 WebAssembly 模块的相对路径。

这是必填字段。

ServiceMeshExtension 参考

ServiceMeshExtension API 提供了一种机制,可以通过 WebAssembly 过滤器扩展 Istio 代理提供的功能。编写 WebAssembly 扩展程序包括两个部分

  1. 使用公开 proxy-wasm API 的 SDK 编写您的扩展程序,并将其编译为 WebAssembly 模块。

  2. 将其打包到容器中。

创建新的 WebAssembly 扩展程序时,请使用WasmPlugin API。ServiceMeshExtension API 已在 Red Hat OpenShift Service Mesh 2.2 版本中弃用,并在 Red Hat OpenShift Service Mesh 2.3 版本中移除。

表 8. ServiceMeshExtension 字段参考
字段 描述

metadata.namespace

ServiceMeshExtension 源的metadata.namespace字段具有特殊的语义:如果它等于控制平面命名空间,则扩展程序将应用于服务网格中与其workloadSelector值匹配的所有工作负载。部署到任何其他网格命名空间时,它将仅应用于同一命名空间中的工作负载。

spec.workloadSelector

spec.workloadSelector字段与Istio Gateway 资源spec.selector字段具有相同的语义。它将根据 Pod 标签匹配工作负载。如果未指定workloadSelector值,则扩展程序将应用于命名空间中的所有工作负载。

spec.config

这是一个结构化字段,将传递给扩展程序,其语义取决于您正在部署的扩展程序。

spec.image

指向包含扩展程序的镜像的容器镜像 URI。

spec.phase

阶段决定了扩展程序在过滤器链中的注入位置,相对于现有的 Istio 功能(如身份验证、授权和指标生成)。有效值为:PreAuthN、PostAuthN、PreAuthZ、PostAuthZ、PreStats、PostStats。此字段默认为扩展程序的manifest.yaml文件中设置的值,但用户可以覆盖它。

spec.priority

如果将多个具有相同spec.phase值的扩展程序应用于相同的工作负载实例,则spec.priority值将决定执行顺序。优先级较高的扩展程序将首先执行。这允许相互依赖的扩展程序。此字段默认为扩展程序的manifest.yaml文件中设置的值,但用户可以覆盖它。

部署ServiceMeshExtension资源

您可以使用ServiceMeshExtension资源启用 Red Hat OpenShift Service Mesh 扩展程序。在此示例中,istio-system是服务网格控制平面项目的名称。

创建新的 WebAssembly 扩展程序时,请使用WasmPlugin API。ServiceMeshExtension API 已在 Red Hat OpenShift Service Mesh 2.2 版本中弃用,并在 Red Hat OpenShift Service Mesh 2.3 版本中移除。

有关使用 Rust SDK 构建的完整示例,请查看header-append-filter。它是一个简单的过滤器,它将一个或多个标头附加到 HTTP 响应中,其名称和值取自扩展程序的config字段。请参见下面代码段中的示例配置。

步骤
  1. 创建以下示例资源

    示例 ServiceMeshExtension 资源 extension.yaml
    apiVersion: maistra.io/v1
    kind: ServiceMeshExtension
    metadata:
      name: header-append
      namespace: istio-system
    spec:
      workloadSelector:
        labels:
          app: httpbin
      config:
        first-header: some-value
        another-header: another-value
      image: quay.io/maistra-dev/header-append-filter:2.1
      phase: PostAuthZ
      priority: 100
  2. 使用以下命令应用您的extension.yaml文件

    $ oc apply -f <extension>.yaml

ServiceMeshExtension资源迁移到WasmPlugin资源

ServiceMeshExtension API 已在 Red Hat OpenShift Service Mesh 2.2 版本中弃用,并在 Red Hat OpenShift Service Mesh 2.3 版本中移除。如果您正在使用ServiceMeshExtension API,则必须迁移到WasmPlugin API 才能继续使用您的 WebAssembly 扩展程序。

这两个 API 非常相似。迁移包括两个步骤

  1. 重命名您的插件文件并更新模块打包。

  2. 创建一个引用更新的容器镜像的WasmPlugin资源。

API 更改

新的WasmPlugin API 与ServiceMeshExtension类似,但有一些区别,尤其是在字段名称方面

表 9.ServiceMeshExtensionsWasmPlugin之间的字段更改
ServiceMeshExtension WasmPlugin

spec.config

spec.pluginConfig

spec.workloadSelector

spec.selector

spec.image

spec.url

spec.phase有效值:PreAuthN、PostAuthN、PreAuthZ、PostAuthZ、PreStats、PostStats

spec.phase有效值:<empty>、AUTHN、AUTHZ、STATS

以下是如何将ServiceMeshExtension资源转换为WasmPlugin资源的示例。

ServiceMeshExtension 资源
apiVersion: maistra.io/v1
kind: ServiceMeshExtension
metadata:
  name: header-append
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      app: httpbin
  config:
    first-header: some-value
    another-header: another-value
  image: quay.io/maistra-dev/header-append-filter:2.2
  phase: PostAuthZ
  priority: 100
等效于上述 ServiceMeshExtension 的新的 WasmPlugin 资源
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: header-append
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: httpbin
  url: oci://quay.io/maistra-dev/header-append-filter:2.2
  phase: STATS
  pluginConfig:
    first-header: some-value
    another-header: another-value

容器镜像格式更改

新的WasmPlugin容器镜像格式与ServiceMeshExtensions类似,但存在以下差异

  • ServiceMeshExtension容器格式要求在容器文件系统的根目录中有一个名为manifest.yaml的元数据文件。WasmPlugin容器格式不需要manifest.yaml文件。

  • 以前可以具有任何文件名的.wasm文件(实际插件)现在必须命名为plugin.wasm,并且必须位于容器文件系统的根目录中。

迁移到WasmPlugin资源

要将您的 WebAssembly 扩展程序从ServiceMeshExtension API 升级到WasmPlugin API,您需要重命名您的插件文件。

先决条件
  • ServiceMeshControlPlane已升级到 2.2 或更高版本。

步骤
  1. 更新您的容器镜像。如果插件已位于容器内的/plugin.wasm中,请跳到下一步。如果不是

    1. 确保插件文件名为plugin.wasm。您必须将扩展文件命名为plugin.wasm

    2. 确保插件文件位于根(/)目录中。您必须将扩展文件存储在容器文件系统的根目录中。

    3. 重新构建您的容器镜像并将其推送到容器注册表。

  2. 删除ServiceMeshExtension资源并创建一个引用您构建的新容器镜像的WasmPlugin资源。