为Envoy编写WASM Filter并部署到服务网格ASM中使用

简介: ## 简介 Envoy是一个高性能、可编程的L3 / L4和L7代理,被服务网格ASM作为数据面的代理使用。Envoy的连接和流量处理的核心是网络过滤器(Network Filter),该过滤器一旦融合进滤器链(Filter Chain),就可以实现用于访问控制、数据或协议转换、数据增强、审计等高级功能。通过添加新的过滤器Filter,可以用来扩展Envoy的已有功能集。当前有两种方法可以添加新

简介

Envoy是一个高性能、可编程的L3 / L4和L7代理,被服务网格ASM作为数据面的代理使用。Envoy的连接和流量处理的核心是网络过滤器(Network Filter),该过滤器一旦融合进滤器链(Filter Chain),就可以实现用于访问控制、数据或协议转换、数据增强、审计等高级功能。通过添加新的过滤器Filter,可以用来扩展Envoy的已有功能集。当前有两种方法可以添加新的过滤器:

  • 静态预编译:将其他过滤器Filter集成到Envoy的源代码中,并编译新的Envoy版本。这种方法的缺点是您需要维护自己的Envoy版本,并不断使其与官方发行版保持同步。此外,由于Envoy是用C++实现的,因此新开发的过滤器Filter也必须用C++实现。
  • 动态运行时加载:在运行时将新的过滤器动态加载到Envoy代理中。

显而易见,从使用难易角度来看,第二种方式极大地简化了扩展Envoy的过程。这种解决方案依赖于一种称之为WebAssembly(WASM)的新技术,它是一种有效的可移植二进制指令格式,提供了可嵌入和隔离的执行环境。

ASM与WASM

阿里云服务网格ASM产品中提供了对WebAssembly(WASM)技术的支持,如下图所示,服务网格使用人员可以把扩展的WASM Filter通过ASM部署到数据面集群中相应的Envoy代理中。通过这种过滤器扩展机制,可以轻松扩展Envoy的功能并将其在服务网格中的应用推向了新的高度。

image.png

为什么要使用WASM Filter

使用WebAssembly(WASM)实现过滤器Filter的扩展,可以得到如下优势:

  • 敏捷性:过滤器Filter可以动态加载到正在运行的Envoy进程中,而无需停止或重新编译。
  • 可维护性:不必更改Envoy自身基础代码库即可扩展其功能。
  • 多样性:可以将流行的编程语言(例如C / C ++和Rust)编译为WASM,因此开发人员可以使用他们选择的编程语言来实现过滤器Filter。
  • 可靠性和隔离性:过滤器Filter会被部署到VM沙箱中,因此与Envoy进程本身是隔离的;即使当WASM Filter出现问题导致崩溃时,它也不会影响Envoy进程。
  • 安全性:过滤器Filter通过预定义API与Envoy代理进行通信,因此它们可以访问并只能修改有限数量的连接或请求属性。

当前WebAssembly(WASM)实现过滤器Filter的扩展,也需要考虑以下缺点是否可以容忍:

  • 性能约为C++编写的原生静态编译的Filter的70%。
  • 由于需要启动一个或多个WASM虚拟机,因此会消耗一定的内存使用量。

使用Proxy-WASM SDK构建过滤器

Envoy Proxy在基于堆栈的虚拟机中运行WASM过滤器,因此过滤器的内存与主机环境是隔离的。Envoy代理与WASM过滤器之间的所有交互都是通过Envoy Proxy-WASM SDK提供的功能实现的。Envoy Proxy-WASM SDK提供了多种编程语言的实现,包括C++、Rust、AssemblyScript以及处于实验中的golang等。此外,社区也在推动相应的WebAssembly (Wasm) for Proxies (Proxy-Wasm)应用二进制接口ABI规范,具体可以参考:https://github.com/proxy-wasm/spec

  1. 构建WASM Filter的最简单方法是使用Docker,参考https://github.com/proxy-wasm/proxy-wasm-cpp-sdk#docker所述,使用C++ Envoy Proxy-WASM SDK创建一个Docker镜像。

