eBPF: революция в наблюдаемости Linux

Рейтинг: 71.7% · 16 голосов
Подробный курс по диагностике и производительности Linux для админов и DevOps: с чего начать, методология USE, логи (journalctl, dmesg), процессы, CPU, память и OOM, диск и IO (iostat), сеть (ss, tcpdump), системные вызовы и strace, ltrace, perf, флеймграфы, ftrace, eBPF и bpftrace, lsof, мониторинг. Разбор каждого инструмента с чтением вывода.
Ответить
Аватара пользователя
Dmitry_SRE
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

eBPF: революция в наблюдаемости Linux

Сообщение Dmitry_SRE »

Оглавление курса (47)
  1. С чего начать диагностику Linux: методология вместо паники
  2. Первые 60 секунд: экспресс-диагностика нагруженного сервера
  3. Методологии диагностики: USE, RED и здравый смысл
  4. Логи systemd через journalctl: где искать причину
  5. Где лежат логи Linux: /var/log, dmesg и rsyslog
  6. Источники правды: load average, /proc и /sys
  7. Процессы Linux: ps, pstree и состояния процессов
  8. Интерактивный мониторинг: top и htop
  9. Метрики процессов во времени: pidstat
  10. Приоритеты и ограничения: nice, ionice, cgroups
  11. Сигналы и зависшие процессы: kill, и что делать с D-state
  12. Загрузка CPU: user, system, iowait, steal и контекст-свитчи
  13. Диагностика CPU по ядрам: vmstat и mpstat
  14. Профилирование CPU: perf top и поиск пожирателя
  15. Частоты, троттлинг и NUMA: turbostat и numastat
  16. Память Linux: RSS, VSZ, page cache и миф о нехватке памяти
  17. Сколько памяти занято: free, /proc/meminfo и vmstat
  18. Поиск утечек и пожирателей памяти: smem, pmap, smaps
  19. Swap и подкачка: swapon, swappiness, когда своп - это боль
  20. OOM killer: кто и за что убил процесс
  21. Память ядра и slab: slabtop и куда уходит RAM
  22. Подсистема ввода-вывода: путь запроса от приложения до диска
  23. Диагностика диска: iostat и чтение await, %util
  24. Кто грузит диск: iotop и атрибуция io процессам
  25. Файловые системы: df, du, иноды и куда делось место
  26. Глубокая диагностика блочного слоя: blktrace и biolatency
  27. Кеш страниц и грязные данные: dirty pages, fsync, drop_caches
  28. Сетевой стек Linux: путь пакета и где возникают задержки
  29. Сокеты и соединения: ss и netstat
  30. Захват трафика: tcpdump для диагностики сети
  31. Задержки и потери в сети: ping, mtr, диагностика латентности
  32. Сеть как источник проблем: nftables, conntrack, дропы
  33. Что такое системный вызов и зачем его трассировать
  34. strace: трассировка системных вызовов на практике
  35. strace в бою: почему программа висит, падает или тормозит
  36. ltrace: трассировка вызовов библиотек
  37. Накладные расходы трассировки и безопасные альтернативы
  38. perf: универсальный профайлер Linux
  39. Флеймграфы: визуализация профиля производительности
  40. Трассировка ядра: ftrace и trace-cmd
  41. eBPF: революция в наблюдаемости Linux (вы здесь)
  42. Инструменты eBPF на практике: BCC и bpftrace
  43. lsof: открытые файлы, дескрипторы, кто держит файл и порт
  44. Разбор кейса: приложение тормозит - пошаговая диагностика
  45. Непрерывный мониторинг: sar, node_exporter, Grafana, Zabbix
  46. Диагностика в контейнерах: cgroups, лимиты, Docker и Kubernetes
  47. Карта инструментов и сквозной разбор инцидента производительности
Представь ситуацию. На проде дёргается latency, графики мигают красным, а ты понятия не имеешь, что именно тормозит. strace вешает процесс. tcpdump топит тебя в гигабайтах пакетов. логи врут или их просто нет. Хочется задать ядру конкретный вопрос - "покажи мне все open() с задержкой больше 10 мс по этому сервису" - и получить готовую табличку, а не сырой поток, который надо ещё час разбирать. Вот ровно эту боль и решает eBPF. Это технология, которая превратила Linux в систему, где ты можешь спрашивать почти что угодно прямо у ядра, в реальном времени, на живом сервере, не пересобирая ядро и почти не нагружая машину.

