eBPF — це суперсила ядра Linux, що дозволяє безпечно підключати міні-програми для глибокого мережевого й системного спостереження без патчів ядра. У цій інструкції ми крок за кроком поставимо bpftrace і bpftool, запустимо корисні скрипти, а також зберемо метрики у Prometheus і намалюємо графіки в Grafana. Поїхали 🚀

Що потрібно знати перед стартом

Щоб eBPF працював стабільно для вашого Linux моніторинг, зверніть увагу на вимоги:

  • Ядро Linux 5.4+ бажано (eBPF працює й на старших 4.x, але з обмеженнями).
  • BTF (BPF Type Format) сильно спрощує життя: перевірити можна так:
ls /sys/kernel/btf/vmlinux

Якщо файлу немає — встановіть заголовки ядра й увімкніть BTF у вашому дистрибутиві (нижче покажу як).

Встановлення bpftrace і bpftool

Ми працюватимемо у термінал Linux. Нижче — як встановити програму в Linux на популярних дистрибутивах. Усі команди запускайте з правами sudo.

Debian/Ubuntu

sudo apt update
sudo apt install -y bpftrace bpftool bpfcc-tools linux-headers-$(uname -r)

Перевірка:

bpftrace -V
bpftool version

Fedora

sudo dnf install -y bpftrace bpftool bcc-tools kernel-devel

Arch/Manjaro

sudo pacman -S --noconfirm bpftrace bpftool bcc linux-headers

Швидка діагностика можливостей eBPF

bpftool feature

Ця команда підкаже, які можливості eBPF доступні у вашому ядрі.

Перші кроки з bpftrace: готові one-liners і скрипти

bpftrace — мова й утиліта для швидкого трасування. Ось кілька корисних прикладів для старту:

Топ системних викликів кожні 5 секунд

sudo bpftrace -e 'tracepoint:syscalls:sys_enter_* { @[probe] = count(); } interval:s:5 { print(@); clear(@); }'

Відслідковування відкриття файлів з іменами

sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%s %s\n", comm, str(args->filename)); }'

TCP ретрансміти (мережеві проблеми)

sudo bpftrace -e 'tracepoint:tcp:tcp_retransmit_skb { @[comm] = count(); } interval:s:10 { print(@); clear(@); }'

Скрипт-файл для моніторингу затримок блокових IO

Збережіть як bio_latency.bt і запустіть sudo bpftrace bio_latency.bt:

BEGIN { printf("Tracing block IO latency... Ctrl-C to end\n"); }
tracepoint:block:block_rq_issue { @start[args->dev] = nsecs; }
tracepoint:block:block_rq_complete /@start[args->dev]/ {
  $delta = (nsecs - @start[args->dev]) / 1000000; // ms
  @lat_ms = hist($delta);
  delete(@start[args->dev]);
}
interval:s:15 { print(@lat_ms); clear(@lat_ms); }

Альтернативні способи та інструменти

  • BCC (bpfcc-tools): десятки готових скриптів: execsnoop, opensnoop, tcpretrans, runqlat. Напр.: sudo /usr/sbin/opensnoop-bpfcc.
  • bpftool: низькорівневий інструмент для завантаження/перевірки програм eBPF, виводу карт, пінінгу в bpffs.
  • perf/trace-cmd: не eBPF, але добрі сусіди для профілювання й трасування, коли eBPF недоступний.

GUI-спосіб: Prometheus + Grafana

Інтегруємо eBPF-метрики в Prometheus. Покажу найпростіший шлях через textfile collector node_exporter, а також згадку про спеціальний ebpf_exporter. Це зручно для постійних дашбордів і алертів 🧪

Швидкий шлях: textfile collector у node_exporter

  1. Переконайтеся, що node_exporter запущено з параметром --collector.textfile.directory=/var/lib/node_exporter/textfile_collector.
  2. Створіть директорію:
sudo mkdir -p /var/lib/node_exporter/textfile_collector
sudo chown -R $(whoami) /var/lib/node_exporter/textfile_collector
  1. Створимо простий bash скрипт, що збирає ретрансміти TCP за 10 секунд і пише у формат Prometheus:
