r3tam blog

eBPF: новая эра наблюдаемости, безопасности и производительности в Linux

eBPF: новая эра наблюдаемости, безопасности и производительности в Linux

Введение

Долгое время ядро Linux оставалось «чёрным ящиком» для разработчиков и инженеров. Чтобы заглянуть внутрь, приходилось либо писать модули ядра с риском обрушить всю систему, либо довольствоваться грубыми инструментами вроде strace и tcpdump, которые давали срез, но не полную картину. Расширение возможностей всегда было сопряжено с опасностью: один неверный указатель в модуле ядра — и сервер уходит в kernel panic.

Технология eBPF (extended Berkeley Packet Filter) навсегда изменила это положение. Она позволяет безопасно выполнять пользовательский код прямо в ядре Linux — без перезагрузки, без компиляции модулей и без риска обрушить систему. За десять лет eBPF прошёл путь от нишевого механизма фильтрации пакетов до фундаментальной инфраструктурной технологии, на которой строятся современные системы наблюдаемости, сетевого взаимодействия и безопасности.

В этой статье мы разберёмся, как устроен eBPF, какие задачи он решает лучше всего, и почему к 2026 году он стал обязательным элементом стека любого platform-инженера. Вы узнаете о реальных кейсах внедрения от GitHub, Datadog и Alibaba Cloud, а также познакомитесь с экосистемой проектов, которые уже сегодня работают на eBPF.

Что такое eBPF и как он устроен

От BPF к eBPF: история эволюции

В 1992 году Стив Маккейн и Ван Якобсон представили Berkeley Packet Filter — технологию для фильтрации сетевых пакетов в ядре. Именно на ней работал легендарный tcpdump. Классический BPF (cBPF) был простым виртуальным движком с минимальным набором инструкций, достаточным для того, чтобы отбросить ненужные пакеты ещё до того, как они попадут в пользовательское пространство.

В 2014 году Алексей Старовойтов из Red Hat представил расширенную версию — eBPF. Она не просто увеличила разрядность регистров с 32 до 64 бит, а принципиально изменила подход: eBPF стал полноценной виртуальной машиной внутри ядра, способной выполнять произвольные программы в ответ на любые события. В 2015 году eBPF был включён в основное ядро Linux начиная с версии 4.8, и с тех пор его возможности только расширяются.

«eBPF — это виртуальная машина внутри ядра Linux, которая запускает небольшие изолированные программы в ответ на события. Событиями могут быть сетевые пакеты, системные вызовы, вызовы функций ядра и даже вызовы функций пользовательского пространства через uprobes.» — James M., The eBPF Revolution

Архитектура eBPF

Программа eBPF проходит пять этапов, прежде чем оказаться исполняемой в ядре:

  1. Написание кода — программа пишется на ограниченном подмножестве C (или Rust) и компилируется в байт-код с помощью clang -target bpf.
  2. Загрузка — байт-код загружается в ядро через системный вызов bpf().
  3. Верификация — встроенный верификатор ядра символически исполняет программу, проверяя все возможные пути выполнения. Он убеждается, что программа не содержит бесконечных циклов, не разыменовывает некорректные указатели и всегда завершается.
  4. JIT-компиляция — если верификация пройдена, байт-код компилируется в нативные инструкции целевого процессора.
  5. Привязка к hook'у — программа прикрепляется к одному из множества доступных hook'ов: kprobe, tracepoint, XDP, cgroup и другим.

Этот процесс гарантирует, что eBPF-программа не может навредить системе. В отличие от традиционных модулей ядра (LKM), где любая ошибка может привести к kernel panic, eBPF-программы работают в изолированной песочнице. Как образно выражаются разработчики, «eBPF даёт пользовательский контроль с видимостью уровня ядра и нулевым риском».

Механизмы взаимодействия: maps и helpers

Программы eBPF не могут вызывать произвольные функции ядра. Для коммуникации с внешним миром используются два механизма:

Helper-функции — фиксированный набор API, предоставляемых ядром: получение текущего времени, манипуляция сетевыми пакетами, работа с картами и так далее. Каждый тип программы eBPF имеет свой набор доступных helpers.

eBPF Maps — структуры данных «ключ — значение», которые служат мостом между ядром и пользовательским пространством. Map может быть хеш-таблицей, массивом, кольцевым буфером (ring buffer) или программным массивом (для tail calls). Через maps программы eBPF обмениваются данными с пользовательскими процессами в реальном времени.

В современных ядрах (5.8+) появился BPF_MAP_TYPE_RINGBUF — кольцевой буфер, спроектированный специально для высокопроизводительной передачи данных из eBPF-программ в пользовательское пространство. Он заменил устаревший perf-буфер и стал стандартом для новых инструментов.

