eBPF: программы внутри ядра Linux без перекомпиляции

В главе «Телеметрия» мы говорили про метрики, логи и трейсы — и про то, что обычно для их сбора нужно добавлять код в приложение или ставить агенты, которые умеют «подсматривать» за работой системы. А что если бы можно было подключаться к самому ядру Linux и видеть, что происходит внутри, без изменений в коде и без перекомпиляции?

Это и есть eBPF — технология, которая в последние годы перевернула подход к observability, networking и security в Linux-системах.

Что такое eBPF простыми словами

Представьте себе Linux как огромный завод с миллионом конвейеров. Обычно чтобы понять, что происходит на конвейере, нужно: - Поставить камеры (добавить код в приложение) - Поставить датчики (поставить агенты, которые читают системные вызовы) - Каждый раз, когда меняется конвейер, перенастраивать всё

eBPF — это способ запускать маленькие безопасные программы прямо внутри ядра, на уровне этих конвейеров. Эти программы могут: - Читать, что происходит с сетевыми пакетами - Следить за файловой системой - Профилировать CPU - Перехватывать системные вызовы - Принимать решения — блокировать или пропускать пакет

Без модификации ядра, без перекомпиляции, без перезагрузки. Программа загружается в ядро через специальный API, проверяется верификатором на безопасность и исполняется при каждом событии, которое нас интересует.

Почему это важно для SRE

До eBPF у SRE было два варианта получить глубокое observability: 1. Инструментировать код — добавлять метрики/трейсы в приложение. Работает, но требует изменений в коде, релизов, и не работает для legacy-систем. 2. Использовать сэмплинг и экспортёры — Prometheus exporter, Node Exporter, sidecar-контейнеры. Работает, но видит только верхний слой.

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

Три основные области применения

1. Observability — наблюдаемость

Pixie (от New Relic) — профилирование и трейсы прямо из ядра для приложений на любом языке. Не нужно ставить SDK в каждое приложение — Pixie видит HTTP-запросы, запросы к базам, gRPC-вызовы автоматически через eBPF.

Parca — непрерывное профилирование CPU и памяти. С eBPF можно снимать flamegraph-ы с любого процесса без перезапуска и без инструментации.

BCC и bpftrace — набор утилит и DSL для написания собственных eBPF-программ. Например, можно одной командой посмотреть, какие процессы больше всего читают с диска:

bpftrace -e 'tracepoint:block:block_rq_issue { @[comm] = count(); }'

2. Networking — сеть

Cilium — это сетевой плагин для Kubernetes, который заменяет kube-proxy и iptables на eBPF. Результат: - Быстрее маршрутизация (особенно в больших кластерах с тысячами сервисов) - Встроенный service mesh без sidecar-ов (Cilium Service Mesh) - Лучшая видимость сетевого трафика - Network policies с детальной гранулярностью

Calico тоже использует eBPF для ускорения.

3. Security — безопасность

Tetragon (от Cilium/Aqua) — runtime security: видит системные вызовы и может блокировать подозрительные действия в реальном времени. Например: «процесс X пытается читать файл Y — заблокировать».

Falco — детектор аномалий. С помощью eBPF ловит необычные действия: процесс читает /etc/shadow, кто-то делает exec из tmp, кто-то делает исходящий DNS-запрос на подозрительный домен.

Tracee — ещё один инструмент от Aqua для runtime-безопасности на базе eBPF.

Как это работает технически

Чтобы не уходить в дебри, вот общая схема:

  1. Пользовательская программа пишется на C, Rust или ограниченном подмножестве C (для bpftrace — DSL)
  2. Программа загружается в ядро через bpf() системный вызов
  3. Верификатор в ядре проверяет программу: что она не зацикливается, не обращается к невалидной памяти, завершается гарантированно
  4. Программа прикрепляется к hook-точке (точка входа в сетевой стек, tracepoint, kprobe, uprobe)
  5. При каждом событии ядро запускает eBPF-программу
  6. Программа пишет результат в map — структуру данных «ключ-значение» в ядре, которую можно прочитать из userspace
[Приложение]
       ↓ системные вызовы
[Linux Kernel]
       ↓ hook-точка (kprobe, tracepoint)
[eBPF программа]
       ↓ пишет в map
[Userspace агент]
       ↓ читает map, обрабатывает, отправляет в backend
[Prometheus, Jaeger, S3, ...]

Главное ограничение — eBPF-программа должна завершаться. Верификатор гарантирует, что она не зациклится. Поэтому eBPF не подходит для сложной бизнес-логики, но идеален для наблюдения и быстрых решений «пропустить/заблокировать».

Практический пример: посмотреть HTTP-запросы без кода в приложении

С Pixie в Kubernetes-кластере одна команда покажет все HTTP-запросы во всех подах:

px http_data

Результат — таблица с method, URL, status_code, latency. Без единого изменения в коде приложений. Pixie использует eBPF-программы, которые прикрепляются к сетевым syscall-ам и читают HTTP-пакеты на лету.

Аналогично с bpftrace можно одной командой увидеть все DNS-запросы:

bpftrace -e 'tracepoint:net:net_dev_xmit { @[args->name] = count(); }'

Где это работает, а где нет

Работает: - Linux-ядра 4.19+ (для продвинутых фич — 5.x+) - Kubernetes 1.18+ (для Cilium) - Контейнеры без привилегированных namespace

Не работает: - Windows (там свой аналог, но зрелость ниже) - macOS (частичная поддержка через Virtualization framework) - Очень старые ядра (RHEL 7, Ubuntu 16.04) - Окружения, где eBPF заблокирован из соображений безопасности (некоторые managed Kubernetes-провайдеры)

Сравнение с традиционными подходами

Задача Традиционный подход С eBPF
Сбор метрик из приложения Добавить Prometheus client в код Pixie/Parca собирают автоматически
Service mesh в Kubernetes Sidecar-контейнер в каждом поде (Envoy, 50-100 MB памяти) Cilium Service Mesh без sidecar
Runtime security Auditd, syslog Tetragon, Falco — в реальном времени с блокировкой
Профилирование CPU perf, async-profiler (нужно знать, что искать) Parca — непрерывное профилирование всех процессов
Сетевые политики в K8s CNI с iptables (медленно на больших кластерах) Cilium на eBPF

Когда НЕ нужен eBPF

  • Если приложение уже хорошо инструментировано и observability работает — eBPF добавит сложности без выгоды
  • Если команда не готова разбираться с новой технологией — кривая обучения у eBPF крутая
  • Если стек не Linux — для Windows и macOS другие инструменты
  • Для небольших проектов — overhead от eBPF-агентов может быть больше пользы
  • Когда метрик верхнего уровня достаточно — eBPF оправдан, когда нужна глубина

Резюме

eBPF — это технология запуска безопасных программ внутри ядра Linux без модификации самого ядра. Для SRE это три большие области: observability (Pixie, Parca), networking (Cilium как замена kube-proxy и service mesh), security (Tetragon, Falco для runtime-детекта).

Не нужно бросаться переписывать весь стек. Начните с одного: поставьте Pixie в dev-кластер, посмотрите как она показывает HTTP-запросы без кода в приложениях. Если команде зашло — Cilium в production. Главное помнить: eBPF не заменяет инструментацию приложений, а дополняет её на уровне, который раньше был недоступен без модификации кода.

См. также: «Service Mesh», «Телеметрия», «DevSecOps и SRE», «Chaos Engineering».