Блог "Дети ОИТа"
/поиск

eBPF для наблюдаемости Linux: архитектура, практические примеры и типовые ошибки

Практическое руководство по применению eBPF для сбора метрик, трассировки и профилирования в production. Архитектура, безопасность, BCC/libbpf/bpftrace, готовые сценарии и антипаттерны.

eBPF для наблюдаемости Linux: архитектура, практические примеры и типовые ошибки

Аннотация

Практическое руководство по применению eBPF для сбора метрик, трассировки и профилирования в production. Покрываем архитектуру, безопасность, экосистему (BCC, libbpf, bpftrace), готовые сценарии и антипаттерны. Статья ориентирована на SRE, DevOps и системных администраторов.

1. Что такое eBPF и почему это важно

Extended Berkeley Packet Filter (eBPF) — это виртуальная машина в ядре Linux, позволяющая безопасно выполнять программы в ответ на события ядра (kprobes/uprobes, tracepoints, XDP, TC, сокеты). Ключевые свойства:

  • Выполняется в ядре без модулей — верификатор гарантирует безопасность.
  • Почти нулевые накладные расходы при правильной фильтрации.
  • Доступ к контексту: пакеты, системные вызовы, аргументы функций, стек вызовов.

Типичные задачи: latency breakdown, частота системных вызовов, распределение размеров запросов, ошибки errno, анализ TCP-retransmits, профилирование CPU по стекам.

2. Архитектура и безопасность

Компоненты:

  • Загрузчик: bpftool, libbpf, Clang/LLVM для компиляции.
  • Хранилище карт: BPF maps (hash, lru_hash, array, percpu, ringbuf, perf_event).
  • Точки крепления: kprobes/uprobes, tracepoints, XDP/TC, cgroup-bind, sockops.
  • Привилегии: CAP_BPF/CAP_PERFMON/CAP_NET_ADMIN в зависимости от типа программы; рекомендуется least-privilege.

Риски и контрмеры:

  • Переполнение карт: лимиты max_entries, ротация, LRU.
  • Утечки данных: минимизируйте payload, используйте redaction PII.
  • Совместимость ядра: проверяйте BTF, CO-RE (BPF Compile Once — Run Everywhere).
  • Живучесть: systemd unit для автозагрузки, проверка статуса, health-check.

3. Экосистема и инструменты

  • BCC: набор Python/CLI инструментов для прототипирования.
  • libbpf/CO-RE: продакшн-подход, переносимость.
  • bpftrace: однострочники и быстрые проверки.
  • Beyla, Parca, Pixie, Falco: готовые платформы на базе eBPF.
  • Метрики: экспортер в Prometheus через гистограммы/счётчики в maps или userspace exporter.

4. Практические сценарии

4.1 Latency breakdown для конкретного PID

Цель: понять, где процесс проводит время (ядро/пользователь, I/O, блокировки).

Подход:

  • attach uprobe к целевому бинарнику на горячих функциях.
  • собирать интервалы в гистограмму (power-of-two buckets).
  • экспортировать в Prometheus.

Черновик кода (libbpf):

// pseudo-skeleton
SEC("uprobe/myapp:hot_func")
int BPF_UPROBE(hot_func_enter, struct pt_regs *ctx) {
    u64 ts = bpf_ktime_get_ns();
    u64 pid_tgid = bpf_get_current_pid_tgid();
    start.update(&pid_tgid, &ts);
    return 0;
}

SEC("uretprobe/myapp:hot_func")
int BPF_URETPROBE(hot_func_exit, struct pt_regs *ctx) {
    u64 *tsp = start.lookup(&bpf_get_current_pid_tgid());
    if (!tsp) return 0;
    u64 delta = bpf_ktime_get_ns() - *tsp;
    // histogram map update
    start.delete(&bpf_get_current_pid_tgid());
    return 0;
}

4.2 Анализ TCP retransmits и RTO по namespace

Цель: быстро находить «плохие» пути/узлы.

Подход:

  • tracepoint tcp/tcp_retransmit_skb
  • ключ: netns, dst, причина
  • метрики: счётчик, гистограмма RTO

4.3 Профилирование CPU по стекам (on-CPU)

Цель: найти горячие стеки без остановки сервиса.

Подход:

  • perf_event с частотой, stackid в map
  • flamegraph из userspace

5. Типовые ошибки и как их избежать

  • Игнорирование BTF/CO-RE: скрипты ломаются при обновлении ядра. Решение: libbpf + заголовки BTF.
  • Слишком широкие kprobes: оверхед. Решение: фильтрация по PID/cgroup, выбор tracepoints.
  • Нет лимитов на maps: OOM. Решение: max_entries, LRU, мониторинг заполнения.
  • Сбор PII в traces: регуляторные риски. Решение: redaction, sampling.
  • Отсутствие health-check: «умерший» агент не заметен. Решение: Prometheus target, liveness probe.

6. Деплой и эксплуатация

  • Упаковка: systemd unit, статический бинарник, ConfigMap с параметрами.
  • Версионирование: семвер карт и сигнатур событий.
  • Наблюдаемость агента: метрики загрузчика, ошибки верификатора, дропы.
  • Rollout: canary на одном узле, сравнение latency/throughput.

7. Чек-лист внедрения

  • Определены KPI: что измеряем и пороги.
  • Выбран стек: libbpf vs BCC vs bpftrace.
  • Проверена поддержка BTF на целевых ядрах.
  • Настроены лимиты maps и retention.
  • Реализован exporter метрик.
  • Health-check и алерты.
  • Политика sampling и redaction.
  • Runbooks для типовых инцидентов.

Заключение

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