本文分享自华为云社区《Kmesh v0.1.0 版本发布!打造极致性能的流量治理体验》,作者:云容器大未来。
Kmesh是业内首个内核级云原生流量治理引擎,通过基础软件创新帮助用户构筑云原生场景下高性能的通信基础设施。Kmesh第一个版本v0.1.0 [1]现已正式发布,用户可以在服务网格环境中使用yaml一键部署,无缝对接Istiod,通过流量治理下沉OS,实现相比 Istio Sidecar 方案转发时延降低50%+,为应用提供极致的转发性能体验。
Kmesh 介绍
Kmesh 基于 eBPF + 可编程内核技术,将流量治理下沉 OS,数据路径上无需经过代理层,实现了一个内核级 sidecarless 网格数据面。
Kmesh 关键能力:
- 高性能:内核中原生支持 L4~L7 流量治理功能,治理过程无需经过实体代理组件,网格内服务通信路径从代理架构下的三跳变为一跳,大幅提升网格数据面的转发性能;
- 低开销:Pod 中无需部署 Sidecar 程序,大幅降低网格基础设施的资源开销;
- 安全隔离:基于 eBPF 的运行时安全,并支持 cgroup 级治理隔离;
- 平滑兼容:支持与 Istiod 等支持 XDS 协议的服务网格管控面对接,同时可以与现有 Sidecar 网格协同工作;
Kmesh 的主要部件包括:
- kmesh-controller:负责生命周期管理、XDS 协议对接、观测运维等功能;
- kmesh-api:接口层,主要包括XDS 转换后的编排 API、观测运维通道等;
- kmesh-runtime:kernel 中实现的支持 L4~L7 流量编排的运行时;其中7层编排运行时能力依赖对内核的增强;
- kmesh-orchestration:基于 eBPF 实现 L4~L7 流量编排,如路由、灰度、负载均衡等;
- kmesh-probe:观测运维探针,提供端到端观测能力;
Kmesh v0.1.0关键特性
- 一键部署Kmesh
社区发布了 Kmesh 的部署镜像[2],并支持通过 yaml 一键部署 Kmesh[3];
- 基于namespace使能Kmesh
类似Istio,Kmesh支持按namespace使能流量接管范围,如:kubectl label namespace default label istio.io/dataplane-mode=Kmesh
- 无缝连通Istio Sidecar
支持在已有sidecar形态的网格环境启用Kmesh,启用后namespace 下新创建的 Pod 流量会自动被 Kmesh 接管,而不再经过 sidecar 代理;
- 自动对接服务网格控制面
Kmesh支持与Istiod自动对接,且理论上遵循XDS协议的网格控制面都可以与Kmesh对接,可通过修改yaml中的 MESH_CONTROLLER 环境量指定;
- TCP/HTTP1.1基础流量治理
支持TCP流量转发,支持HTTP1.1头域匹配、路由、灰度等,支持随机、轮询负载均衡算法;
- 兼容运行模式
支持根据运行环境的OS内核能力,自适应使能Kmesh特性,在无增强补丁的内核版本上,也能够以兼容模式运行Kmesh;详情参考Release Notes[1]。
性能测试
我们使用 fortio 测试了 Istio(Envoy)、Kmesh 在同等流量治理场景下的表现,同时测试了 K8s 下基于 kubeProxy 的服务通信时延作为基线参考;
不同链接数下的时延对比:
相同QPS下的CPU开销对比:
从测试结果可以看到:
- Kmesh 的转发时延基本接近K8s原生转发时延,相比 Istio sidecar 模式的转发时延有明显降低;
- 相同 qps 下,Kmesh 的 CPU 开销基本与 k8s 原生 CPU 开销一致,相比 Istio sidecar 模式有明显降低;
想要了解详细的 demo 测试细节,可以观看我们的演示视频:
Kmesh关键技术剖析
内核级流量编排运行时
微服务通信一般先建立链接,再发送业务报文,如果想要无感的对业务报文做编排处理,通常需要对流量进行劫持,编排完成后再基于调整后的报文继续转发,这也是现在 Proxy 代理的实现;Kmesh 考虑随流完成治理工作,将链路建立时机推迟到业务报文发送阶段,以实现更高的编排处理性能。
- 伪建链
pre_connect 流程挂载 bpf prog,若当前访问的目标地址在 xds 的 listener 范围,则调用 bpf_setsockopt 通过 TCP_ULP 将当前 socket 的 tcp proto hook重载到 kmesh_defer 的内核模块实现;
- 延迟建链
kmesh_defer 内核模块重写了 connect/send hook(在原生 hook 上做了增强):
- 服务第一次走到 connect hook 时,会设置 bpf_defer_connect 标记,并不真正触发握手流程;
- send hook 中,若 sock 上设置了 bpf_defer_connect 标记,则触发connect,此时,会基于扩展的BPF_SOCK_OPS_TCP_DEFER_CONNECT_CB 调用 bpf prog,并在 bpf prog 中完成流量治理,然后基于调整后的通信五元组、报文进行建链和发送;
整个治理过程大致如下图所示:
XDS规则管理
xds 模型是一颗层次化的树型规则表达,且不同版本模型定义可能会有调整,Kmesh 需要将模型信息转换成 eBPF map 存储,同时保持模型规则之间的层次关系;
- 将 xds 模型转换成 eBPF map 数据
具体过程:
- Kmesh 订阅 Istiod 的 xds 模型,并基于 protobuf-c 将 pb 模型转换成 c 数据结构风格;
- 对于顶层模型( listener 等),Kmesh 定义了知名 map 表与之对应,且value 的数据结构复用 protobuf-c 导出的 c struct;
- map 更新从顶层的知名 map 表开始,对于记录中的指针成员,xds-adapter 中会创建 inner-map 表来存储指针指向的真实数据区域,并将 inner-map的map fd添加进 map-in-map表中,最后将其在map-in-map表的key(index)作为该指针成员的 value;
- map-in-map 解决 xds 模型层次化
对于 map 记录的 value 成员,如果是指针变量(涉及引用其他数据结构),通过 inner-map 存储指向的数据区域:
- 如果 vaule 成员是基础数据类型(int 等),则直接访问;
- 如果 value 成员是指针类型,则指针存储的 value 是存放真实数据的 inner-map 在 map-in-map 表中的 index(注意:index 是在 kmesh-daemon 的xds-adapter 模块中更新 bpf map 时配合写入);访问时,先基于 index 找到 inner-map的map fd,再去 inner-map 表中查找真正数据,对于多级指针成员,则重复该过程,直到指针信息全部被剥离。
流量治理编排实现
xds 的治理规则复杂,层层匹配,超过了单个 eBPF 程序的复杂度限制;Kmesh 基于 eBPF Tail Calls 特性,将治理过程拆分成多个独立的 eBPF progs,具备较好的扩展性;
展望
Kmesh 是一种基于eBPF+可编程内核实现的高性能流量治理引擎,与业界方案相比,具有更高的转发性能和更低的资源开销;在无增强补丁的内核版本上,可以以兼容模式运行Kmesh,如果想要使用Kmesh完整的治理能力,当前 openEuler 23.03[4]版本已经原生支持,除此之外的其他操作系统需要基于增强的 patch 构建[5]。
Kmesh 正在逐步完善,成为一个更受欢迎的流量治理引擎还有很多工作要做,欢迎大家试用 Kmesh v0.1.0 版本,并持续关注 Kmesh 社区,也期待您的共同参与。
参考链接
[1] Kmesh v0.1.0:github.com/kmesh-net/k...
[2] Kmesh的部署镜像:github.com/orgs/kmesh-...
[3] 一键部署Kmesh:github.com/kmesh-net/k...
[4] openEuler 23.03版本:repo.openeuler.org/openEuler-2...
[5] 基于增强的patch构建:github.com/kmesh-net/k...
[6] Kmesh社区地址:github.com/kmesh-net/k...