使用 Cloudflare 的 ebpf_exporter 创建自定义 eBPF 监控探针

ebpf_exporter 是由 Cloudflare 开发的一个 Prometheus 导出器,允许用户编写自定义的 eBPF 程序以监控和检测系统指标。本文将介绍如何使用 ebpf_exporter 创建包括 CPU 错误率和 IO 错误率在内的自定义探针,并提供完整的项目创建流程。

项目概述

ebpf_exporter 使得用户能够通过编写 eBPF 程序来收集内核级别的自定义指标,并将这些指标以 Prometheus 兼容的格式导出。其主要功能包括:

  • 支持自定义 eBPF 探针
  • 集成 Prometheus 进行指标收集
  • 提供丰富的配置选项以定义和管理指标
  • 支持从内核读取 eBPF 程序的 BTF 信息

创建自定义探针的完整流程

以下是创建包含 CPU 错误率和 IO 错误率监控的自定义 eBPF 探针的完整流程。

1. 克隆仓库并构建项目

首先,克隆 ebpf_exporter 仓库并构建项目。

git clone https://github.com/cloudflare/ebpf_exporter.git
cd ebpf_exporter
make build

该命令将构建一个静态链接的二进制文件 ebpf_exporter

2. 编写自定义 eBPF 程序

cmd/ebpf_exporter 目录下编写自定义的 eBPF 程序,以捕获 CPU 错误率和 IO 错误率。以下是一个示例:

// cmd/ebpf_exporter/cpu_io_errors.bpf.c

#include <vmlinux.h>
#include <bpf/bpf_tracing.h>
#include "maps.bpf.h"

struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __uint(max_entries, 1024);
    __type(key, u64);
    __type(value, u64);
} cpu_errors_total SEC(".maps");

struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __uint(max_entries, 1024);
    __type(key, u64);
    __type(value, u64);
} io_errors_total SEC(".maps");

SEC("tp_btf/sched_process_exit")
int BPF_PROG(cpu_error_monitor, struct task_struct *task)
{
    u64 key = 0;
    u64 *count;

    // 假设通过某种方式检测到 CPU 错误
    count = bpf_map_lookup_elem(&cpu_errors_total, &key);
    if (count) {
        __sync_fetch_and_add(count, 1);
    }

    return 0;
}

SEC("tp_btf/block_rq_insert")
int BPF_PROG(io_error_monitor, struct request *req)
{
    u64 key = 0;
    u64 *count;

    // 假设通过某种方式检测到 IO 错误
    count = bpf_map_lookup_elem(&io_errors_total, &key);
    if (count) {
        __sync_fetch_and_add(count, 1);
    }

    return 0;
}

char LICENSE[] SEC("license") = "GPL";

3. 配置 ebpf_exporter

创建一个配置文件 config.yaml 来定义如何导出这些指标。

# config.yaml

metrics:
  counters:
    - name: cpu_errors_total
      help: CPU 错误总数
      labels:
        - name: cpu
          size: 8
          decoders:
            - name: ksym

    - name: io_errors_total
      help: IO 错误总数
      labels:
        - name: device
          size: 8
          decoders:
            - name: string

4. 编译 eBPF 程序

编译自定义的 eBPF 程序。

make -C cmd/ebpf_exporter build

这将在 cmd/ebpf_exporter 目录下生成相应的 ELF 文件。

5. 运行 ebpf_exporter

启动 ebpf_exporter 并指定配置文件。

sudo ./ebpf_exporter --config.dir=./configs --config.names=cpu_io_errors

6. 配置 Prometheus 采集指标

编辑 Prometheus 配置文件 prometheus.yml,添加 ebpf_exporter 作为一个新的抓取目标。

# prometheus.yml

scrape_configs:
  - job_name: 'ebpf_exporter'
    static_configs:
      - targets: ['localhost:9435']

重新启动 Prometheus 以应用新的配置。

7. 可视化指标

使用 Grafana 等工具连接 Prometheus,创建仪表盘以可视化 CPU 错误率和 IO 错误率。

详细代码示例

以下是项目中关键文件的示例代码。

自定义 eBPF 程序

#include <vmlinux.h>
#include <bpf/bpf_tracing.h>
#include "maps.bpf.h"

struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __uint(max_entries, 1024);
    __type(key, u64);
    __type(value, u64);
} cpu_errors_total SEC(".maps");

struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __uint(max_entries, 1024);
    __type(key, u64);
    __type(value, u64);
} io_errors_total SEC(".maps");

SEC("tp_btf/sched_process_exit")
int BPF_PROG(cpu_error_monitor, struct task_struct *task)
{
    u64 key = 0;
    u64 *count;

    // 假设通过某种方式检测到 CPU 错误
    count = bpf_map_lookup_elem(&cpu_errors_total, &key);
    if (count) {
        __sync_fetch_and_add(count, 1);
    }

    return 0;
}

SEC("tp_btf/block_rq_insert")
int BPF_PROG(io_error_monitor, struct request *req)
{
    u64 key = 0;
    u64 *count;

    // 假设通过某种方式检测到 IO 错误
    count = bpf_map_lookup_elem(&io_errors_total, &key);
    if (count) {
        __sync_fetch_and_add(count, 1);
    }

    return 0;
}

char LICENSE[] SEC("license") = "GPL";

配置文件

metrics:
  counters:
    - name: cpu_errors_total
      help: CPU 错误总数
      labels:
        - name: cpu
          size: 8
          decoders:
            - name: ksym

    - name: io_errors_total
      help: IO 错误总数
      labels:
        - name: device
          size: 8
          decoders:
            - name: string

参考资源

结论

通过 ebpf_exporter,您可以创建高度自定义的 eBPF 探针来监控系统的各种指标,如 CPU 错误率和 IO 错误率。该工具结合了 eBPF 的强大功能和 Prometheus 的灵活性,适用于需要深度系统监控和性能分析的场景。

License

MIT

资源链接

贡献者

感谢所有贡献者的努力!

标签

performance, linux-kernel, prometheus, tracing, prometheus-exporter, ebpf, bpf, libbpf

结束语

通过以上步骤,您可以成功创建并部署自定义的 eBPF 监控探针,实时监控系统的 CPU 和 IO 错误率,提升系统的可观测性和稳定性。

参考链接

完整项目创建流程示例

以下是一个示例项目结构及其关键文件:

ebpf-monitoring/
├── cmd/
│   └── ebpf_exporter/
│       ├── cpu_io_errors.bpf.c
│       └── Makefile
├── configs/
│   └── cpu_io_errors.yaml
├── Dockerfile
├── prometheus.yml
├── README.md
└── scripts/
    └── build.sh

示例 Makefile

CC = clang
CFLAGS = -O2 -g -Wall -target bpf -c

cpu_io_errors.bpf.o: cpu_io_errors.bpf.c
    $(CC) $(CFLAGS) $< -o $@

示例 Dockerfile

FROM ubuntu:20.04

RUN apt-get update && apt-get install -y \
    clang \
    llvm \
    make \
    git \
    && rm -rf /var/lib/apt/lists/*

COPY . /ebpf-monitoring
WORKDIR /ebpf-monitoring

RUN make -C cmd/ebpf_exporter build

CMD ["./cmd/ebpf_exporter/ebpf_exporter", "--config.dir=./configs", "--config.names=cpu_io_errors"]

示例 prometheus.yml

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'ebpf_exporter'
    static_configs:
      - targets: ['ebpf_exporter:9435']

示例 README.md

# eBPF Monitoring 项目

本项目使用 Cloudflare 的 `ebpf_exporter` 创建自定义 eBPF 探针,用于监控 CPU 错误率和 IO 错误率。

## 项目结构

- `cmd/ebpf_exporter/`: 包含自定义的 eBPF 程序和构建文件。
- `configs/`: 包含 Prometheus 配置文件。
- `Dockerfile`: 用于构建包含 eBPF 探针的 Docker 镜像。
- `prometheus.yml`: Prometheus 配置文件。
- `scripts/`: 包含辅助脚本。

## 构建和运行

### 使用 Makefile 构建 eBPF 程序

```bash
cd cmd/ebpf_exporter
make

构建 Docker 镜像

docker build -t ebpf-monitoring .

运行 Docker 容器

docker run --privileged -p 9435:9435 ebpf-monitoring

配置 Prometheus

prometheus.yml 配置文件挂载到 Prometheus 容器中,并启动 Prometheus。

docker run -d -p 9090:9090 -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus

可视化

使用 Grafana 连接到 Prometheus,创建仪表盘以显示 CPU 错误率和 IO 错误率。

更多推荐