目录

基于eBPF的系统异常观测与根因定位工具

这是一个面向 openKylin 2.0 SP2 / Linux Kernel 6.6+ 的轻量级 Go + eBPF 根因分析工具。该工具采集内核跟踪点证据,在 Go 中进行聚合,执行基于规则的诊断,并输出结构化 JSON 报告和易读的 Markdown 报告。

已覆盖场景

场景 状态 主要信号
CPU_HIGH_USAGE 完成 调度器跟踪点 + 调度等待 + 运行队列 + perf 辅助热点分析
SYSCALL_HOTSPOT 完成 目标优先的原始系统调用进入/退出归因
IO_LATENCY_JITTER 完成 块设备延迟 + diskstats 队列深度 + 基于置信度评分的文件归因 + libaio 归因
MEMORY_PRESSURE / MEMORY_RECLAIM_JITTER 完成 缺页异常 + 内存分配/释放 + 内存回收 + PSI/vmstat + cgroup v2
LOCK_CONTENTION 完成
futex 进入/退出、等待栈、futex VMA 映射、可选的受控互斥锁归因

快速开始

sudo bash scripts/install_deps.sh
bash scripts/check_env.sh
make check
make build
sudo make run-all
sudo make overhead

系统架构

工作负载脚本
  -> eBPF 探针层(bpf/ 目录下的 C 跟踪点程序)
  -> Go 采集器层(github.com/cilium/ebpf)
  -> 分析器/规则引擎(阈值来自 configs/default.yaml)
  -> 证据链 + 相关进程/对象选择
  -> outputs/ 目录下的 JSON 报告 + Markdown 报告

诊断结果并不是针对某个场景硬编码得到的。每个 suspected_root_cause 都由 key_metrics、配置阈值和 evidence_chain 共同推导得出。

环境配置

sudo bash scripts/install_deps.sh

所需的构建和运行工具包括 Go、clang/llvm、bpftool、libbpf 头文件、make、位于 /sys/kernel/btf/vmlinux 的 BTF、tracefs/debugfs 访问权限,以及用于加载 eBPF 程序的 sudo/root 权限。场景复现工作负载使用 stress-ngfio;在可行情况下,内存和锁场景也提供备用实现。

在 openKylin 中,软件包安装可能受到系统保护机制限制。如果 apt 被 ostree-pkgs-guard 阻止,请使用 openKylin 支持的机制,例如:

sudo mm-cli -o
sudo reboot

请勿手动移除系统保护机制。

环境检查

bash scripts/check_env.sh

该命令会生成 docs/env_check.md,并检查 BTF、bpftool、编译工具、fio/stress-ng、内存相关 /proc 文件、cgroup v2 内存文件、块设备跟踪点、futex 跟踪点、sched 跟踪点(包括可选的调度等待/运行队列信号)、perf-event 分析前置条件、gcc 和 pthread 编译能力。

构建

make check
make build