CO-RE: главное новшество для продакшена

Долгое время главной болью eBPF была зависимость от версии ядра: программу приходилось компилировать под каждую конкретную сборку. CO-RE (Compile Once, Run Everywhere) решила эту проблему. Программа компилируется один раз, а BTF (BPF Type Format) позволяет ядру адаптировать её под свою версию во время загрузки. Благодаря CO-RE современные eBPF-инструменты работают на ядрах от 5.4 и выше без перекомпиляции.

Три кита eBPF: наблюдаемость, сети и безопасность

Наблюдаемость без инструментирования

Главное достижение eBPF в области наблюдаемости — возможность видеть, что на самом деле делает приложение, не требуя изменений в его коде. Традиционный подход требовал добавления SDK, экспорта метрик и трассировок — всё это увеличивало сложность и потребление ресурсов. С eBPF достаточно установить инструмент на узел, и он начнёт собирать данные на уровне ядра.

Возможности eBPF для наблюдаемости включают:

  • Трассировку всех системных вызовов процесса в реальном времени.
  • Захват сетевых пакетов на любом уровне — от драйвера NIC (XDP) до сокета.
  • Профилирование CPU и памяти непрерывно, с минимальным оверхедом.
  • Отслеживание операций ввода-вывода, включая файловые операции и обращения к диску.

Ключевое преимущество — полнота данных. Традиционные мониторинговые системы работают на сэмплах и агрегированных метриках. eBPF же даёт «сырую» картину каждого события, что принципиально меняет качество диагностики. Инструменты вроде Pixie могут показывать HTTP-трейсы, запросы к базам данных и использование CPU на уровне функций — и всё это без единой строчки instrumentation-кода.

Сетевое взаимодействие нового поколения

Сетевая подсистема Linux десятилетиями строилась на iptables и сложных цепочках правил. С появлением контейнеров и Kubernetes этот подход начал давать сбои: IP-адреса меняются каждую секунду, а таблицы с сотнями тысяч правил становятся узким местом производительности.

eBPF решает эту проблему кардинально — код обработки пакетов выполняется прямо в ядре, а в случае XDP (eXpress Data Path) — ещё до того, как пакет попадёт в сетевой стек. Это даёт субмикросекундную задержку обработки и полный контроль над сетевыми потоками.

На базе eBPF построен Cilium — де-факто стандарт сетевого взаимодействия в Kubernetes. Cilium полностью заменяет kube-proxy, реализует балансировку нагрузки, сетевые политики и service mesh на уровне ядра. Идентификация трафика происходит по identity сервиса, а не по IP-адресу, что критически важно в динамических средах.

Безопасность на уровне ядра

eBPF позволяет детектировать угрозы там, где они действительно возникают, — на уровне ядра. Традиционные агенты безопасности работают в пользовательском пространстве и видят только то, что им позволяет увидеть система. eBPF же перехватывает каждый системный вызов, каждую попытку открыть файл, каждый запуск процесса.

Проекты вроде Falco и Tetragon используют eBPF для runtime-безопасности: они отслеживают нештатные системные вызовы, подозрительное поведение процессов и попытки эскалации привилегий. Tetragon пошёл ещё дальше — он не только наблюдает, но и может принудительно блокировать действия: убить процесс, который вызывает shell из контейнера, или заблокировать опасный системный вызов.

Возможность не только наблюдать, но и активно вмешиваться — ключевое отличие Tetragon от конкурентов. Большинство инструментов безопасности на eBPF ограничиваются отправкой событий в SIEM-системы. Tetragon может действовать самостоятельно, что делает его незаменимым для zero-trust архитектур.

eBPF в продакшене: пять реальных кейсов

GitHub: защита деплоя от циклических зависимостей

Инженеры GitHub столкнулись с классической проблемой: как протестировать деплой без доступа к github.com на самих серверах, которые одновременно обслуживают продакшен-трафик? Просто заблокировать домен нельзя — серверы stateful и требуют доступ к репозиториям для обслуживания запросов.

GitHub использовал eBPF для создания изолированной сети для каждого скрипта деплоя. Техническое решение оказалось элегантным:

  1. Скрипт деплоя помещается в отдельную контрольную группу (cgroup).
  2. eBPF-программа типа BPF_PROG_TYPE_CGROUP_SKB перехватывает весь исходящий трафик из этой cgroup.
  3. DNS-запросы перенаправляются в пользовательский DNS-proxy, который сверяется с блок-листом.
  4. BPF_PROG_TYPE_CGROUP_SOCK_ADDR подменяет адрес назначения в сокетах, блокируя нежелательные соединения.

