WebAssembly(WASM)是一种有效的可移植二进制指令格式,可以用于扩展ASM数据平面的功能。然而在服务网格内构建、部署和运行Wasm Filter较为复杂。本文介绍如何使用ORAS简化基于WASM的服务网格扩展功能。
前提条件
已创建ASM实例,并添加集群到ASM实例。具体操作,请参见创建ASM实例和添加集群到ASM实例。
说明ASM实例必须为v1.8.3.17-g1399628c-aliyun或者以上版本。
使用kubectl连接到ASM实例。具体操作,请参见通过控制面kubectl访问Istio资源。
已部署应用到ASM实例。具体操作,请参见部署应用到ASM实例。
已创建Istio虚拟服务和入口网关。具体操作,请参见使用Istio资源实现版本流量路由。
已创建并编译一个Wasm Filter二进制文件。本文以将过滤器的头添加到响应头的Wasm Filter为例。
背景信息
ASM提供了对WASM技术的支持,可以把扩展的Wasm Filter通过ASM部署到数据面集群中相应的Envoy代理中,从而扩展数据平面的功能。ORAS是基于OCI Artifacts规范的OCI注册表存储,可以显著简化OCI注册库中内容的存储过程。基于WASM扩展ASM数据平面功能时,可以使用ORAS对功能扩展过程进行简化。
上传Wasm Filter
使用ORAS CLI工具上传Wasm Filter到镜像仓库,以阿里云容器镜像服务企业版ACR EE为例。
创建容器镜像仓库并获取登录镜像仓库的账号。具体操作,请参见使用企业版实例推送和拉取镜像。
执行以下命令,登录镜像仓库。
oras login --username=<登录账号> acree-1-registry.cn-hangzhou.cr.aliyuncs.com
执行以下命令,将Wasm Filter推送到镜像仓库。
oras push acree-1-registry.cn-hangzhou.cr.aliyuncs.com/******/asm-test:v0.1 --manifest-config runtime-config.json:application/vnd.module.wasm.config.v1+json example-filter.wasm:application/vnd.module.wasm.content.layer.v1+wasm
在容器镜像仓库查看推送的Wasm Filter。
- 登录容器镜像服务控制台。
- 在顶部菜单栏,选择所需地域。
- 在左侧导航栏,选择实例列表。
- 在实例列表页面单击目标企业版实例。
在企业版实例管理页面左侧导航栏选择 。
在镜像仓库页面单击目标镜像仓库的名称。
在镜像仓库管理页面左侧导航栏单击镜像版本,在镜像版本页面可以看到上传的Wasm Filter。
启用使用WASM的功能
通过控制台启用使用WASM的功能
登录ASM控制台。
在左侧导航栏,选择 。
在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
在网格详情页面左侧导航栏,选择 ,然后在右侧页面,单击功能设置。
在功能设置更新面板数据面扩展区域选中启用基于WebAssembly的服务网格扩展,然后单击确定。
说明在功能设置更新面板数据面扩展区域去掉选中启用基于WebAssembly的服务网格扩展,可以关闭使用WASM的功能。
通过命令行启用使用WASM的功能
通过Aliyun CLI可以启用服务网格中的使用WASM的功能。执行以下命令,启用使用WASM的功能。
aliyun servicemesh UpdateMeshFeature --ServiceMeshId=xxxx --WebAssemblyFilterEnabled=true
您也可以执行以下命令,关闭使用WASM的功能。
aliyun servicemesh UpdateMeshFeature --ServiceMeshId=xxxx --WebAssemblyFilterEnabled=false
在ASM中使用WASM
服务网格ASM产品提供了一个ASMFilterDeployment资源以及相关的Controller组件。这个Controller组件会监听ASMFilterDeployment资源对象的情况,并进行以下操作:
创建用于控制面的Istio EnvoyFilter Custom Resource,并推送到对应的ASM控制面Istio中。
从镜像仓库中拉取对应的Wasm Filter镜像, 并挂载到对应的Workload Pod中。
使用WASM流程
启用使用WASM的功能,启用后,自动部署一个DaemonSet类型的asmwasm-controller到ACK集群中。
asmwasm-controller监听一个ConfigMap,该configmap存放了拉取的Wasm Filter的镜像仓库地址。
如果需要授权认证,该asmwasm-controller会根据定义的pullSecret值获得相应的Secret值。
asmwasm-controller会调用ORAS API从注册库中动态拉取Wasm Filter。
asmwasm-controller使用HostPath方式挂载Volume, 所以拉取的Wasm Filter会落盘到对应的节点上。