В этом уроке разберёмся, что такое eBPF на пальцах, почему это считают прорывом, и подойдём вплотную к инструментам bcc и bpftrace, которыми ты будешь пользоваться руками уже в следующих уроках. Актуально на 2026 год: eBPF давно перестал быть экзотикой и стал стандартным слоем диагностики в Linux.

Что такое eBPF и почему это прорыв

Если совсем коротко: eBPF (extended Berkeley Packet Filter) - это способ запускать твои маленькие программы внутри ядра в ответ на события. Произошёл системный вызов, прилетел сетевой пакет, ядро зашло в свою функцию - и в этот момент срабатывает твой кусочек кода. Он что-то считает, фильтрует, агрегирует и отдаёт результат наружу. Название историческое: когда-то "BPF" был крошечным фильтром пакетов для tcpdump, но "extended"-версия разрослась далеко за пределы сети.

Аналогия. Раньше, чтобы понять, что творится в ядре, у тебя было два пути. Либо лезть с инструментом снаружи (strace, tcpdump) - это как стоять у двери магазина и записывать каждого входящего, чтобы потом руками посчитать выручку. Дорого, медленно, мешает работе. Либо патчить само ядро и пересобирать - это как ломать стену магазина, чтобы поставить камеру. Опасно и долго.

eBPF - это третий путь. Ядро само пускает внутрь маленького доверенного "наблюдателя", который сидит прямо на кассе и сразу говорит тебе итоговую цифру. Никаких стен ломать не надо, наблюдатель проверен на безопасность, и работает он почти бесплатно по нагрузке.

Ключевое отличие ebpf трассировки от старого strace вот в чём. strace ловит каждый syscall через ptrace и гонит сырой поток в userspace, дважды переключая контекст на каждый вызов - на нагруженном процессе это замедление в разы, иногда в десятки раз. А eBPF-программа считает прямо в ядре: тебе наружу падает уже готовая статистика - гистограмма задержек, счётчик по процессам, топ функций. Данные не покидают ядро без нужды, и overhead падает на порядки. Именно поэтому eBPF не боятся запускать на боевом трафике, а strace на проде - почти всегда плохая идея.

Изображение

Как это устроено: события, верификатор, карты

Чтобы bpf в linux не превратился в дыру размером с ядро, придумали жёсткую механику. Разберём по частям.

События (хуки) - к чему цепляется программа. eBPF-программу можно повесить на разные точки:
  • kprobe / kretprobe - вход и выход почти любой функции ядра. Динамически, без перекомпиляции. Хочешь знать, кто вызывает vfs_read - вешаешь kprobe.
  • uprobe / uretprobe - то же самое, но для функций в пользовательских программах и библиотеках (например, поймать вызов в libc, в OpenSSL или в твоём бинарнике).
  • tracepoint - заранее размеченные ядром стабильные точки (syscalls, планировщик, блочный слой). Надёжнее kprobe, потому что не зависят от имён внутренних функций между версиями ядра.
  • fentry / fexit - современная замена kprobe (с ядра 5.5), быстрее и с типизированным доступом к аргументам через BTF. На 2026 для трассировки функций ядра это предпочтительный механизм там, где он доступен.
  • perf events - аппаратные и софтверные счётчики, сэмплирование по таймеру (основа для профилирования и флеймграфов).
  • USDT - статические точки трассировки внутри приложений (есть в JVM, в libc, в PostgreSQL и т.д.).
  • XDP / TC - сетевые хуки на самом раннем этапе обработки пакета. На этом строят фильтрацию, балансировку, защиту от DDoS.
Верификатор - почему это безопасно. Это сердце всей идеи. Прежде чем твою программу загрузят в ядро, её проверяет верификатор - встроенный статический анализатор. Он гарантирует, что программа завершается (никаких бесконечных циклов - раньше циклы были вообще запрещены, с ядра 5.3 разрешены ограниченные, а с 5.17 есть удобный bpf_loop), не разыменовывает нулевые и чужие указатели, не лезет в произвольную память ядра и не уронит систему. Не прошла проверку - просто не загрузится, программа даже не начнёт исполняться. Поэтому eBPF можно сравнительно безопасно гонять на проде: ядро тебе физически не даст выстрелить себе в ногу. Оговорка: верификатор - не панацея, в истории были CVE с обходом проверок (например, privilege escalation в bpf), поэтому на боевых хостах unprivileged-eBPF обычно выключают, а доступ дают только через sudo.