Результат — полная прозрачность и контроль над каждым соединением, которое устанавливает скрипт деплоя, без какого-либо влияния на продакшен-трафик. Система работает с 2026 года, и за это время GitHub получил не только защиту от циклических зависимостей, но и аудит всех внешних соединений в процессе деплоя.

Datadog: фильтрация миллиардов событий в минуту

Datadog построил на eBPF систему мониторинга целостности файлов (FIM), способную обрабатывать более 10 миллиардов событий в минуту. Каждая операция с файлом — будь то чтение, запись или изменение прав доступа — перехватывается eBPF-программой на уровне ядра.

Главная проблема, с которой столкнулась команда, — объём данных. Сериализованное событие занимает около 5 Кбайт, а при потоке в 10 миллиардов событий в минуту это даёт терабайты данных в секунду. Решение оказалось в переносе логики фильтрации прямо в eBPF-программы.

Datadog разработал двухуровневую систему фильтрации:

  • Approvers — разрешённые паттерны (например, изменения в /etc/passwd), которые однозначно интересны для безопасности.
  • Discarders — заведомо нерелевантные пути (например, /tmp), которые можно сразу отбросить.

Фильтрация в ядре позволила сократить объём событий для пользовательского агента на 94%. Вместо 10 миллиардов событий в минуту агент обрабатывает около миллиона — и не теряет ни одного релевантного события.

Alibaba Cloud: десять миллионов запросов в секунду

Команда Alibaba Cloud столкнулась с проблемой масштабирования L7-балансировщиков нагрузки. При более чем 10 миллионах запросов в секунду традиционные механизмы уведомления о событиях ввода-вывода (epoll) становились узким местом.

Инженеры Alibaba создали Hermes — фреймворк, использующий eBPF для интеллектуального распределения соединений. Воркер-процессы публикуют свои метрики (загрузку, количество активных соединений) в eBPF-карты, а программа в ядре динамически выбирает наиболее подходящий воркер для каждого нового соединения.

Результаты впечатляют: снижение стоимости инфраструктуры на 19%, сокращение зависаний воркеров на 99,8%, устойчивая работа на 100 000 ядрах CPU без единого инцидента за два года.

Speedscale: прощай, sidecar

Speedscale — платформа для записи и воспроизведения трафика — изначально использовала sidecar-контейнеры для перехвата трафика. Каждый новый pod означал новый sidecar с собственными накладными расходами на CPU и память.

Переход на eBPF изменил архитектуру кардинально: одна eBPF-программа на узел перехватывает трафик всех pod'ов. При 1 000 pod'ов вместо 1 000 sidecar'ов нужно всего 10–20 eBPF-программ. Speedscale измеряет снижение потребления CPU на 30–50%, памяти — на 60–80%, а p99 задержки уменьшилась на 2–5 мс за счёт исчезновения лишнего прокси-хопа.

Этот кейс особенно показателен: sidecar'ы долгое время считались необходимым злом service mesh, но eBPF предлагает альтернативу, которая просто работает эффективнее.

ClickPost: профилирование без боли

Команда ClickPost искала способ понять, почему их Python-сервисы потребляют всё больше ресурсов по мере масштабирования. С помощью eBPF они построили систему профилирования потоков, которая измеряла шесть ключевых метрик: задержку запросов, глубину очереди, утилизацию потоков, время ожидания блокировок, I/O-wait и общее количество запросов.

Результаты оказались неожиданными: некоторые потоки тратили до 40% времени на ожидание блокировок (lock contention), а высокая утилизация CPU часто маскировала проблемы с I/O. Оптимизация на основе этих данных дала снижение времени ответа на 35%, сокращение количества запросов в очередях на 50% и уменьшение расходов на инфраструктуру на 20%.

Экосистема eBPF в 2026 году

Сообщество eBPF породило множество зрелых проектов, каждый из которых закрывает свою нишу. Вот ключевые инструменты, которые должен знать platform-инженер:

  • Cilium — де-факто стандарт сетевого взаимодействия в Kubernetes. Заменяет kube-proxy, реализует CNI, сетевые политики L3–L7, service mesh и наблюдаемость через Hubble. Работает исключительно на eBPF.
  • Tetragon — runtime-безопасность на eBPF. Наблюдает и принудительно блокирует подозрительное поведение на уровне ядра: процессы, системные вызовы, сетевые соединения.
  • Pixie — мгновенная наблюдаемость для Kubernetes без инструментирования. Показывает HTTP-трейсы, запросы к базам данных, профили CPU на уровне функций сразу после установки.
  • Parca и Pyroscope — непрерывное профилирование CPU и памяти на всём флоте с минимальным оверхедом.
  • Falco — runtime-безопасность для соответствия стандартам и аудита. Мигрировал на eBPF как основной источник данных.
  • bpftrace — швейцарский нож для трассировки в стиле awk. Позволяет писать однострочники для отладки ядра.
  • Coroot — интегрированная наблюдаемость с корневым анализом причин на eBPF.

