目录

EKD

EKD 是面向 Linux/openKylin 的轻量级系统异常观测与根因定位工具。它以固定 10 Hz Base 数据面持续采集低成本主机指标,在异常窗口内按需开启 eBPF Deep 探针,再用可回溯的 YAML 规则输出结构化诊断。规则层是异常类型与疑似根因的唯一权威;缺失指标、采集降级和事件丢失 都会进入报告,不会被解释为零值。

能力

  • 覆盖 CPU/调度、块 I/O、内存回收/OOM 风险、futex 锁竞争和系统调用代理五类场景。
  • /proc、PSI 与 eBPF 直方图统一发布为 100 ms BaseFrame,保留有效性、状态和采集质量。
  • 三层检测:静态持续阈值、Hampel/EWMA/Page-Hinkley、SPOT 极值检测。
  • 一等 AnomalyWindow,严格区分异常结束 last_active 与 quiet 确认关闭时刻。
  • Deep 阶段按 top-k 进程/线程定向开启栈、futex、通用 syscall、PMU 与页错误映射归因。
  • bpf_iter__task 一次读取全量 task 计数器,由用户态按稳定身份做 delta/top-k;不可用时回退 /proc
  • 可选 causal 服务按固定先验验证滞后传播路径,带有效样本、split-half、方向和采集质量守卫。
  • 前台 daemon 通过有界 Unix 控制 socket 发布原子 status/report 快照,支持 statusreportattach 客户端。
  • Self-protect 持续监测自身 CPU/RSS、处理延迟和 BPF/Deep 丢失,按带滞回的四级预算保护 Base/Detector/Direct。
  • on/off-CPU 栈按完整路径聚合,可发布 folded stacks 与无需外部脚本的 SVG 火焰图。
  • JSON 与 Markdown 报告包含异常类型、对象、指标、时间窗口、根因、证据链、建议和限制。
  • BPF 不可用时自动降级为 /proc-only,不中断主流程。

block request 的稳定进程/cgroup 归因已经可用;报告会明确 标记无法可靠获得的文件路径等来源,现有 Direct 诊断不依赖这些增强项。

架构

/proc + PSI + always-on BPF
            |
       BaseFrame (10 Hz) -> BaseStore
                               | \
                               |  +-> Detector -> AnomalyWindow -> ProbePlanner
                               |                   |                  |
                               |                 Direct          Deep eBPF (top-k)
                               |                   |                  |
                               +-> causal service  +--------+---------+
                                      (optional)            |
                                                   report merger
                                                        |
                                                 JSON / Markdown

完整设计与数据语义见 docs/design.md

构建

openKylin/Ubuntu 系依赖:

sudo apt-get update
sudo apt-get install -y build-essential cmake pkg-config clang llvm libbpf-dev bpftool \
  nlohmann-json3-dev libyaml-cpp-dev libspdlog-dev libfmt-dev libgtest-dev cargo rustc

cmake -B build -S .
cmake --build build -j$(nproc)
ctest --test-dir build --output-on-failure
./build/src/cli/ekd --version

没有 BPF 工具链或权限的环境可构建降级版:

cmake -B build-off -S . -DEKD_ENABLE_BPF=OFF
cmake --build build-off -j$(nproc)
ctest --test-dir build-off --output-on-failure

详细依赖、capability 与 systemd 部署说明见 docs/install.md

使用

1. 运行前检查

完整模式需要 root,或 CAP_BPFCAP_PERFMONCAP_SYS_ADMIN 和跨用户符号化所需的 CAP_SYS_PTRACE。先确认版本、规则和基础采集正常:

./build/src/cli/ekd --version
./build/src/cli/ekd sample --count 3 --interval-ms 1000

sample 主要用于检查 /proc、PSI、BPF 指标和任务候选是否可见,不生成诊断报告。BPF iterator 可用时任务候选来自一次全量 task 快照;不可用时自动回退 /proc/<pid>

2. 一次性观测与完整产物

推荐同时保存机器可读 JSON、人工报告和窗口级原始时序:

mkdir -p reports/manual/sessions
sudo ./build/src/cli/ekd run --duration 180 \
  --interval-ms 1000 \
  --rules rules \
  --schema-version 2 \
  --report reports/manual/diagnosis.json \
  --markdown reports/manual/diagnosis.md \
  --artifact-dir reports/manual/sessions \
  --flamegraph-dir reports/manual/sessions