操作步骤
执行以下命令,启用使用WASM的功能。
aliyun servicemesh UpdateMeshFeature --ServiceMeshId=xxxxxx --WebAssemblyFilterEnabled=true
在ACK集群中创建用来访问镜像仓库的Secret。
关于Secret的详细信息,请参见Secret。
使用以下内容,创建名为myconfig.json的文件。
{ "auths":{ "**********.cn-hangzhou.cr.aliyuncs.com":{ "username":"*****username*****", "password":"*****password*****" } } }
**********.cn-hangzhou.cr.aliyuncs.com
:镜像仓库地址。username
:镜像仓库用户名。password
:镜像仓库密码。
执行以下命令,创建Sercet。
说明Secret名字必须为asmwasm-cache,命名空间为istio-system。
kubectl create secret generic asmwasm-cache -n istio-system --from-file=.dockerconfigjson=myconfig.json --type=kubernetes.io/dockerconfigjson
部署ASMFilterDeployment资源。
使用以下内容,创建一个名为filter.yaml的文件。
apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMFilterDeployment metadata: name: details-v1-wasmfiltersample spec: workload: kind: Deployment labels: app: details version: v1 filter: patchContext: 'SIDECAR_INBOUND' parameters: '{"name":"hello","value":"hello details"}' image: 'acree-1-registry.cn-hangzhou.cr.aliyuncs.com/asm/asm-test:v0.1' rootID: 'my_root_id' id: 'details-v1-wasmfiltersample.default'
workload
下的参数解释:kind
:目标工作负载的类型。labels
:筛选的条件。
filter
下的参数解释:patchContext
:生效的上下文阶段。parameters
:运行Wasm Filter所需的配置参数。image
:Wasm Fitler对应的镜像仓库地址。rootID
:Wasm Filter扩展插件对应的RootID。id
:该Wasm Filter的唯一ID。
执行以下命令,部署ASMFilterDeployment资源。
kubectl apply -f filter.yaml
ASMFilterDeployment部署后,会自动生成EnvoyFilter。其中match片段中定义了envoy.router,patch片段中定义了INSERT_BEFORE。
match片段
patch片段
查看Workload。
apiVersion: extensions/v1beta1 kind: Deployment metadata: .… spec: …. template: metadata: annotations: sidecar.istio.io/userVolume: '[{"name":"wasmfilters-dir","hostPath":{"path":"/var/local/lib/wasm-filters"}}]’ sidecar.istio.io/userVolumeMount: '[{"mountPath":"/var/local/lib/wasm-filters","name":"wasmfilters-dir"}]'
可以看到Wasm Filter文件以HostPath方式挂载到Proxy容器中。
验证Wasm Filter是否生效
执行以下命令,登录到productpage Pod的istio-proxy容器中并请求details服务。
kubectl exec -ti deploy/productpage-v1 -c istio-proxy -- curl -v http://details:9080/details/123
预期输出:
* Trying 172.21.9.191...
* TCP_NODELAY set
* Connected to details (172.21.9.191) port 9080 (#0)
> GET /details/123 HTTP/1.1
> Host: details:9080
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
xxxxxxx
< resp-header-demo: added by our filter
xxxxx
* Connection #0 to host details left intact
xxxxx
返回结果中,可以看到过滤器的头添加到响应头中。