По данным отчёта eBPF Foundation, 86% респондентов уже используют eBPF в продакшене. Основные драйверы внедрения — наблюдаемость (72%), сети (65%) и безопасность (48%).

Ограничения и сложности

Как и любая мощная технология, eBPF не лишён ограничений. Вот что важно учитывать:

Зависимость от версии ядра. Новые возможности eBPF появляются с каждым релизом ядра, и для продвинутых сценариев (например, кольцевые буферы или новые типы программ) требуется ядро не ниже 5.8. CO-RE смягчил, но не устранил эту проблему полностью.

Модель привилегий. Традиционно eBPF-программы требовали CAP_SYS_ADMIN — очень широкую привилегию. Новые ядра ввели более гранулярные возможности: CAP_BPF, CAP_PERFMON. Тем не менее, каждый eBPF-инструмент — это код, работающий в ядре, и к его безопасности нужно относиться соответственно.

Совокупный оверхед. Несколько eBPF-инструментов на одном узле могут конкурировать за ресурсы. Cilium + Tetragon + Pixie + Parca — это уже ощутимая нагрузка. Современные инструменты стараются разделять инфраструктуру через libbpf, но измерять производительность необходимо в каждом конкретном случае.

Сложность отладки. Когда eBPF-программа ведёт себя неожиданно, диагностика может быть нетривиальной. bpftool становится обязательным инструментом в арсенале: просмотр загруженных программ (bpftool prog list), карт и событий — базовый навык для эксплуатации eBPF в продакшене.

Заключение

eBPF — это не очередная технология из мира Linux. Это фундаментальный сдвиг в том, как мы строим и эксплуатируем инфраструктуру. Впервые за десятилетия разработчики получили безопасный и производительный способ программировать ядро, не рискуя стабильностью системы.

Если контейнеры определили Cloud Native 1.0, а Kubernetes — Cloud Native 1.5, то eBPF становится основой Cloud Native 2.0. Он уже работает внутри Cilium, Falco, Pixie, Hubble, Tetragon и десятков других инструментов. И самое важное — вам не нужно писать eBPF-программы, чтобы пользоваться их преимуществами. Достаточно знать, какие инструменты на него полагаются, и осознанно выбирать их для своих задач.

Начните с малого: поставьте Cilium в тестовый кластер Kubernetes, посмотрите на данные Hubble, попробуйте bpftrace для трассировки проблемного приложения. eBPF — одна из тех технологий, которая окупается с первого дня использования.

Часто задаваемые вопросы

Нужно ли писать код на C, чтобы использовать eBPF?

Нет. Большинство инженеров never пишут eBPF-программы напрямую. Они используют готовые инструменты: Cilium, Pixie, Falco, Tetragon. Понимание архитектуры eBPF помогает выбирать и настраивать эти инструменты, но код писать не требуется.

Какая минимальная версия ядра нужна для eBPF?

Базовые возможности доступны с ядра 4.8 (2015 год). Для CO-RE и современных инструментов рекомендуется ядро 5.4 и выше. Для продвинутых возможностей (кольцевые буферы, новые типы программ) — 5.8+.

Не замедляет ли eBPF работу системы?

В правильно настроенной конфигурации оверхед eBPF минимален. JIT-компиляция превращает байт-код в нативные инструкции, а XDP-программы обрабатывают пакеты ещё до входа в сетевой стек. При использовании нескольких инструментов на одном узле необходимо измерять совокупное влияние.

Чем eBPF отличается от модулей ядра?

eBPF-программы проходят верификацию перед загрузкой (проверка на безопасное завершение, корректность указателей, отсутствие бесконечных циклов), используют ограниченный набор API через helper-функции и не могут обрушить ядро. Модули ядра не имеют этих ограничений, но и не имеют этих гарантий.

Где можно узнать больше?

Официальный сайт фонда eBPF (ebpf.foundation), документация Cilium (docs.cilium.io), репозиторий cilium/ebpf для Go-разработчиков. Для практического знакомства — bpftrace и примеры из BCC (BPF Compiler Collection).