Карты (maps) - как данные попадают наружу. eBPF-программа сама по себе не печатает текст. Она складывает результаты в специальные структуры - eBPF maps (хеш-таблицы, массивы, кольцевые буферы). А userspace-утилита читает их и рисует тебе человеческий вывод. Именно так считалка живёт в ядре, а ты видишь готовую гистограмму. Современный канал передачи событий наружу - BPF ring buffer (с ядра 5.8), он эффективнее и проще старых per-CPU perf-буферов.

JIT. Загруженный байткод ядро компилирует JIT-ом в нативные инструкции процессора, поэтому он бежит на скорости обычного кода ядра, а не интерпретируется.

Экосистема: bpftrace, bcc, libbpf - чем работать руками

Голый eBPF-байткод руками никто не пишет. Есть удобные обёртки.

bpftrace - язык одной строкой, вдохновлённый awk и DTrace. Идеален для быстрых разовых вопросов "а что сейчас происходит". На 2026 актуальны версии ветки 0.2x. Сначала посмотри своё "меню" событий:

Код: Выделить всё

sudo bpftrace -l 'tracepoint:syscalls:*' | head
# выведет список доступных tracepoint-ов - это твоё "меню" событий
Классический пример - посчитать, сколько системных вызовов делает каждый процесс:

Код: Выделить всё

sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count() }'
Как читать. Жмёшь Ctrl-C, чтобы остановить, и видишь:

Код: Выделить всё

@[systemd]: 412
@[sshd]: 1530
@[nginx]: 88204
Слева - имя процесса (встроенная переменная comm), справа - число syscall-ов за время наблюдения. Если один процесс вылетел на порядки вперёд (тут nginx с 88 тысячами) - вот твой кандидат на разбор. @ - это и есть та самая map в ядре, count() инкрементит счётчик по ключу comm. Сырьё наружу не льётся, агрегация идёт в ядре.

Гистограмма задержки чтения по процессам:

Код: Выделить всё

sudo bpftrace -e 'tracepoint:syscalls:sys_exit_read { @[comm] = hist(args.ret) }'
hist() строит степенную (log2) гистограмму, args.ret - возвращаемое значение read() (число прочитанных байт). Обрати внимание: в современном bpftrace доступ к полям tracepoint - через args.имя (точка), старый синтаксис args->имя уже не нужен. Узнать список полей конкретной точки можно так:

Код: Выделить всё

sudo bpftrace -lv tracepoint:syscalls:sys_enter_openat
А чтобы из указателя получить строку (например, имя файла), оборачивай его в str():

Код: Выделить всё

sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat { printf("%-16s %s\n", comm, str(args.filename)) }'
bcc (BPF Compiler Collection) - набор готовых питоновских инструментов плюс библиотека. Это твой "ящик с отвёртками" на каждый день. В Ubuntu/Debian пакет ставится как:

Код: Выделить всё

sudo apt install bpfcc-tools
# на RHEL/Fedora: sudo dnf install bcc-tools
Инструменты в Debian/Ubuntu обычно с суффиксом -bpfcc (например, execsnoop-bpfcc). Важное обновление на 2026: классические Python-инструменты bcc тяжёлые (тянут LLVM/Clang и компилируют C прямо на хосте при запуске). Поэтому проект переписывает их на libbpf-tools - это те же утилиты (execsnoop, opensnoop, biolatency, runqlat...), но скомпилированные заранее в один маленький бинарник на базе CO-RE, без зависимости от компилятора и kernel headers на целевой машине. Если выбираешь, что ставить на сервер, - libbpf-tools предпочтительнее. Самые ходовые инструменты:
  • execsnoop - показывает каждый новый процесс (вызов exec). Ловит "кто это запустил странный скрипт".
  • opensnoop - какие файлы кто открывает прямо сейчас.
  • biolatency - гистограмма задержек блочного ввода-вывода (диск тормозит или нет).
  • tcpconnect / tcpaccept / tcplife - кто куда коннектится, кто к тебе, и сколько живут соединения.
  • runqlat - задержка в очереди планировщика (процессы голодают по CPU?).
  • profile - сэмплирующий профайлер стеков, основа для флеймграфов.
