InfoQ|eBPF 在网易轻舟云原生的应用实践( 三 )



InfoQ|eBPF 在网易轻舟云原生的应用实践
本文插图

  • 监控每个进程中各状态的 TCP 链接数 。 在引入 eBPF 监控之前 , 我们曾通过 inet_diag 实现了该监控功能 , 但是每次读取都是整个系统的全量 , 对于动辄几十万上百万连接的线上节点 , 非常占用 CPU 资源 , 没办法做到在线的实时监控 。 引入 eBPF 后 , 我们以非常小的代价达到了相同的监控效果 , 实测 QPS 性能只有 3.7% 的下降 , 对 CPU 资源的占用可以忽略不计 。
  • 开发了 cpucycles/instructions、llcreferences/misses 等一系列针对硬件 PMU 的监控功能用来支持混合部署中的调度功能 。
更多的监控功能就不一一列举了 , 除了自研的一些监控 , 我们还将 BCC 工具集中一些功能引入了进来 , 目前主要用来支撑自动诊断、监控报警、性能调优等场景 。
eBPF 开发中遇到的问题:一直都在陈述 eBPF 的优点 , 但是在开发具体监控功能的过程中 , 依然存在诸多限制 , 包括内核实现方面的限制也有 eBPF 自身的一些限制 , 需要开发者充分的考虑 , 例如在多核平台上如何保证对 eBPF MAP 中数据修改操作的原子性、如何将监控数据与产生数据的进程关联起来等等 。
有些问题我们可以解决 , 但是也有些问题我们目前也没找到好的解决方法 , 例如将监控数据与产生数据的进程关联起来这个问题 , 这是一个非常常见的问题 , 通常由内核的实现逻辑引入 , 该问题我们在监控 TCP 连接状态变化的场景中(连接建立过程不在进程上下文) , 通过记录 socket 创建以及 socket 继承等操作得到了解决 , 但是在 Block IO 相关的监控场景中就没那么好解决了 , 我们依然在这方面不断探索 。
3.2 网络性能优化 【InfoQ|eBPF 在网易轻舟云原生的应用实践】在网络性能优化方面 , 网易轻舟也基于 ebpf 的 sockmap 和 sk redirect 功能研发了自己的 sockops 组件 , 主要用于加速 istio 架构中 sidecar 代理和本地进程之间的通信 。
InfoQ|eBPF 在网易轻舟云原生的应用实践
本文插图
Sockops 技术原理说明:Sockmap 是 eBPF 提供的一个特殊的 eBPF MAP 类型 , 主要用于 socket redirection , 在 socket redirection 中 , socket 被添加到 sockmap 中并由 key(主要是四元组)引用 , 然后该 socket 在调用 bpf_sockmap_redirect时进行重定向 。
sockops 的技术原理如下图所示 , 对于本地通信可以绕过 TCP/IP 协议栈将报文直接发给对端 socket , 以此来提高性能 。 Sockops 组件技术原理如下图所示:
InfoQ|eBPF 在网易轻舟云原生的应用实践
本文插图
Sockops 数据面对轻舟服务网格场景的适配:如果一个报文的 key(主要是四元组)在 sockmap 中被命中 , 那么该报文将绕过 TCP/IP 协议栈 , 而被直接发送给接收端的 socket , 接收端的 socket 对应的就是下图中 sockmap 的 value 所存储的 skops 结构 。
InfoQ|eBPF 在网易轻舟云原生的应用实践
本文插图
首先我们监听 TCP 链接状态的变化 , 在连接建立时 , 填充 sockmap 。 然后我们再通过 eBPF 的 sk_msg 功能 hook TCP 的发包流程(sendmsg/sendfile 等) , 并在 hook 函数中调用 bpf_sockmap_redirect对 socket 进行重定向 。
不过在 istio 环境中 , 该情况会变得稍微复杂一些 , 因为 istio 通过 iptables redirect 将 pod 访问 svc 的报文重定向到 envoy , 加之 sockmap 的捕捉是在 iptable 规则之前 , 所以 sockmap 捕捉到的反向连接跟正向连接的源、目的地址不是一一对应的 , 找不到正向连接信息 。 我们的解决方案是新增一个 eBPF MAP , 并在正向连接建立时 , 以源地址为 key , 目的地址作为 value 存储起来 , 反向连接建立时根据反向链接的目的地址可以直接找到正向连接的完整信息 。 用一张图可以比较清晰的看懂这个过程:


推荐阅读