×

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

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

以下是相同的示例,但这次使用开放容器倡议 (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
描述

<空>

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

IfNotPresent

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

Always

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

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

表 5. Struct
字段 类型 描述

字段

map<string, Value>

动态类型值的映射。

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

表 6. PluginPhase
字段 描述

<空>

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

AUTHN

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

AUTHZ

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

STATS

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

部署 WasmPlugin 资源

您可以使用 WasmPlugin 资源启用 Red Hat OpenShift Service Mesh 扩展。在此示例中,istio-system 是 Service Mesh 控制平面项目的名称。以下示例创建了一个执行 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

扩展的名称。

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

description

扩展的描述。

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

version

扩展的版本。

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

phase

扩展的默认执行阶段。

这是必需字段。

priority

扩展的默认优先级。

这是必需字段。

module

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

这是必需字段。

ServiceMeshExtension 参考

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

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

  2. 将其打包到容器中。

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

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

metadata.namespace

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

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 是 Service Mesh 控制平面项目的名称。

创建新的 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 资源

在 Red Hat OpenShift Service Mesh 2.2 版本中已弃用的 ServiceMeshExtension API 已在 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资源。