或者直接使用已构建好的镜像:registry.cn-hangzhou.aliyuncs.com/acs/wasmsdk:v0.1

  1. 参照https://github.com/proxy-wasm/proxy-wasm-cpp-sdk#creating-a-project-for-use-with-the-docker-build-image 所述,创建一个项目并使用上述Docker镜像进行构建。
  1. 具体开发过程在此不再赘述,具体可参见:https://github.com/proxy-wasm/proxy-wasm-cpp-sdk#webassembly-for-proxies-c-sdk
  1. 切换到项目根目录,执行如下命令构建WASM:
docker run -v $PWD:/work -w /work  registry.cn-hangzhou.aliyuncs.com/acs/wasmsdk:v0.1 /build_wasm.sh

在ASM中部署启用WASM Filter

  1. 创建一个configmap,用于保存WASM过滤器的二进制文件内容。例如,在命名空间default下,创建一个名称为wasm-example-filter的configmap,并将WASM过滤器的二进制文件example-filter.wasm保存到该configmap中。
kubectl create configmap -n default wasm-example-filter --from-file=example-filter.wasm
  1. 使用以下两个annotation将WASM过滤器的二进制文件注入到应用程序对应的Kubernetes服务中:
sidecar.istio.io/userVolume: '[{"name":"wasmfilters-dir","configMap": {"name": "wasm-example-filter"}}]'
sidecar.istio.io/userVolumeMount: '[{"mountPath":"/var/local/lib/wasm-filters","name":"wasmfilters-dir"}]'
  1. 执行以下命令更新productpage-v1:
kubectl patch deployment productpage-v1 -p '{"spec":{"template":{"metadata":{"annotations":{"sidecar.istio.io/userVolume":"[{\"name\":\"wasmfilters-dir\",\"configMap\": {\"name\": \"wasm-example-filter\"}}]","sidecar.istio.io/userVolumeMount":"[{\"mountPath\":\"/var/local/lib/wasm-filters\",\"name\":\"wasmfilters-dir\"}]"}}}}}'

执行以下命令更新details-v1:

kubectl patch deployment details-v1 -p '{"spec":{"template":{"metadata":{"annotations":{"sidecar.istio.io/userVolume":"[{\"name\":\"wasmfilters-dir\",\"configMap\": {\"name\": \"wasm-example-filter\"}}]","sidecar.istio.io/userVolumeMount":"[{\"mountPath\":\"/var/local/lib/wasm-filters\",\"name\":\"wasmfilters-dir\"}]"}}}}}'
  1. 现在,您可以在istio-proxy容器中的路径/var/local/lib/wasm-filters下,找到WASM过滤器的二进制文件:
kubectl exec -it deployment/productpage-v1 -c istio-proxy -- ls /var/local/lib/wasm-filters/
kubectl exec -it deployment/details-v1 -c istio-proxy -- ls /var/local/lib/wasm-filters/
  1. 要使WASM过滤器在处理针对应用服务productpage的流量时,能够以DEBUG日志级别记录,执行如下命令:
kubectl port-forward deployment/productpage-v1 15000
curl -XPOST "localhost:15000/logging?wasm=debug"

同样地, 要使WASM过滤器在处理针对应用服务productpage的流量时,能够以DEBUG日志级别记录,执行如下命令:

kubectl port-forward deployment/details-v1 15000
curl -XPOST "localhost:15000/logging?wasm=debug"


  1. 将WASM过滤器插入到应用服务productpage的HTTP级别过滤器链中,执行如下命令:
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: productpage-v1-examplefilter
spec:
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_INBOUND
      listener:
        filterChain:
          filter:
            name: envoy.http_connection_manager
            subFilter:
              name: envoy.router
    patch:
      operation: INSERT_BEFORE
      value:
        config:
          config:
            name: example-filter
            rootId: my_root_id
            vmConfig:
              code:
                local:
                  filename: /var/local/lib/wasm-filters/example-filter.wasm
              runtime: envoy.wasm.runtime.v8
              vmId: example-filter
              allow_precompiled: true
        name: envoy.filters.http.wasm
  workloadSelector:
    labels:
      app: productpage
      version: v1
  1. 通过在浏览器中访问入口网关的地址, 将一些流量发送到productpage服务上, 在页面响应中,可以看到过滤器的头添加到响应头中,如下图所示。
    image.png
  1. 将WASM过滤器插入到应用服务details的HTTP级别过滤器链中,执行如下命令:
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: details-v1-examplefilter
spec:
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_INBOUND
      listener:
        filterChain:
          filter:
            name: envoy.http_connection_manager
            subFilter:
              name: envoy.router
    patch:
      operation: INSERT_BEFORE
      value:
        config:
          config:
            name: example-filter
            rootId: my_root_id
            vmConfig:
              code:
                local:
                  filename: /var/local/lib/wasm-filters/example-filter.wasm
              runtime: envoy.wasm.runtime.v8
              vmId: example-filter
              allow_precompiled: true
        name: envoy.filters.http.wasm
  workloadSelector:
    labels:
      app: details
      version: v1
  1. 将一些流量发送到details服务上 :