cat > ~/ebpf_tcp_retrans_exporter.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
OUT="/var/lib/node_exporter/textfile_collector/ebpf.prom"
# Запустимо bpftrace одноразово на невеликий інтервал
TMP=$(mktemp)
sudo bpftrace -e 'tracepoint:tcp:tcp_retransmit_skb { @retrans = count(); } interval:s:10 { print(@retrans); exit(); }' > "$TMP" 2>/dev/null || true
# Очікуваний формат виводу: @retrans: N
VAL=$(grep -Eo "[0-9]+$" "$TMP" || echo 0)
rm -f "$TMP"
# Прометеєвий метрик
{
  echo "# HELP ebpf_tcp_retransmits_total Total TCP retransmissions observed by eBPF"
  echo "# TYPE ebpf_tcp_retransmits_total counter"
  echo "ebpf_tcp_retransmits_total ${VAL}"
} > "$OUT"
EOF
chmod +x ~/ebpf_tcp_retrans_exporter.sh

Тепер можна запускати скрипт кожні, скажімо, 30 секунд через systemd timer (замість cron — так зручніше керувати логами):

sudo bash -c 'cat > /etc/systemd/system/ebpf-tcp-retrans.service <<"UNIT"
[Unit]
Description=eBPF TCP Retrans Exporter (bpftrace)

[Service]
Type=oneshot
ExecStart=/bin/bash -lc "/home/${SUDO_USER}/ebpf_tcp_retrans_exporter.sh"
User=%i
Group=%i
UNIT'

sudo bash -c 'cat > /etc/systemd/system/ebpf-tcp-retrans@.timer <<"TIMER"
[Unit]
Description=Run eBPF TCP Retrans Exporter periodically

[Timer]
OnBootSec=30
OnUnitActiveSec=30
Unit=ebpf-tcp-retrans.service

[Install]
WantedBy=timers.target
TIMER'

# Запуск для поточного користувача
ME=$(whoami)
sudo systemctl daemon-reload
sudo systemctl enable --now ebpf-tcp-retrans@${ME}.timer

У Prometheus додайте job, який скрейпить ваш node_exporter. Метрика з'явиться як ebpf_tcp_retransmits_total. У Grafana додайте панель з запитом rate(ebpf_tcp_retransmits_total[5m]).

Просунуто: Cloudflare ebpf_exporter

Якщо хочете нативний експортер eBPF з розширеною конфігурацією — погляньте на ebpf_exporter (Cloudflare). Його можна запустити у контейнері або зібрати з Go. Він експортує метрики у форматі Prometheus й має приклади профілів для мережі/сокетів.

FAQ

Пише "permission denied" або "Operation not permitted"?

Для більшості eBPF-трас потрібні root-права. Запускайте команди з sudo. У середовищах із SELinux/AppArmor можуть знадобитися додаткові дозволи. У контейнері потрібні привілеї (--privileged) і змонтований /sys та /sys/fs/bpf.

Немає BTF: "/sys/kernel/btf/vmlinux: No such file"

Встановіть заголовки ядра. Наприклад, на Ubuntu: sudo apt install linux-headers-$(uname -r). На деяких ядрах BTF входить до пакета linux-image-*-dbgsym або постачається окремим файлом vmlinux. Також переконайтеся, що ввімкнені опції ядра CONFIG_DEBUG_INFO_BTF.

bpftrace: "failed to initialize maps" чи проблеми з tracefs

Увімкніть tracefs/debugfs: sudo mount -t tracefs nodev /sys/kernel/tracing та sudo mount -t debugfs nodev /sys/kernel/debug. Переконайтеся, що файлові системи монтуються автоматично через fstab у серверах.

Чи не занадто eBPF навантажує систему?

Правильно написані програми eBPF мають дуже низький overhead. Але все одно тестуйте у стейджингу, вимірюйте impact, уникайте надмірних printf та великих гістрограм у проді.

Старе ядро (4.x) — що втратимо?

Можуть бути обмеження в tracepoints/kprobes, відсутність BTF, складніше писати програми. Рекомендую оновити ядро для стабільної роботи eBPF (якщо політики дозволяють).

Порада від Kernelka

Тримайте ваші bash скрипти короткими й без зайвих циклів у просторі користувача: хай важку частину рахує сама eBPF-програма, а ви лише збирайте агрегати періодично. Використовуйте інтервали (interval:s:N) і clear(@), щоб не роздувати карти в пам'яті. І завжди документуйте, що саме ви міряєте — це рятує нерви під час інцидентів 🙂

Підсумок

  • Встановили bpftrace і bpftool та перевірили можливості ядра.
  • Запустили корисні one-liners для файлів, системних викликів і мережевих ретрансмітів.
  • Зібрали метрики в Prometheus через textfile collector і підключили Grafana.
  • Знаємо, куди дивитися для просунутої інтеграції (ebpf_exporter) та як вирішувати типові помилки.