make generate 会将所有 eBPF C 程序编译为 bpf/*.bpf.o,其中包括可选的 I/O 文件路径/libaio 跟踪器;make build 会生成 bin/rca

场景复现命令

推荐用于最终验证的命令:

make check
make build
sudo make run-all
sudo make overhead

单场景复现命令:

sudo make run-cpu
sudo make run-syscall
sudo make run-syscall-controlled   # 可选:运行受控 syscall_stress fcntl 热点场景
sudo make run-io
sudo make run-memory
sudo make run-memory-cgroup
sudo make run-lock
sudo make run-lock-controlled      # 可选:运行受控 pthread 互斥锁归因场景

按顺序运行全部场景复现,并生成汇总结果:

sudo make run-all

旧版 demo-* 目标仍作为现有脚本的兼容别名保留。

各场景输出如下:

场景 JSON Markdown
CPU_HIGH_USAGE outputs/cpu_result.json outputs/cpu_result.md
SYSCALL_HOTSPOT outputs/syscall_result.json outputs/syscall_result.md
SYSCALL_HOTSPOT_CONTROLLED outputs/syscall_controlled_result.json outputs/syscall_controlled_result.md
IO_LATENCY_JITTER outputs/io_result.json outputs/io_result.md
MEMORY_PRESSURE outputs/mem_result.json outputs/mem_result.md
MEMORY_PRESSURE cgroup 视图 outputs/mem_cgroup_result.json outputs/mem_cgroup_result.md
LOCK_CONTENTION outputs/lock_result.json outputs/lock_result.md
LOCK_CONTENTION_CONTROLLED outputs/lock_controlled_result.json outputs/lock_controlled_result.md
全部场景汇总 outputs/all_result.json outputs/all_result.md

运行 sudo make run-cpu 时,CPU 的 perf 辅助热点分析还会生成 outputs/cpu_hotspot_perf.txtoutputs/cpu_hotspot.json。在直接使用 CLI 时,也可以通过 --enable-cpu-hotspot 启用相同的分析功能;即使 perf 分析失败,也不会导致 CPU 场景复现或 CPU_HIGH_USAGE 诊断失败。

手动使用 CLI

sudo ./bin/rca --mode cpu --duration 60 --config configs/default.yaml --target-comm stress-ng-cpu --enable-cpu-hotspot --hotspot-duration 15 --hotspot-frequency 49 --progress --progress-interval 5 --output outputs/cpu_result.json
sudo ./bin/rca --mode syscall --duration 60 --config configs/default.yaml --output outputs/syscall_result.json
sudo ./bin/rca --mode io --duration 60 --config configs/default.yaml --output outputs/io_result.json --target-comm fio --target-file /var/tmp/fio-test.img --progress --progress-interval 5
sudo ./bin/rca --mode memory --duration 60 --config configs/default.yaml --output outputs/mem_result.json --progress --progress-interval 5
sudo ./bin/rca --mode memory --duration 60 --config configs/default.yaml --target-comm stress-ng-vm --target-cgroup /sys/fs/cgroup/rca_mem_demo --output outputs/mem_cgroup_result.json --progress --progress-interval 5
sudo ./bin/rca --mode lock --duration 60 --config configs/default.yaml --output outputs/lock_result.json --progress --progress-interval 5
sudo ./bin/rca --mode all --duration 60 --config configs/default.yaml --output outputs/all_result.json

使用 --target-pid--target-comm,可以在根因归因时优先选择指定工作负载。

完整的场景复现应使用 sudo make run-all,因为该命令会启动工作负载并聚合各场景结果。直接运行 sudo ./bin/rca --mode all 只会执行用于多信号分析的采集器流程,不会自行复现所有工作负载。

直接使用 CLI 时,可以选择启用终端可视化:

sudo ./bin/rca --mode cpu --duration 30 --config configs/default.yaml --target-comm stress-ng-cpu --progress --progress-interval 5 --output outputs/cpu_result.json

--progress 会将分阶段实时状态输出到 stderr,--quiet 会关闭进度和汇总输出。run-* 场景复现目标默认启用进度显示。进度信息只显示在终端中,不会改变 JSON 和 Markdown 报告的结构。

本地监听 UI

pip3 install -r requirements-ui.txt
sudo -E make ui
python3 -m streamlit run ui/app.py

在浏览器中访问 http://127.0.0.1:8501。本地 UI 仅负责启动 ./bin/rca 进行监听并显示实时日志,不负责启动压力负载。压力负载需要用户在终端中手动启动。所有诊断逻辑仍由 ./bin/rca 完成,最终结果以 outputs/*.jsonoutputs/*.md 为准。

各场景使用的跟踪点

场景 跟踪点/输入
CPU_HIGH_USAGE sched/sched_switchsched/sched_wakeupsched/sched_wakeup_new、可选的 sched/sched_stat_wait/proc/stat/proc/loadavg、可选的 /proc/sched_debug
SYSCALL_HOTSPOT raw_syscalls/sys_enterraw_syscalls/sys_exit
IO_LATENCY_JITTER block/block_rq_issueblock/block_rq_complete;可选的文件归因跟踪点:syscalls/sys_enter_openatsyscalls/sys_exit_openatsyscalls/sys_enter_openat2syscalls/sys_exit_openat2syscalls/sys_enter_closesyscalls/sys_enter_read/write/pread64/pwrite64 及其退出跟踪点;libaio:syscalls/sys_enter_io_submitsyscalls/sys_exit_io_submitsyscalls/sys_enter_io_geteventssyscalls/sys_exit_io_getevents
MEMORY_PRESSURE exceptions/page_fault_userexceptions/page_fault_kernelkmem/mm_page_allockmem/mm_page_free、vmscan 跟踪点、/proc/meminfo/proc/vmstat/proc/pressure/memory、可选的 cgroup v2 memory.current/high/max/events/stat/pressure/proc/<pid>/status/proc/<pid>/smaps_rollup
LOCK_CONTENTION 首选:syscalls/sys_enter_futexsyscalls/sys_exit_futex;备用:raw_syscalls/sys_enterraw_syscalls/sys_exit;可选:sched/sched_switch

输出字段

场景指标包括:

  • CPU:CPU 使用率、上下文切换次数、调度事件、loadavg、可运行任务数、优先采用 sched_stat_wait 的调度等待延迟、运行队列来源及准确度(支持可选的 BTF+kprobe rq->nr_running,并在失败时回退到 eBPF 估算器)、目标调度任务,以及 perf 辅助的热点函数/调用栈候选字段。如果无法使用 perf-event 栈采样或符号解析,则由 unavailable_features 记录该情况,而不会虚构函数名称。
  • 系统调用:采用目标优先的根因诊断方式,并提供可选的受控 syscall_stress 工作负载,用于稳定复现 fcntl/openat/read/write/阻塞读取热点。target_root_causetarget_latency_summary 由所选 PID/comm 推导;global_background 用于保留全局热点和阻塞系统调用上下文,但不会将非目标进程中的 futex/ppoll/read 活动作为根因。系统调用名称优先从系统 unistd 头文件解析,并提供 x86_64 备用映射;无法解析的系统调用 ID 会被报告。
  • I/O:包括 IOPS、eBPF 块请求完成延迟、P99、最大延迟、慢 I/O 数量、eBPF 延迟直方图、主要设备/进程、从 /sys/block/<device>/stat/proc/diskstats 获取的运行时 await/队列深度,以及基于置信度评分的文件归因。文件归因综合使用工作负载目标文件元数据、openat 文件描述符—路径跟踪、/proc/<pid>/fd 扫描、存在时的 fd read/write/pread/pwrite 活动、libaio io_submit 中 iocb 的 fd/op/bytes 解析、inode/dev/mount 映射以及块设备关联。fio 的 iodepth/numjobs 仍只作为工作负载压力配置,不会被报告为实际观测到的在途 I/O 数量。
  • 内存:包括系统可用内存、缺页异常、页面分配/释放、PSI/vmstat 内存回收增量、可选的 cgroup v2 memory.current/high/max/events/stat/pressure、来自 memory.events 的 cgroup OOM kill 证据、目标进程的 VmRSS/VmSize/RssAnon/VmSwap 与 smaps_rollup 信息、目标工作负载证据,以及全局内存活动热点。只有在观测指标支持时才会报告 OOM 风险和 CGROUP_OOM_KILL;默认场景复现不会强制触发真实的 OOM kill。
  • 锁:包括 futex 等待延迟、长时间等待、主要等待线程、主要 futex 地址、futex/等待/off-CPU 速率、可选的 off-CPU 切换信号、futex 等待栈聚合,以及 futex 地址到 VMA/模块的映射。可选的受控 lock_stress 场景在观测到的元数据与 futex 地址匹配时,可将其映射为 global_hot_mutex;对于通用程序,该归因仍属于尽力而为。

每份主要报告包含:

  • anomaly_type:规则判断结果,例如 CPU_HIGH_USAGESYSCALL_HOTSPOTIO_LATENCY_JITTERMEMORY_PRESSURELOCK_CONTENTION
  • time_window:采集开始/结束时间。
  • related_process:根据采集证据选出的 PID/TID/comm。
  • related_object:适用时对应的块设备或 futex 对象。
  • key_metrics:规则引擎使用的结构化指标。
  • evidence_chain:支持诊断结论的精简证据。
  • suspected_root_cause:由规则生成的疑似根因。
  • suggestion:建议采取的后续操作。
  • confidence:0~1 的置信度评分。
  • raw_events_summary:精简的原始事件计数。
  • collector:采集后端、eBPF 程序及已附加的跟踪点。

结果示例

示例结构位于 examples/ 目录中。运行场景复现后,当前机器的真实结果位于 outputs/ 目录中。docs/results_summary.md 用于汇总最新生成的结果文件,提交前应通过以下命令重新生成:

python3 scripts/update_results_summary.py

性能开销

本地性能开销测试方法和测量结果记录在 docs/overhead.md 中。运行:

sudo make overhead

性能开销流程会将分阶段进度和最终性能摘要输出到 stderr。默认设置为 OVERHEAD_PROGRESS=1OVERHEAD_QUIET=0;可设置 OVERHEAD_QUIET=1 关闭进度输出,同时保留最终输出路径。进度输出不属于测量数据源,也不会写入 fio JSON、工作负载指标 JSON 或 RCA 进程采样 CSV 文件。

性能开销流程会在 outputs/overhead/ 中记录原始产物,并报告:

  • 根据 fio 的 IOPS、带宽、平均延迟和 p99 延迟评估 I/O 工作负载影响。
  • 根据 tools/syscall_stress/syscall_stress 的每秒操作数评估受控系统调用工作负载影响。
  • 根据 tools/lock_stress/lock_stress 的每秒加锁操作数评估受控锁工作负载影响。
  • 在启用 RCA 的运行过程中采样 RCA 进程的 CPU/RSS。

系统调用/锁吞吐量部分属于可选的受控工作负载测量。如果某个工作负载或指标文件不可用,报告会将对应部分标记为不可用,而不会虚构数据。所有数值均只应视为本地 openKylin 虚拟机上的测量结果。

openKylin 适配说明

该项目已在当前虚拟机中的 openKylin 2.0 SP2 与 Linux Kernel 6.6+ 环境下完成验证。项目依赖 BTF、tracefs/debugfs 和内核跟踪点的可用性。在支持的情况下,缺失的可选跟踪点会记录在输出中;缺失必需跟踪点时则会返回明确错误。

多架构适配计划

Makefile 会为 x86_64、aarch64 和 riscv64 选择相应的 BPF 目标架构编译参数。ARM/RISC-V 的实际运行时验证、系统调用 ID/名称映射以及跟踪点格式验证,仍属于后续计划中的适配工作。

安全性

场景复现脚本运行的是带有超时限制和清理 trap 的有界工作负载。默认情况下,这些脚本不会删除工作负载文件,也不会执行破坏性系统操作。I/O 场景文件默认位于 /var/tmp。高内存压力场景为可选项,必须手动运行。cgroup 内存场景复现被限制在 /sys/fs/cgroup/rca_mem_demo 中,并会在采集完成后清理工作负载和 cgroup。

关于
190.5 MB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号