Envoy Filter 介绍
Listener Filter:用于操作处理 L4 连接中的元数据。 Network Filter:用于操作处理 L4 连接中的原始数据。 HTTP Filter:用于操作处理 L7 连接中的 HTTP 请求与响应。
此外,Envoy 提供了一组 API,也就是我们常说的 xDS API。通过这些 API,控制平面可以动态地配置 Envoy 代理。
第一个 filter 是 envoy.filters.network.metadata_exchange,它的主要作用顾名思义,用来在 filter 之间交换元数据。
第二个 filter: envoy.http_connection_manager,它下面通常会有以下几个跟 http 特定的 filter,包括:
envoy.filters.http.wasm/envoy.wasm.metadata_exchange(用于元数据交互)
Istio_authn filter(用于授权认证)
envoy.filters.http.cors(处理跨域资源共享的 filter)
envoy.filters.http.fault(故障注入过滤器,可以用来测试微服务架构中容错能力,用户可以自定义错误代码来实现延时注入或者终止请求,在不同的失败场景下提供错误处理的能力,例如服务失败、服务过载、服务高延时等情况,这个也是较为常用的 filter)
envoy.filters.http.wasm/envoy.wasm.stats、envoy.filters.http.wasm/xxx-wasmfilter(用户自定义的 wasm 实现的filter)
envoy.filters.http.router(实现 HTTP 转发,几乎所有 HTTP 场景下都会使用到这一过滤器)
备注:可以通过请求这个 URL 地址获取配置信息:kubectl exec -it [productpage-xxx] -c istio-proxy curl localhost:15000/config_dump
添加新的 Filter
Envoy 社区已经提供了若干个 Built-in Filters,具体参见:https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/http_filters。
在服务网格中,可以通过 API 启用这些 Built-in Filter 能力。
静态预编译: 将其他过滤器集成到 Envoy 的源代码中,并编译新的 Envoy 版本。 这种方法的缺点是您需要维护 Envoy 版本,并不断使其与官方发行版保持同步。 由于 Envoy 是用 C++ 实现的,因此新开发的过滤器也必须用 C++ 实现。 动态运行时加载: 在运行时将新的过滤器动态加载到 Envoy 代理中。 为了简化扩展 Envoy 的过程, 通过引入 WebAssembly 技术 - 它是一种有效的可移植二进制指令格式,提供了可嵌入和隔离的执行环境。
使用 Wasm 扩展 Envoy Proxy 的优缺点
在实际应用中,会根据以下优缺点来决定是否使用 Wasm 这种方式扩展 Envoy Filter。
Pros
敏捷性:过滤器可以动态加载到正在运行的 Envoy 进程中,而无需停止或重新编译。 可维护性:不必更改 Envoy 自身基础代码库即可扩展其功能。 多样性:可以将流行的编程语言(例如 C/C++ 和 Rust)编译为 WASM,因此开发人员可以选择实现过滤器的编程语言。 可靠性和隔离性:过滤器会被部署到 VM 沙箱中,因此与 Envoy 进程本身是隔离的;即使当 WASM Filter 出现问题导致崩溃时,它也不会影响 Envoy 进程。 安全性:过滤器通过预定义 API 与 Envoy 代理进行通信,因此它们可以访问并只能修改有限数量的连接或请求属性。
Cons
性能约为 C++ 编写的原生静态编译的 Filter 的 70%。 由于需要启动一个或多个 WASM 虚拟机,因此会消耗一定的内存使用量。 The WebAssembly ecosystem is still young。
envoy-wasm 运行机制
如下图所示,envoy-wasm 运行机制包括以下几个步骤:
Wasm 二进制代码需要能够被动态加载进来,无论是通过 local file 方式还是 xds 远程获取方式。 一个 Wasm filter 是否被允许加载,需要一致性校验:https://github.com/proxy-wasm/spec。 一旦被加载之后,Wasm filter 就成为 filter chain 的一部分,当新的请求进来之后,还是先进入到原生的 filter,之后进入到 Proxy-Wasm 扩展控制器。 Proxy-Wasm 扩展控制器会根据在 filter chain 中定义的 configuration 信息,调用并执行注册的校验过的这些 Wasm filter。 内置的 Wasm runtime 支持:LLVM-based WAVM ~20MB, and V8 ~10MB。 事件驱动模型。 兼容 native filter 调用方式。
OPAS 及 Wasm filter 注册库
将 WebAssembly 模块推入到 OCI 注册库中。 从 OCI 注册库中拉取 WebAssembly 模块。
阿里云服务网格 ASM 架构
从向下与基础设施融合的角度 服务网格自身的能力建设的角度 向上支持应用层以及被集成能力的角度
在托管侧,将控制面核心组件进行改造托管,并负责整个控制面和数据面组件的生命周期管理。在产品能力方面,ASM 在 Mesh CA、安全审计方面做了增强提升网格实例的安全度;把客户场景的常见问题形成了诊断规则,用户可以自行运行诊断分析。
在做核心托管侧的建设之外,ASM 优化整合了阿里云的多个产品服务,如:在可观测性方面,整合了 xtrace、arms、日志服务等;在跨 vpc 网络打通方面整合了 cen,实现多集群的互联互通;在限流方面集成了 AHAS 的限流服务。
ASM 还集成扩展了社区开源的组件能力,包括在安全方面的 OPA 安全引擎的支持、spiffe/spire 的支持、envoyfilter 的扩展支持等。所以这一部分需要提供一种简单有效的方式帮助用户轻松扩展这些能力。
在阿里云 ASM 中使用 Wasm
aliyun servicemesh UpdateMeshFeature --ServiceMeshId=xxxxxx --WebAssemblyFilterEnabled=true
部署一个 DaemonSet(asmwasm-controller) 到 K8s 集群中。 asmwasm-controller 监听一个 configmap,该 configmap 存放要拉取的 wasm filter 的地址,例如:acree-1-registry.cn-hangzhou.cr.aliyuncs.com/*******/sample:v0.1。 如果需要授权认证,该 asmwasm-controller 会根据定义的 pullSecret 值获得相应的 secret 值。 然后,调用 oras API 从注册库中动态拉取 Wasm filter。 该 asmwasm-controller 使用 HostPath 方式挂载 volume,所以拉取的 Wasm filter 会落盘到对应的节点上。
启用了该功能之后,如何开始部署一个 Wasm filter 并挂载到对应 workload 的 Envoy Proxy 中呢?
创建出用于控制面的 Istio EnvoyFilter Custom Resource,并推送到对应的 asm 控制面 istiod 中。 从 OCI 注册库中拉取对应的 wasm filter 镜像,并挂载到对应的 workload pod 中。
apiVersion: istio.alibabacloud.com/v1beta1
kind: ASMFilterDeployment
metadata:
name: details-v1-wasmfiltersample
spec:
workload:
kind: Deployment
labels:
app: details
version: v1
filter:
parameters: '{"name":"hello","value":"hello details"}'
image: 'acree-1-registry.cn-hangzhou.cr.aliyuncs.com/asm/asm-test:v0.1'
imagePullOptions:
pullSecret: 'asmwasm-cache'
rootID: 'my_root_id'
id: 'details-v1-wasmfiltersample.default'
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"}]'
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
总结
可以登录到 proxy container 进行查看 Wasm filter 是否挂载成功。 通过调整 wasm log level 来打印相关信息。
作者简介
王夕宁 阿里云高级技术专家,阿里云服务网格 ASM 技术负责人,专注于 Kubernetes、服务网格以及其他云原生领域。之前曾在 IBM 中国开发中心工作,曾担任专利技术评审委员会主席,作为架构师和主要开发人员负责或参与了一系列在 SOA 中间件、云计算等领域的工作,拥有 50 多项相关领域的国际技术专利。曾在多个技术大会如 Kubecon、ArchSummit、云栖大会等参与技术分享。编写《服务网格技术解析与实践》并在多个技术社区发布文章若干。