Merge pull request ‘决赛材料’ (#4) from final into main
ebpf 是一种新兴的内核技术,使开发者能够在内核级别收集和分析系统性能数据。通过 eBPF,可以监控各种内核事件,例如系统调用、上下文切换、进程调度、文件系统操作等,而无需修改应用程序代码或重启系统。eBPF 程序可以附加到特定的内核探针(如 kprobe 和 tracepoint),实时收集详细的运行时信息,将其传输到用户空间,并生成更高层次的性能分析和可视化数据。这种实时、低开销的可观测性使得 eBPF 成为监控和调试 Linux 系统的关键技术,广泛应用于性能调优和故障排查等场景。
目前,ebpf 社区主流的开发工具有 BCC、libbpf,主流的诊断工具有 BCC examples、bpftraces 等。基于 BCC 开发框架在部署上比较方便,但运行环境需要安装完整工具链,并且在部署时需要现场编译,性能开销过高;基于libbpf的原生开发方案ebpf程序运行性能开销低,但 C/C++ 开发难度较大,对开发人员不友好。ebpf 社区开发了基于 Go 语言与 Rust 语言的原生开发框架,但也只针对特定语言。
在容器异常检测上,我们主要针对混部场景的容器资源竞争进行检测。基于监督学习的方法需要大量标注好的训练数据,覆盖工作负载有限,较难落地;无监督学习方法根据历史数据模式识别异常,正确率有限。结合 ebpf 的可观测性功能,以及对性能异常数据检测工具的调研,我们提出以下 3 个观点:
题目初始的目标有 4 项,Zoltraak 全部完成:
对于目标 1, Zoltraak 使用基于 libbpf 的原生框架开发,在 JIT 预热之后 CPU 开销 < 1%;
对于目标 2,Zoltraak 设计了丰富的性能指标,可供可观测数据平台分析使用。同时开发了精准的异常检测算法。详见 2.1 与 2.2。
对于目标 3,Zoltraak 自研了基于 Echarts 的可视化界面,方便查看性能数据与异常检测结果。
对于目标 4,Zoltraak 设计了基于动态库的 ebpf 程序部署方式,可以给多种编程提供服务,将 ebpf 程序开发与指标数据存储处理开发工作解耦。并且,Zoltraak 框架保留了原生libbpf的性能优势,在添加 ebpf 功能时,ebpf 开发人员暴露相关接口,由上层开发人员调用接口启动并对ebpf数据进行读取。另外,Zoltraak 也能基于 Json 配置文件配置已开发的功能。
Zoltraak 的指标设计有几点原则:
基于以上原则,Zoltraak 实现了如下指标的采集:
Zoltraak 做到容器每个 CPU 核心利用率指标的采集。多数可观测性框架没有实现这一特性,使用聚合后的 CPU 利用率,但聚合后的数据不足以支撑性能分析与异常检测。
Zoltraak 所有指标按照容器为单位进行划分。
ebpf 在容器内存性能监测上能力较弱,建议使用 Linux 5.15 引入的 DAMON 特性,而不是使用 ebpf。
Zoltraak 实现了基于无监督离线学习的脚本进行异常监测,并在实验数据上验证的了算法正确性。但如同 1.1 中所述,我们不推荐使用机器学习方法,故仅提供脚本代码作为参考。
BCC examples 提供的 CPU 资源竞争检测是通过 runqueue length 这一指标进行评估;Netfix 则使用 runqueue latency 与 context switch out 2 个指标对容器间的 CPU 资源竞争进行评估。Zoltraak 采集 context switch out,并基于该数据建立有向图,使用 Tarjan 算法获取有向图的强连通分量。当强连通分量内点的个数 > 1 时,可以认为发生了 CPU 资源竞争。节点中的边权信息是 context switch out 次数,其代表 CPU 资源竞争的激烈程度。根据节点出入度与应用类别(延迟敏感/批处理),上层调度器可以实现简单的调度算法处理该异常。
相较于 BCC examples 的方案,Zoltraak 方案的优势是:
相较于 Netfix 容器干扰邻居检测,Zoltraak 的优势是:
Netfix 与 Zoltraak 都采集了 context switch out 这一指标,但是,Zoltraak 与 Netfix 都是独立提出这一指标的。Zoltraak 不是基于 Netfix 方案进行改良,而是在初赛时就完成了该方案的主体设计。Netfix 容器干扰邻居检测方法的博文是 2024.9.11 提出,比 Zoltraak 初赛提交晚 1 个月。
Zoltraak 框架可以采集陷入 Syscall Futex 与 Semop 的时间,该时间与墙上时间的比值,可以一定程度上反映对锁的利用程度。当高于某个阈值时,可以认为锁使用上发生了异常。
Zoltraak 也能捕获 OOM 事件,该事件是异常事件,ebpf 可以采集 OOM 发生时的函数栈,内存页数量与触发 OOM 的原因。上层调度器可有根据原因与内存页数量判断该程序是存在内存泄漏 BUG 或者是由于容器配置异常所致。
ebpf 程序与可观测数据平台代码之间的融合是一个棘手的问题,有几种方案:
针对以上框架和问题,我们有以下思考:
Zoltraak 的解决方案,是 ebpf 开发人员开发 ebpf 程序,并暴露出 API 供其他程序调用。这样部署时只需要在目标机器上添加一份动态链接库文件即可。上层监控平台人员通过接口启动 ebpf 程序并采集性能数据。具体到 Zoltraak 实现上,ebpf 程序仅需要暴露 start,read,clean_up 完成对上层框架的对接。上层程序仅需要实现 Manager 的子类,调用对应接口完成启动到采集数据,存储到数据库整个过程。Zoltraak 框架设计完成了 ebpf 开发与上层监控平台开发的解耦。
Zoltraak ebpf 侧使用 libbpf 原生开发,上层数据采集与处理使用 dotnet8,时序数据库使用 Influxdb2.7。得益于 C ABI 的稳定性,Zoltraak 提出的 ebpf 程序开发与部署方案适用于绝大多数语言,可以迁移到其他平台上。
在 oos_ebpf 目录下,输入如下指令
bash go.sh
influxdb 的配置信息在 config/influx.json 中编辑,需要有 metrics 与 abnormal 2 个 bucket。
启动 Zoltraak 采集器指令如下所示:
# 这是 DEBUG 模式运行,会打印采集到的数据与一些额外信息 sudo LD_PRELOAD=lib/libbpf.so dotnet run config/test.json config/influx.json # 这是 Release 模式运行,不会打印额外信息 sudo LD_PRELOAD=lib/libbpf.so dotnet run config/test.json config/influx.json -c Release
启动可视化 Web 程序命令如下所示:
python src/Web/main.py
我们通过 iperf3 与 SPECCPU 2017 602.gcc 工作负载评价。分别运行在 Zoltraak 未启动与 Zoltraak 启动时运行负载,对比运行时间与输出的性能指标。
# iperf3 启动命令 (运行 Zoltraak 的机器) iperf3 -s # iperf3 # SPECCPU2017 602.gcc 输入数据为 train,使用 time 采集运行时间
602.gcc 运行 3 次采集运行时间测试结果。 | Zoltraak 是否开启 | 602.gcc 平均运行时间 | | :—————: | :——————: | | 否 | 44.703 sec | | 是 | 44.288 sec |
iperf3 运行 60 秒,获取 iperf3 输出的带宽指标。 | Zoltraak | iperf3 Receiver Bitrate | | ——– | :———————: | | 否 | 17.4 Gbits/sec | | 是 | 18.2 Gbits/sec |
Zoltraak 开启后性能指标有细微提升,可以认为是系统误差。基于上述实验结果,可以认为 Zoltraak 具有极低的性能开销,适合作为可观测性工具使用。
©Copyright 2023 CCF 开源发展委员会 Powered by Trustie& IntelliDE 京ICP备13000930号
Zoltraak
1 背景与目标
1.1 背景
ebpf 是一种新兴的内核技术,使开发者能够在内核级别收集和分析系统性能数据。通过 eBPF,可以监控各种内核事件,例如系统调用、上下文切换、进程调度、文件系统操作等,而无需修改应用程序代码或重启系统。eBPF 程序可以附加到特定的内核探针(如 kprobe 和 tracepoint),实时收集详细的运行时信息,将其传输到用户空间,并生成更高层次的性能分析和可视化数据。这种实时、低开销的可观测性使得 eBPF 成为监控和调试 Linux 系统的关键技术,广泛应用于性能调优和故障排查等场景。
目前,ebpf 社区主流的开发工具有 BCC、libbpf,主流的诊断工具有 BCC examples、bpftraces 等。基于 BCC 开发框架在部署上比较方便,但运行环境需要安装完整工具链,并且在部署时需要现场编译,性能开销过高;基于libbpf的原生开发方案ebpf程序运行性能开销低,但 C/C++ 开发难度较大,对开发人员不友好。ebpf 社区开发了基于 Go 语言与 Rust 语言的原生开发框架,但也只针对特定语言。
在容器异常检测上,我们主要针对混部场景的容器资源竞争进行检测。基于监督学习的方法需要大量标注好的训练数据,覆盖工作负载有限,较难落地;无监督学习方法根据历史数据模式识别异常,正确率有限。结合 ebpf 的可观测性功能,以及对性能异常数据检测工具的调研,我们提出以下 3 个观点:
1.2 目标
题目初始的目标有 4 项,Zoltraak 全部完成:
对于目标 1, Zoltraak 使用基于 libbpf 的原生框架开发,在 JIT 预热之后 CPU 开销 < 1%;
对于目标 2,Zoltraak 设计了丰富的性能指标,可供可观测数据平台分析使用。同时开发了精准的异常检测算法。详见 2.1 与 2.2。
对于目标 3,Zoltraak 自研了基于 Echarts 的可视化界面,方便查看性能数据与异常检测结果。
对于目标 4,Zoltraak 设计了基于动态库的 ebpf 程序部署方式,可以给多种编程提供服务,将 ebpf 程序开发与指标数据存储处理开发工作解耦。并且,Zoltraak 框架保留了原生libbpf的性能优势,在添加 ebpf 功能时,ebpf 开发人员暴露相关接口,由上层开发人员调用接口启动并对ebpf数据进行读取。另外,Zoltraak 也能基于 Json 配置文件配置已开发的功能。
2 实现
2.1 指标采集
Zoltraak 的指标设计有几点原则:
基于以上原则,Zoltraak 实现了如下指标的采集:
2.2 异常检测
Zoltraak 实现了基于无监督离线学习的脚本进行异常监测,并在实验数据上验证的了算法正确性。但如同 1.1 中所述,我们不推荐使用机器学习方法,故仅提供脚本代码作为参考。
2.2.1 CPU 资源竞争检测
BCC examples 提供的 CPU 资源竞争检测是通过 runqueue length 这一指标进行评估;Netfix 则使用 runqueue latency 与 context switch out 2 个指标对容器间的 CPU 资源竞争进行评估。Zoltraak 采集 context switch out,并基于该数据建立有向图,使用 Tarjan 算法获取有向图的强连通分量。当强连通分量内点的个数 > 1 时,可以认为发生了 CPU 资源竞争。节点中的边权信息是 context switch out 次数,其代表 CPU 资源竞争的激烈程度。根据节点出入度与应用类别(延迟敏感/批处理),上层调度器可以实现简单的调度算法处理该异常。
相较于 BCC examples 的方案,Zoltraak 方案的优势是:
相较于 Netfix 容器干扰邻居检测,Zoltraak 的优势是:
2.2.2 锁阈值检测与 OOM 检测
Zoltraak 框架可以采集陷入 Syscall Futex 与 Semop 的时间,该时间与墙上时间的比值,可以一定程度上反映对锁的利用程度。当高于某个阈值时,可以认为锁使用上发生了异常。
Zoltraak 也能捕获 OOM 事件,该事件是异常事件,ebpf 可以采集 OOM 发生时的函数栈,内存页数量与触发 OOM 的原因。上层调度器可有根据原因与内存页数量判断该程序是存在内存泄漏 BUG 或者是由于容器配置异常所致。
ebpf 功能拓展
ebpf 程序与可观测数据平台代码之间的融合是一个棘手的问题,有几种方案:
针对以上框架和问题,我们有以下思考:
Zoltraak 的解决方案,是 ebpf 开发人员开发 ebpf 程序,并暴露出 API 供其他程序调用。这样部署时只需要在目标机器上添加一份动态链接库文件即可。上层监控平台人员通过接口启动 ebpf 程序并采集性能数据。具体到 Zoltraak 实现上,ebpf 程序仅需要暴露 start,read,clean_up 完成对上层框架的对接。上层程序仅需要实现 Manager 的子类,调用对应接口完成启动到采集数据,存储到数据库整个过程。Zoltraak 框架设计完成了 ebpf 开发与上层监控平台开发的解耦。
Zoltraak ebpf 侧使用 libbpf 原生开发,上层数据采集与处理使用 dotnet8,时序数据库使用 Influxdb2.7。得益于 C ABI 的稳定性,Zoltraak 提出的 ebpf 程序开发与部署方案适用于绝大多数语言,可以迁移到其他平台上。
3 使用
在 oos_ebpf 目录下,输入如下指令
influxdb 的配置信息在 config/influx.json 中编辑,需要有 metrics 与 abnormal 2 个 bucket。
启动 Zoltraak 采集器指令如下所示:
启动可视化 Web 程序命令如下所示:
4 测试
4.1 测试环境
4.2 测试软件
我们通过 iperf3 与 SPECCPU 2017 602.gcc 工作负载评价。分别运行在 Zoltraak 未启动与 Zoltraak 启动时运行负载,对比运行时间与输出的性能指标。
4.3 测试结果
602.gcc 运行 3 次采集运行时间测试结果。 | Zoltraak 是否开启 | 602.gcc 平均运行时间 | | :—————: | :——————: | | 否 | 44.703 sec | | 是 | 44.288 sec |
iperf3 运行 60 秒,获取 iperf3 输出的带宽指标。 | Zoltraak | iperf3 Receiver Bitrate | | ——– | :———————: | | 否 | 17.4 Gbits/sec | | 是 | 18.2 Gbits/sec |
Zoltraak 开启后性能指标有细微提升,可以认为是系统误差。基于上述实验结果,可以认为 Zoltraak 具有极低的性能开销,适合作为可观测性工具使用。