Base 数据面固定按 100 ms 采集;--interval-ms 控制检测和窗口推进周期,不会把 Base 改成 1 Hz。--duration 0 表示持续运行直到收到 SIGINT/SIGTERM。中断会正常关闭窗口并写报告。

JSON 默认为兼容 schema v1。上例使用 schema v2,将每条诊断分为 anomalymechanism_diagnosisattributionfinal_diagnosis。窗口关闭后,产物目录形如:

reports/manual/sessions/session-<start_wall_ns>-window-<id>/
  diagnosis.json          窗口级结构化诊断
  diagnosis.md            窗口级人工报告
  metrics.json            全部 Base 指标、时间戳、状态和来源
  metrics.csv             表格形式的同一份时序
  metrics-trends.svg      独立趋势图
  oncpu.folded / oncpu.svg
  offcpu.folded / offcpu.svg

只有窗口内确实采集到对应栈时才生成 on/off-CPU 文件。metrics.json/CSV 是原始证据,SVG 只用于展示,不能替代原始时序。

快速查看最终诊断而不依赖 jq

python3 - reports/manual/diagnosis.json <<'PY'
import json, sys
d = json.load(open(sys.argv[1], encoding="utf-8"))
print("anomaly_count:", d["anomaly_count"])
for item in d["diagnoses"]:
    final = item.get("final_diagnosis", item)
    mechanism = item.get("mechanism_diagnosis", item)
    print(mechanism.get("anomaly_type"), final.get("status", item.get("root_cause_status")),
          final.get("root_cause", item.get("root_cause")))
PY

进度写入 stderr,JSON/Markdown 写入指定文件;未指定两个输出参数时,JSON 写到 stdout。 检测到异常仍返回退出码 0,因为异常属于业务结果;参数错误返回 2,规则/报告/socket 等工具故障返回 1。

3. 参数速查

常用参数如下,完整说明见 docs/usage.md

参数 默认值 用途
--duration N 180 观测秒数;0 表示持续运行
--interval-ms N 1000 检测周期;Base 始终为 100 ms
--rules DIR 内建规则 加载 YAML 规则目录
--top-k N 5 报告和 Deep allowlist 的候选进程数
--schema-version 1/2 1 兼容或分层 JSON schema
--artifact-dir DIR 关闭 保存每个异常窗口的诊断和全指标时序
--flamegraph-dir DIR 关闭 保存 folded stacks 与 SVG 火焰图
--causal-socket PATH 关闭 调用可选 causal 服务
--control-socket PATH 关闭 发布 daemon 控制 socket
--protect-cpu-pct N 10 Self-protect 单核 CPU 百分比上限
--protect-rss-mb N 256 Self-protect 当前 RSS 上限
--quiet 关闭 不打印逐样本进度

采样或短时观测示例:

./build/src/cli/ekd run --duration 30 --interval-ms 500 --top-k 5
./build/src/cli/ekd sample --count 3 --interval-ms 1000

4. 启用因果服务

因果层是可选组件。先在普通用户下启动独立服务,再让 root 运行的 agent 连接 socket:

causal-svc/.venv/bin/python causal-svc/ekd_causal_service.py \
  --socket /tmp/ekd-causal.sock

# 另一个终端
sudo ./build/src/cli/ekd run --duration 180 \
  --causal-socket /tmp/ekd-causal.sock \
  --report reports/causal-diagnosis.json

因果结果为 acceptedinconclusiverejectedfailednot_run。它只补充 Base 指标的滞后传播路径,不覆写 Direct 的异常类型和对象根因;输入样本或 split-half 稳定性不足时 主动拒绝属于正常质量结论。

已有异常会话可以直接离线比较根因算法,无需重新运行 eBPF 采集:

causal-svc/.venv/bin/python causal-svc/experiments/compare_real_sessions.py \
  reports/mature-comparison-2026-07-30 \
  --output /tmp/rca-comparison.json \
  --markdown /tmp/rca-comparison.md

该脚本只读取各 session 的 metrics.json 和同目录 diagnosis.json,在 baseline 上拟合 N-sigma、BARO、CIRCA RHT、PCMCI+ 和 RRF。当前历史对比默认选择 BARO + CIRCA RRF。

5. daemon 与控制面

持续运行并从另一个终端查询:

sudo ./build/src/cli/ekd run --duration 0 \
  --rules rules \
  --schema-version 2 \
  --control-socket /run/ekd/control.sock \
  --report /var/log/ekd/latest.json

# 另一个终端
./build/src/cli/ekd status --socket /run/ekd/control.sock
./build/src/cli/ekd report --socket /run/ekd/control.sock
./build/src/cli/ekd attach --socket /run/ekd/control.sock

status 输出当前窗口、Base 质量、规则、诊断数和 self-protect 预算;report 返回最近一次原子 报告快照;attach 只在控制序列发生变化时输出紧凑 JSON 行。完整 systemd 部署见 docs/install.md

运行中可用 SIGHUP 原子替换规则集。新规则加载失败时保留旧规则;成功后滚动基线重新预热:

kill -HUP $(pidof ekd)

6. 权限不足与降级

完整 BPF 模式建议使用 sudo。没有 BPF/BTF/capability 时程序不会伪造零值,而是记录 collection_limitations 并回退 /proc/PSI;依赖缺失指标的规则不参与裁决。若目标机不具备 BPF 工具链,可使用 build-off

cmake -B build-off -S . -DEKD_ENABLE_BPF=OFF
cmake --build build-off -j$(nproc)
./build-off/src/cli/ekd run --duration 30 --report /tmp/proc-only.json

常见排查顺序:先运行 sample --count 3;再查看报告的 run.collection_limitationsrun.self_protectevidence.collector_statusesevidence.collection_qualityunavailable 表示探针未具备条件,no_events 表示探针已运行但窗口内没有事件,二者不能混用。

复现与开销

sudo apt-get install -y stress-ng fio
./scripts/reproduce.sh
./scripts/reproduce.sh cpu io memory lock syscall
./scripts/measure_overhead.sh --duration 30 --repeats 3

复现报告默认写入 reports/。脚本会把期望异常类型与实际诊断做 MATCH/MISMATCH 对照, 并在 reports/<scenario>-sessions/session-<timestamp>-window-<id>/ 中保存该异常窗口独立的 JSON、Markdown、全指标 CSV/JSON/SVG 趋势和 folded/flame graph 产物。开销实验只使用新生成 的、带版本与环境信息的 session,不把未经复核的历史汇总日志当作项目证据。 验证契约见 docs/validation.md

报告保证

  • time_window.end 是最后一个异常信号时刻,不包含用于确认恢复的 quiet 样本。
  • BPF 锁、设备直方图和回收证据按完整异常窗口累积,不使用最后一个 interval 冒充窗口证据。
  • 通用 syscall 只在对应 Deep profile 内 attach,按目标 TGID 输出编号、名称、次数、错误数和耗时。
  • CPU Deep 只对冻结目标中的热点 TID 打开 PMU 事件组;IPC 与 miss ratio 按 multiplex 时间缩放。
  • Memory Deep 按稳定进程身份聚合热点虚拟页,每个 interval 快照解析 VMA、设备、inode 与 file offset。
  • close_reasonright_censored 区分自然恢复、运行结束和操作员中断。
  • evidence.collection_quality 显示 jitter、read span、drop、CPU/PMU 目标覆盖与 multiplex 质量。
  • run.self_protect 显示当前/最高保护级别、资源读数、有效 Deep 预算和有界转换历史。
  • 未命中规则时输出“未分类异常”,不会由 causal 或 Deep 数据编造根因。

目录

src/common   BaseFrame、BaseStore、指标契约
src/core     /proc 采集与 10 Hz 调度
src/detect   检测算法与异常窗口
src/rules    YAML Direct 规则与分析器
src/bpf      CO-RE BPF 程序
src/bpfcoll  BPF 生命周期、map 差分、栈与符号化
src/deep     ProbePlanner、有界窗口聚合与 worker
src/causal   对齐请求、生产质量守卫与异步 Unix socket client
causal-svc   独立 Tigramite 服务与离线实验
src/control  daemon status/report 快照协议与 Unix socket 生命周期
src/report   JSON/Markdown 报告
src/cli      前台运行入口
tests        单元与集成测试

项目面向 Linux kernel 6.6+,优先验证环境为 openKylin 2.0 SP2 x86_64。BPF CO-RE 设计可适配 其他具备 BTF 的发行版与架构,但 PMU、tracepoint、权限和虚拟化能力会按主机实际情况降级。

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

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