go+proxy-wasm-go-sdk+tinygo 开发 wasm
一、创建项目
go mod init xxxxxx
二、安装proxy-wasm-go-sdk
go get github.com/tetratelabs/proxy-wasm-go-sdk
三、创建main.go 文件
touch main.go
四、编辑代码
1 package main 2 3 import ( 4 "strconv" 5 6 "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm" 7 "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types" 8 ) 9 10 type vmContext struct { 11 types.DefaultVMContext 12 } 13 14 type pluginContext struct { 15 types.DefaultPluginContext 16 } 17 18 type httpHeaders struct { 19 types.DefaultHttpContext 20 contextID uint32 21 authority string 22 } 23 24 func main() { 25 proxywasm.SetVMContext(&vmContext{}) 26 } 27 28 func (*vmContext) NewPluginContext(contextId uint32) types.PluginContext { 29 return &pluginContext{} 30 } 31 32 func (*pluginContext) NewHttpContext(contextID uint32) types.HttpContext { 33 return &httpHeaders{contextID: contextID} 34 } 35 36 func (ctx *httpHeaders) OnHttpRequestHeaders(numHeaders int, endOfStream bool) types.Action { 37 authority, err := proxywasm.GetHttpRequestHeader(":authority") 38 if err != nil { 39 return types.ActionContinue 40 } 41 ctx.authority = authority 42 return types.ActionContinue 43 } 44 45 func (ctx *httpHeaders) OnHttpResponseHeaders(numHeaders int, endOfStream bool) types.Action { 46 status, err := proxywasm.GetHttpResponseHeader(":status") 47 if err != nil { 48 proxywasm.LogErrorf("responseCode:%v", err) 49 return types.ActionContinue 50 } else { 51 statusi, err := strconv.ParseInt(status, 0, 64) 52 if err != nil { 53 return types.ActionContinue 54 } 55 if statusi >= 400 { 56 proxywasm.RemoveHttpResponseHeader("content-length") 57 headers := [][2]string{} 58 headers = append(headers, [2]string{"content-type", "text/html;charset=UTF-8"}) 59 err = proxywasm.SendHttpResponse(uint32(statusi), 60 headers, 61 []byte("<html><body>"+status+"</body></html>"), 62 -1) 63 if err != nil { 64 proxywasm.LogErrorf("更改Body出现问题:%v", err) 65 } 66 } 67 } 68 69 return types.ActionContinue 70 }
代码演示了 当状态码大于等于400 就返回一段html 展示状态,隐藏真实的未经处理错误信息(可能会暴露一些服务器、代码信息)。
五、一些常用的方法
5.1. 启动加载配置项
OnVMStart
OnPluginStart
5.2. http调用
proxywasm.DispatchHttpCall
5.3. 共享数据
SetSharedData
GetShareData
5.4. 请求头、响应头操作 这个打印一下就知道有哪些了
Add、Remove、Replace
5.5. 获取属性数据
1 var protocolAttr []string = []string{"request", "protocol"} 2 var clusterName []string = []string{"cluster_name"} 3 var responseCode []string = []string{"response", "code"} 4 var grpcStatus []string = []string{"response", "grpc_status"} 5 6 proxywasm.GetProperty(responseCode)
能获取到的属性,参考文档
https://www.envoyproxy.io/docs/envoy/v1.24.0/intro/arch_overview/advanced/attributes.html?highlight=property
(我当时写代码的时候知道能获取属性,但是不知道有哪些属性,这个给我愁坏了)
六. 打包
tinygo build -o xxx.wasm -scheduler=none -target=wasi ./main.go
七、发布
7.1 envoy 配置文件部署
- name: envoy.filters.http.wasm typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm config: name: "xxx" root_id: "xxx" configuration: '@type': type.googleapis.com/google.protobuf.StringValue value: | { } vm_config: runtime: "envoy.wasm.runtime.v8" configuration: '@type': type.googleapis.com/google.protobuf.StringValue value: {} code: local: filename: './xxx.wasm'
7.2 发布istio
7.2.1 envoyfilter发布
--- apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: xxx namespace: xxx spec: configPatches: - applyTo: EXTENSION_CONFIG patch: operation: INSERT_BEFORE value: name: xxx typed_config: '@type': type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm config: configuration: '@type': type.googleapis.com/google.protobuf.StringValue value: | {} root_id: xxx vm_config: code: remote: http_uri: timeout: 10s uri: 'https://xxxxxx/betapreauth.wasm' configuration: '@type': type.googleapis.com/google.protobuf.StringValue value: | { } runtime: envoy.wasm.runtime.v8 vm_id: xxx - applyTo: HTTP_FILTER match: listener: filterChain: filter: name: envoy.filters.network.http_connection_manager subFilter: name: envoy.filters.http.router patch: operation: INSERT_BEFORE value: config_discovery: config_source: ads: {} type_urls: - type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm name: xxx workloadSelector: labels: app: xxxx
7.2.2 wasmplug
Docker打包镜像
FROM tinygo/tinygo as build WORKDIR /src COPY . . RUN go env -w GOPROXY=https://goproxy.cn,direct RUN tinygo build -o xxxx.wasm -scheduler=none -target=wasi ./main.go FROM scratch as final COPY --from=build /src/betaerrconvert.wasm ./plugin.wasm
docker build -t xxxx -f Dockerfile .
docker push xxxxx
yaml部署文件
---
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
name: xxxx
namespace: istio-system
spec:
imagePullPolicy: IfNotPresent
imagePullSecret: xxxx
selector:
matchLabels:
app: istio-ingressgateway
url: 'oci://xxxxx'
https://istio.io/latest/docs/reference/config/proxy_extensions/wasm-plugin/