Wasm 插件介绍和开发自定义插件
本章开始进入 Wasm 插件开发篇,主要介绍 Wasm 插件配置、Higress WasmPlugin CRD 以及如何开发自定义插件。
1 测试环境准备
Higress 本地测试环境网关地址是 127.0.0.1,端口是 80 和 443。
准备 echo-server 和 Ingress, 其 YAML 配置如下:
2 Wasm 插件配置
Higress WasmPlugin 在 Istio WasmPlugin 的基础上进行了扩展,支持全局、路由、域名、服务级别的配置。这 4 个配置优先级是:路由级 > 域名级 > 服务级 > 全局,对于没有匹配到具体路由、域名、服务级别的请求才会应用全局配置。
下面以 Higress 官方提供的 custom-response 插件为例进行介绍。custom-response 插件支持配置自定义响应,包括 HTTP 响应状态码、HTTP 响应头,以及 HTTP 响应体。custom-response 插件不仅可以用于模拟响应,还可以根据特定状态码返回自定义响应。例如,在触发网关限流策略时,返回自定义响应。
应用 custom-response 插件,YAML 配置如下:
访问 foo.com,由于请求没有匹配任何域名级或路由级配置,因此最终应用了全局配置。
访问 bar.com,请求匹配域名级配置。
访问 baz.com,请求匹配路由级配置。
测试完成后删除 custom-response
WasmPlugin,避免对后续测试产生影响。
3 Higress WasmPlugin CRD
Higress WasmPlugin CRD 在 Istio WasmPlugin CRD 的基础上进行了扩展,新增 defaultConfig
和 matchRules
字段,用于配置插件的默认配置和路由级、域名级配置。
主要配置如下:
字段名称 | 数据类型 | 填写要求 | 描述 |
---|---|---|---|
pluginName | string | 选填 | 插件名称 |
phase | string | 选填 | 插件插入插件链中的位置,默认是 UNSPECIFIED_PHASE |
priority | int | 选填 | 插件执行优先级,默认为 0,在相同 phase 下,值越大越先处理请求,但越后处理响应 |
imagePullPolicy | string | 选填 | 插件镜像拉取策略,可选值有:UNSPECIFIED_POLICY (默认值)、IfNotPresent 、Always |
imagePullSecret | string | 选填 | 用于拉取 OCI 镜像的凭据。与 WasmPlugin 在同一命名空间中的Kubernetes Secret 的名称 |
url | string | 必填 | Wasm 文件或 OCI 容器的 URL,默认为 oci:// ,引用 OCI 镜像。同时支持 file:// ,用于容器本地的 Wasm 文件,以及 http[s]:// ,用于引用远程托管的 Wasm 文件 |
Sha256 | string | 选填 | 用于验证 Wasm 文件或 OCI 容器的 SHA256 校验和 |
defaultConfig | object | 选填 | 插件默认配置,全局生效于没有匹配具体域名和路由配置的请求 |
defaultConfigDisable | bool | 选填 | 插件默认配置是否失效,默认值是 false |
matchRules | array of object | 选填 | 匹配域名或路由生效的配置 |
phase
配置说明:
字段名称 | 描述 |
---|---|
UNSPECIFIED_PHASE | 在插件过滤器链的末端,在路由器之前插入插件,如果没有指定插件的 phase ,则默认设置为 UNSPECIFIED_PHASE |
AUTHN | 在 Istio 认证过滤器之前插入插件 |
AUTHZ | 在 Istio 授权过滤器之前且在 Istio 认证过滤器之后插入插件 |
STATS | 在 Istio 统计过滤器之前且在 Istio 授权过滤器之后插入插件 |
matchRules
中每一项的配置字段说明:
字段名称 | 数据类型 | 填写要求 | 配置示例 | 描述 |
---|---|---|---|---|
ingress | 字符串数组 | ingress 、domain 和 service 中必填一项 | [“default/foo”, “default/bar”] | 匹配 ingress 资源对象,匹配格式为: 命名空间/ingress名称 |
domain | 字符串数组 | ingress 、domain 和 service 中必填一项 | [“example.com”, “*.test.com”] | 匹配域名,支持泛域名 |
service | 字符串数组 | ingress 、domain 和 service 中必填一项 | [“echo-server.higress-course.svc.cluster.local”] | 匹配服务名称 |
config | 对象 | 选填 | - | 匹配后生效的插件配置 |
configDisable | bool | 选填 | false | 配置是否生效,默认设置为 false |
4 自定义插件开发
开发一个简单日志插件 easy-logger
, 这个插件根据配置记录请求和响应到网关日志中。整个过程涉及到插件开发环境准备、开发和测试、部署和验证。
4.1 环境准备
环境准备如下:
- Docker 官方安装连接:https://docs.docker.com/engine/install/
- Go 版本: >= 1.19 (需要支持范型特性),官方安装链接:https://go.dev/doc/install
如果选择用 TinyGo 在本地构建 Wasm 文件,再拷贝到 Docker 镜像中,需要安装 TinyGo,其环境要求如下:
- TinyGo 版本: >= 0.28.1 (建议版本 0.28.1) 官方安装链接:https://tinygo.org/getting-started/install/
4.2 开发和测试
4.2.1 初始化工程目录
- 新建一个工程目录文件 easy-logger。
- 在所建目录下执行以下命令,初始化 Go 工程。
go.mod 文件中 go 版本需要设置为 1.19,由于在 4.3.3 节中我们将使用 1.19 版本的 wasm-go-builder 镜像来构建插件,因此需要保持两者的 go 版本一致。
- 国内环境可能需要设置下载依赖包的代理
- 下载构建插件的依赖
4.2.2 编写 main.go 文件
首先,我们编写 easy-logger 插件的基本框架,暂时只读取我们设置的配置参数,不在请求和响应阶段进行任何处理。
Higress 插件 SDK 开发涉及到以下内容:
- wrapper.HttpContext:请求上下文。
- LoggerConfig:自定义插件配置。
- wrapper.Log:插件日志工具。
- wrapper.ProcessXXXX:插件回调钩子函数。
- proxywasm:提供插件工具函数包。
wrapper 插件回调钩子函数包含以下函数,可以根据实际业务需求选择设置以下钩子函数:
- wrapper.ParseConfigBy(parseConfig):解析插件配置。
- wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders):设置自定义函数处理请求头。
- wrapper.ProcessRequestBodyBy(onHttpRequestBody):设置自定义函数处理请求体。
- wrapper.ProcessResponseHeadersBy(onHttpResponseHeaders):设置自定义函数处理响应头。
- wrapper.ProcessResponseBodyBy(onHttpResponseBody):设置自定义函数处理响应体。
- wrapper.ProcessStreamingRequestBodyBy(onHttpStreamingRequestBody):设置自定义函数处理流式请求体。
- wrapper.ProcessStreamingResponseBodyBy(onHttpStreamingResponseBody):设置自定义函数处理流式响应体。
关于 Higress 插件 SDK 内容会在后续章节中详细展开。
4.3.3 本地测试
- 第一步:在插件目录下创建文件 envoy.yaml,内容如下。网关在 10000 端口监听 HTTP 请求,将请求转发到 echo-server 服务。
插件通过本地文件的方式加载到 Envoy 中,插件配置的如下:
- 第二步:在插件目录下创建文件 docker-compose.yaml,内容如下:
- 第三步:在插件目录下创建文件 Dockerfile,内容如下:
- 第四步:在插件目录下创建文件 Makefile,内容如下:
请将 Makefile 文件中镜像仓库地址 REGISTRY ?= higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/
换成自己的镜像仓库地址。
其命令说明如下:
make local-docker-build
: 本地 Docker 环境构建插件,生成插件文件 ./build/plugin.wasm。make local-build
: 本地 TinyGo 构建插件,生成插件文件 ./build/plugin.wasm。make local-run
: 本地启动测试环境。PLUGIN_NAME=easy-logger PLUGIN_VERSION=1.0.0 make build-image
构建 easy-logger 插件镜像,插件版本为 1.0.0。PLUGIN_NAME=easy-logger PLUGIN_VERSION=1.0.0 make build-push
构建 easy-logger 插件镜像,插件版本为 1.0.0,同时推送到镜像仓库。make local-docker-all
: 本地 Docker 环境构建插件,生成插件文件 build/plugin.wasm,同时启动本地测试环境。make local-all
: 本地 TinyGo 构建插件,生成插件文件 ./build/plugin.wasm,同时启动本地测试环境。
注意用 TinyGo 本地构建命令如下:
- 第五步:本地 Docker 环境构建和启动测试环境
本地 Docker 环境构建和启动测试环境,命令如下:
本地启动测试环境后,插件目录整体文件结构如下:
执行以下命令通过网关访问 echo-server。
查看插件目录下 envoy.log 文件,可以看到 easy-logger 插件的日志输出。
到这里表示整体开发和测试环境已经完成,下面就是完善插件功能,然后重新测试。
4.3 完善插件功能
接下来,我们将通过自定义函数来处理请求和响应信息。通过设置插件参数,我们可以控制是否打印请求和响应信息,并根据指定的响应状态码决定是否记录响应内容。
4.4 部署插件和验证
- 构建插件镜像
- 部署插件
easy-logger 插件部署 YAML 如下:
- 验证插件
- 设置网关插件的日志级别为 debug。
- 请求访问
- 查看网关的日志,可以看到输出了请求和响应的详细信息