Пример вывода execsnoop-bpfcc:

Код: Выделить всё

PCOMM            PID    PPID   RET ARGS
bash             8112   8110     0 /usr/bin/ls --color=auto
curl             8120   8112     0 /usr/bin/curl http://example.com
По колонкам: PCOMM - имя процесса, PID - его номер, PPID - кто родитель (важно для "откуда ноги растут"), RET - код возврата exec (0 = успех, отрицательное = ошибка, например файла нет), ARGS - команда с аргументами. Видишь подозрительный curl, у которого PPID ведёт к php-fpm или nginx, - есть повод копать в сторону взлома: веб-сервер обычно не должен порождать произвольные команды.

libbpf + CO-RE - это "взрослый" способ писать переносимые eBPF-программы на C, которые компилируются один раз и работают на разных ядрах (Compile Once - Run Everywhere) за счёт BTF (формата типов ядра). Это уже для разработки своих инструментов и продуктов наблюдаемости. На 2026 именно libbpf+CO-RE - индустриальный стандарт: на нём построены и libbpf-tools, и большинство коммерческих eBPF-агентов.

Требования к ядру и где это применяют

eBPF появился в ядре 4.x, но для нормальной жизни с bcc/bpftrace ориентируйся на ядро 5.x, а лучше 5.15 LTS и новее. На 2026 в свежих дистрибутивах уже встречаются 6.x вплоть до 6.12 LTS - там eBPF в полном расцвете. Ключевые вехи: BTF - с 5.2, ограниченные циклы - с 5.3, fentry/fexit - с 5.5, кольцевой буфер (ring buffer) - с 5.8, kfuncs - с 5.13. Проверить версию и наличие BTF:

Код: Выделить всё

uname -r
# есть ли BTF (нужен для CO-RE-инструментов):
ls /sys/kernel/btf/vmlinux && echo "BTF есть"
Если файл есть - современные libbpf-инструменты заведутся без kernel headers, прямо из коробки. Удобный способ заранее понять, что поддерживает твоё ядро:

Код: Выделить всё

sudo bpftool feature probe | head -n 30
В Astra Linux и RED OS актуальных версий ядра свежие, eBPF, bcc и bpftrace там работают; на совсем старых корпоративных ядрах (3.x/ранние 4.x) часть инструментов не поднимется - тогда смотри на версию и наличие BTF.

Где eBPF используют в реальном мире, помимо трассировки: сеть (XDP - сверхбыстрая фильтрация пакетов, основа Cilium для Kubernetes и kube-proxy без iptables), безопасность (детект подозрительных syscall-ов в рантайме - Falco, Tetragon), профилирование (непрерывный сбор стеков, continuous profiling - Parca, Pyroscope), наблюдаемость без инструментирования кода (Pixie, Coroot). Одна технология - сразу несколько огромных областей.

Типичные грабли и заблуждения
  • "eBPF заменяет strace/tcpdump полностью". Нет. Для разового "что вызывает программа один раз" strace проще и нагляднее. eBPF выигрывает на нагрузке и на агрегации, а не везде подряд. Хотя для долгих наблюдений на проде - почти всегда eBPF.
  • "Можно запускать без root". В общем случае - нет. Загрузка большинства программ требует CAP_BPF (плюс часто CAP_PERFMON / CAP_NET_ADMIN под задачу) или CAP_SYS_ADMIN, поэтому на практике sudo. Unprivileged-режим (sysctl kernel.unprivileged_bpf_disabled) на современных дистрибутивах по умолчанию выключен из соображений безопасности - и обратно его в работающем ядре уже не включить.
  • "kprobe на любую функцию вечны". Имена внутренних функций ядра меняются между версиями, а часть функций инлайнится и пропадает. Скрипт на kprobe:vfs_read может сломаться после апдейта. Где есть tracepoint - бери tracepoint, они стабильны как ABI.
  • "Verifier отклонил - это баг ядра". Чаще это ты пытаешься сделать что-то небезопасное (цикл без видимой границы, доступ к полю без проверки на NULL, слишком большой стек). Читай его сообщение целиком - он подсказывает инструкцию и причину.
  • "Overhead нулевой". Почти нулевой, но не магия. Повесь kprobe на горячую функцию, которая зовётся миллионы раз в секунду, - почувствуешь. Сначала меряй на узких событиях и по возможности фильтруй прямо в обработчике.
