WASM插件
istio为什么使用 WASM
通过 WASM 的实现,我们可以得到:
-
敏捷性 - wasm 可以动态加载业务逻辑到正在运行的 Envoy 进程中,而无需停止或重新编译。
-
可维护性 - 我们不必更改 Envoy 的代码库来扩展其功能。
-
多样性 - 流行的编程语言如 C/C++ 和 Rust 可以编译成 WASM,因此开发人员可以使用他们选择的编程语言来实现过滤器。
-
可靠性和隔离 - 过滤器部署到 VM(沙箱)中,因此与托管 Envoy 进程本身隔离(例如,当 WASM 过滤器崩溃时,它不会影响 Envoy 进程)。
-
安全性 - 由于过滤器通过定义良好的 API 与主机(Envoy 代理)通信,因此它们可以访问并且只能修改有限数量的连接或请求属性。
它还具有一些需要考虑的缺点:
- 性能大约是原生 C++ 的 70%
- 由于需要启动一个或多个 WASM 虚拟机,因此内存使用量会变的更高
envoy 代理 WASM SDK
Envoy Proxy 在基于堆栈的虚拟机中运行 WASM 过滤器,因此过滤器的内存与主机环境隔离。嵌入主机(Envoy Proxy)和 WASM 过滤器之间的所有交互都是通过 Envoy Proxy WASM SDK 提供的函数和回调实现的。
WASM SDK 支持多种编程语言的实现,例如:
- C++
- rust
- AssemblyScript
- Go
在这篇文章中,我们将讨论如何使用Go Envoy Proxy WASM SDK为 Envoy 编写 WASM 过滤器。我们不打算详细讨论 Envoy Proxy WASM SDK 的 API,因为它超出了本文的范围。但是,我们将涉及掌握为 Envoy 编写 WASM 过滤器的基础知识所必需的一些内容。 我们的过滤器实现必须派生自以下两个类: 当加载 WASM 插件(包含过滤器的 WASM 二进制文件)时,会创建一个根上下文。根上下文与 VM 实例具有相同的生命周期,它执行我们的过滤器并用于:
type rootContext struct {
// You'd better embed the default root context
// so that you don't need to reimplement all the methods by yourself.
proxywasm.DefaultRootContext
}
type httpHeaders struct {
// we must embed the default context so that you need not to reimplement all the methods by yourself
proxywasm.DefaultHttpContext
contextID uint32
}
- 初始化wasm项目
$ solarctl wasm init demo
buildVersion = unknown, buildGitRevision = unknown, buildStatus = unknown, buildTag = unknown, buildHub = unknown
Use the arrow keys to navigate: ↓ ↑ → ←
? What language do you wish to use for the filter:
▸ cpp
rust
assemblyscript
tinygo
项目结构如下:
demo
|-- go.mod
|-- main.go
|-- runtime-config.json
- 我们在代码中加上我们所需的代码 例如: 在http的头中加上一个key=“hello” value=“world”
// Override DefaultHttpContext.
func (ctx *httpHeaders) OnHttpResponseHeaders(numHeaders int, endOfStream bool) types.Action {
if err := proxywasm.SetHttpResponseHeader("hello", "world"); err != nil {
proxywasm.LogCriticalf("failed to set response header: %v", err)
}
return types.ActionContinue
}
- 编译demo项目
使用go语言构建wasm的时候需要安装tinygo
macos
brew install tinygo
安装完成后,在当前项目的根目录执行:
tinygo build -o filter.wasm -target=wasi -wasm-abi=generic .
执行当前命令后会生成 filter.wasm
- 将做好的wasm上传到集群可以访问的文件服务器上面
$ kubectl get po -n demo
NAME READY STATUS RESTARTS AGE
details-v1-5588477696-2sw7b 2/2 Running 0 8d
productpage-v1-5bd6875444-j75dp 2/2 Running 0 8d
ratings-v1-c9d5c65fc-l65mq 2/2 Running 0 8d
reviews-v2-c789c7bdc-tsg7q 2/2 Running 0 8d
reviews-v3-78944b866f-96nbw 2/2 Running 0 8d
- 创建envoyfilter
kubectl apply -f-<<EOF
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: basic-auth
namespace: istio-system
spec:
configPatches:
- applyTo: HTTP_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: envoy.http_connection_manager
proxy:
proxyVersion: ^1\.9.*
patch:
operation: INSERT_BEFORE
value:
name: istio.auth
config_discovery:
config_source:
ads: {}
initial_fetch_timeout: 0s # wait indefinitely to prevent bad Wasm fetch
type_urls: [ "type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm"]
---
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: auth-config
namespace: istio-system
spec:
configPatches:
- applyTo: EXTENSION_CONFIG
match:
context: GATEWAY
patch:
operation: ADD
value:
name: istio.auth
typed_config:
'@type': type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
value:
config:
configuration:
'@type': type.googleapis.com/google.protobuf.StringValue
value: |
{
"basic_auth_rules": [
{
"prefix": "/productpage",
"request_methods":[ "GET", "POST" ],
"credentials":[ "ok:test", "YWRtaW4zOmFkbWluMw==" ]
}
]
}
vm_config:
vm_id: auth
code:
remote:
http_uri:
# wasm地址
uri: http://release.solarmesh.cn/wasm/auth.wasm
runtime: envoy.wasm.runtime.v8
EOF
- 向productpage服务上的 HTTP 端口 8080 发送一些流量:
~ curl -L -v http://${GATEWAY}:9080
在响应中,我们希望看到过滤器的标头添加到响应标头中:
* About to connect() to frontpage.backyards-demo port 8080 (#0)
* Trying 10.10.178.38...
* Adding handle: conn: 0x10eadbd8
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x10eadbd8) send_pipe: 1, recv_pipe: 0
* Connected to frontpage.backyards-demo (10.10.178.38) port 8080 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.30.0
> Host: frontpage.backyards-demo:8080
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: text/plain
< date: Thu, 16 Apr 2020 16:32:20 GMT
< content-length: 9
< x-envoy-upstream-service-time: 10
< hello: world
< resp-header-demo: added by our filter
< x-envoy-peer-metadata: CjYKDElOU1RBTkNFX0lQUxImGiQxMC4yMC4xLjU3LGZlODA6OmQwNDM6NDdmZjpmZWYwOmVkMjkK2QEKBkxBQkVMUxLOASrLAQoSCgNhcHASCxoJZnJvbnRwYWdlCiEKEXBvZC10ZW1wbGF0ZS1oYXNoEgwaCjU3OGM2NTU0ZDQKJAoZc2VjdXJpdHkuaXN0aW8uaW8vdGxzTW9k
ZRIHGgVpc3RpbwouCh9zZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1uYW1lEgsaCWZyb250cGFnZQorCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIEGgJ2MQoPCgd2ZXJzaW9uEgQaAnYxChoKB01FU0hfSUQSDxoNY2x1c3Rlci5sb2NhbAonCgROQU1FEh8aHWZyb250cGFnZS12MS01N
zhjNjU1NGQ0LWxidnFrCh0KCU5BTUVTUEFDRRIQGg5iYWNreWFyZHMtZGVtbwpXCgVPV05FUhJOGkxrdWJlcm5ldGVzOi8vYXBpcy9hcHBzL3YxL25hbWVzcGFjZXMvYmFja3lhcmRzLWRlbW8vZGVwbG95bWVudHMvZnJvbnRwYWdlLXYxCi8KEVBMQVRGT1JNX01FVEFEQVRBEhoqGAoWCgpjbHVzdGVyX2lkEg
gaBm1hc3RlcgocCg9TRVJWSUNFX0FDQ09VTlQSCRoHZGVmYXVsdAofCg1XT1JLTE9BRF9OQU1FEg4aDGZyb250cGFnZS12MQ==
< x-envoy-peer-metadata-id: sidecar~10.20.1.57~frontpage-v1-578c6554d4-lbvqk.backyards-demo~backyards-demo.svc.cluster.local
< x-by-metadata: CjYKDElOU1RBTkNFX0lQUxImGiQxMC4yMC4xLjU3LGZlODA6OmQwNDM6NDdmZjpmZWYwOmVkMjkK2QEKBkxBQkVMUxLOASrLAQoSCgNhcHASCxoJZnJvbnRwYWdlCiEKEXBvZC10ZW1wbGF0ZS1oYXNoEgwaCjU3OGM2NTU0ZDQKJAoZc2VjdXJpdHkuaXN0aW8uaW8vdGxzTW9kZRIHGgVp
c3RpbwouCh9zZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1uYW1lEgsaCWZyb250cGFnZQorCiNzZXJ2aWNlLmlzdGlvLmlvL2Nhbm9uaWNhbC1yZXZpc2lvbhIEGgJ2MQoPCgd2ZXJzaW9uEgQaAnYxChoKB01FU0hfSUQSDxoNY2x1c3Rlci5sb2NhbAonCgROQU1FEh8aHWZyb250cGFnZS12MS01NzhjNjU1N
GQ0LWxidnFrCh0KCU5BTUVTUEFDRRIQGg5iYWNreWFyZHMtZGVtbwpXCgVPV05FUhJOGkxrdWJlcm5ldGVzOi8vYXBpcy9hcHBzL3YxL25hbWVzcGFjZXMvYmFja3lhcmRzLWRlbW8vZGVwbG95bWVudHMvZnJvbnRwYWdlLXYxCi8KEVBMQVRGT1JNX01FVEFEQVRBEhoqGAoWCgpjbHVzdGVyX2lkEggaBm1hc3
RlcgocCg9TRVJWSUNFX0FDQ09VTlQSCRoHZGVmYXVsdAofCg1XT1JLTE9BRF9OQU1FEg4aDGZyb250cGFnZS12MQ==
* Server istio-envoy is not blacklisted
< server: istio-envoy
< x-envoy-decorator-operation: frontpage.backyards-demo.svc.cluster.local:8080/*
<
* Connection #0 to host frontpage.backyards-demo left intact
frontpage
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.