kubectl exec -ti  deploy/productpage-v1 -c istio-proxy -- curl -v http://details:9080/details/123

在响应中,可以看到过滤器的头添加到响应头中:

kubectl exec -ti  deploy/productpage-v1 -c istio-proxy -- curl -v http://details:9080/details/123
*   Trying 172.31.13.58...
* TCP_NODELAY set
* Connected to details (172.31.13.58) 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
相关文章
|
4月前
|
Cloud Native 测试技术 开发者
阿里云服务网格ASM多集群实践(二):高效按需的应用多环境部署与全链路灰度发布
介绍服务网格ASM提出的一种多集群部署下的多环境部署与全链路灰度发布解决方案。
|
负载均衡 前端开发 网络协议
【服务网格架构】Envoy 部署类型
【服务网格架构】Envoy 部署类型
|
存储 Serverless 异构计算
使用ASM管理Knative服务(2):使用Knative on ASM部署Serverless应用
如何在阿里云服务网格ASM中开启Knative on ASM功能, 并结合ACK或者ASK部署管理Serverless应用服务。
639 0
使用ASM管理Knative服务(2):使用Knative on ASM部署Serverless应用
|
调度 UED Perl
部署ASM网关Pod到指定的节点上
配置高性能和高可用的ASM网关,可确保业务连续性并提升用户体验。本文介绍如何配置ASM网关,将网关Pod部署到指定节点上,从而提高ASM网关的高可用性并增强与业务Pod的隔离性。
197 0
|
弹性计算 运维 Kubernetes
ASM助力95后恋爱社交产品,加速应用网格化部署
借助阿里云服务网格ASM提供的相关能力,晓宇科技在短时间内完成了链路追踪、网关日志可视化,并且在虚拟机到K8s集群的应用改造中,实现了不停机迁移,节约了大量时间和人力成本并带来了显著的业务价值。
494 7
ASM助力95后恋爱社交产品,加速应用网格化部署
|
运维 Kubernetes 数据可视化
ASM助力95后恋爱社交产品,加速完成应用网格化部署
在公司业务规模不断发展的过程中,为了提升资源利用率,弹性扩容能力以及流量治理能力,技术团队选择使用k8s + istio的方案来达到上述目标。但由于服务网格技术复杂且尚属高速发展中的新技术,对服务网格组件本身的运维和使用都对技术团队提出了挑战。
521 0
|
运维 Kubernetes 网络协议
基于ASM的GRPC服务部署实践
继MicroServices之后,ServiceMesh是又一个推动软件工业的革命性技术。其服务治理的方法论,不仅改变了技术实现的方式和社会分工。 运行于数据平面的用户服务与治理服务的各种规则彻底解耦。运行于控制平面的规则定义组件,将流量控制的具体规则推送给运行于数据平面的proxy,proxy通过对用户服务的ingress和egress的实际控制,最终实现服务治理。 原本需要服务开发
418 0
基于ASM的GRPC服务部署实践
|
Kubernetes 微服务 容器
阿里云服务网格ASM公测来袭系列之五:部署应用到ASM的数据面集群中
本文介绍如何将一个应用示例部署到服务网格ASM 实例中的数据面集群中。
742 0
阿里云服务网格ASM公测来袭系列之五:部署应用到ASM的数据面集群中
|
文字识别 前端开发 关系型数据库
虚拟机模拟部署Extended Clusters(二)asm配置注意事项
/dev/oracleasm/disks/DISK03 仲裁磁盘(QUORUM disk) prod01磁盘(/dev/oracleasm/disks/VOTEDB01,/dev/oracleasm/disks/NODE01DATA01) prod02磁盘(/dev/oracleasm/disk...
4577 0