Мини-лаба: попробуй прямо сейчас

Нужна машина с современным ядром (5.15+) и sudo. По шагам:
  • Поставь инструменты:

    Код: Выделить всё

    sudo apt install bpfcc-tools bpftrace
    (или dnf-аналог).
  • Проверь версию ядра и BTF:

    Код: Выделить всё

    uname -r; ls /sys/kernel/btf/vmlinux
  • Запусти в одном терминале

    Код: Выделить всё

    sudo execsnoop-bpfcc
    , а в другом выполни любую команду (ls, curl). Найди свою команду в выводе, сопоставь PID и PPID.
  • Посчитай syscall-ы по процессам:

    Код: Выделить всё

    sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count() }'
    - дай поработать пару секунд, Ctrl-C, найди самый "болтливый" процесс.
  • Отфильтруй по одному процессу (отвечаем на вопрос из комментариев):

    Код: Выделить всё

    sudo bpftrace -e 'tracepoint:raw_syscalls:sys_enter /comm == "nginx"/ { @[probe] = count() }'
    - выражение в /.../ это фильтр-предикат, считаем только для nginx.
  • Посмотри список доступных событий:

    Код: Выделить всё

    sudo bpftrace -l | wc -l
    - удивись, сколько точек наблюдения у тебя под рукой.
Контрольные вопросы
  • Чем принципиально отличается сбор данных eBPF от strace - почему overhead ниже?
  • Зачем нужен верификатор и что он гарантирует перед загрузкой программы?
  • В чём разница между kprobe и tracepoint, и почему для стабильных скриптов предпочитают tracepoint (и чем тут помогает fentry)?
  • Какая роль у eBPF maps и ring buffer - как результат из ядра попадает к тебе на экран?
Что запомнить
eBPF - это программируемая наблюдаемость: твой безопасный код бежит в ядре в ответ на события, считает и фильтрует на месте и отдаёт наружу готовую статистику, а не сырой поток. Безопасность обеспечивает верификатор, скорость - JIT, данные ходят через maps и ring buffer. На практике ты работаешь не с байткодом, а с bpftrace (быстрые однострочники) и bcc/libbpf-tools (готовые инструменты вроде execsnoop, opensnoop, biolatency, runqlat). Нужно ядро 5.15+ с BTF, доступ - через sudo. Это не просто ещё одна утилита - это фундамент, на котором на 2026 год держатся и трассировка, и сетевой стек, и безопасность Linux.
👍2 ❤️2 🔥 😄 🤔
Аватара пользователя
dimon5
Сообщения: 1
Зарегистрирован: 24 май 2026, 03:01

Re: eBPF: революция в наблюдаемости Linux

Сообщение dimon5 »

Спасибо, наконец дошло чем eBPF отличается от strace - до этого думал что это просто более модный strace. Аналогия с наблюдателем на кассе прямо в голове щёлкнула. И отдельный плюс за пояснение про libbpf-tools, а то я ставил тяжёлый bcc и не понимал зачем он тянет clang.
👍2 ❤️ 🔥 😄 🤔
Аватара пользователя
Mwsmith
Сообщения: 1
Зарегистрирован: 25 май 2026, 03:13

Re: eBPF: революция в наблюдаемости Linux

Сообщение Mwsmith »

Запустил execsnoop-bpfcc на проде, поймал левый bash скрипт с PPID от php-fpm. Похоже у нас правда дыра. Спасибо за однострочник с фильтром /comm == "nginx"/ - то что искал, теперь не ловлю всё подряд.
👍 ❤️1 🔥 😄 🤔2
Ответить
← Предыдущая глава
Трассировка ядра: ftrace и trace-cmd
Следующая глава →
Инструменты eBPF на практике: BCC и bpftrace

Все главы курса «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Поделиться темой: ✈ Telegram VK
Похожие запросы: как посмотреть сколько памяти занято в linuxlsof кто держит файл и порт в linuxperf top как найти что грузит процессорhtop и top как читать и в чем разницаoom killer кто убил процесс linux как узнатькак смотреть логи в linux и где они лежат

Вернуться в «Диагностика и производительность Linux: логи, strace, perf и eBPF»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость