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

eBPF для трассировки прикладного стека: от сокетов до приложения

Практическое руководство по сквозной трассировке через eBPF: от сетевого стека до прикладного кода с корреляцией по trace_id. Обновлено 2026.

eBPF для трассировки прикладного стека: от сокетов до приложения

Аннотация

Практическое руководство по сквозной трассировке запросов через eBPF: от поступления пакета в сетевой стек до возврата из прикладного кода. Покрываем трассировку TCP-соединений, системных вызовов, TLS-библиотек и фреймворков (Go, Java, Python) с корреляцией по trace_id.

1. Архитектура сквозной трассировки

Компоненты:

  • kprobes/uprobes: точки входа в ядро и пользовательское пространство.
  • tracepoints: стабильные события ядра (netif_receive_skb, tcp_v4_rcv).
  • USDT: статические точки трассировки в приложениях.
  • BPF maps: передача контекста между программами, агрегация.
  • Коррелятор: сквозной идентификатор (trace_id) через все уровни.

Ключевые метрики:

  • Время в ядре (qdisc → tcp_v4_rcv → recvmsg)
  • Время в TLS (SSL_read/SSL_write)
  • Время в рантайме (Go: runtime.schedule; Java: GC pauses)
  • Время в приложении (handler/endpoint)

2. Инструментарий

  • bpftrace для быстрого прототипирования.
  • libbpf/CO-RE для production-обвязки.
  • BCC для сложных сценариев.
  • OpenTelemetry eBPF для интеграции с APM.

3. Практические примеры

3.1 Трассировка TCP-рукопожатия и задержек

uprobe:/lib/x86_64-linux-gnu/libssl.so:SSL_read {
  @start[tid] = nsecs;
}
uretprobe:/lib/x86_64-linux-gnu/libssl.so:SSL_read /@start[tid]/ {
  $latency = nsecs - @start[tid];
  @ssl_read_latency = hist($latency);
  delete(@start[tid]);
}

3.2 Корреляция с прикладным кодом (Go)

tracepoint:syscalls:sys_enter_write /comm == "server"/ {
  @write_start[tid] = nsecs;
}
tracepoint:sys_calls:sys_exit_write /@write_start[tid]/ {
  $latency = nsecs - @write_start[tid];
  @write_latency = hist($latency);
  delete(@write_start[tid]);
}

3.3 USDT в Nginx

usdt:/usr/sbin/nginx:request__start {
  @req_start[arg0] = nsecs;
}
usdt:/usr/sbin/nginx:request__done /@req_start[arg0]/ {
  $latency = nsecs - @req_start[arg0];
  @nginx_request_latency = hist($latency);
  delete(@req_start[arg0]);
}

4. Корреляция по trace_id

  • Inject trace_id в HTTP-заголовки (traceparent/tracestate).
  • Передача через контекст корутин/goroutines.
  • BPF-программа читает trace_id из сокета/памяти.
  • Все события пишутся в единую систему с общим ключом.

5. Производительность и оверхед

  • kprobes: 100–500 нс на событие.
  • uprobes: 500–2000 нс.
  • USDT: 100–300 нс.
  • Maps: минимальные при правильной схеме ключей.

Рекомендации:

  • Фильтрация на ранней стадии (comm, pid, fd).
  • Агрегация в ядре, отправка батчами.
  • Sampling для высоконагруженных путей.

6. Сценарии использования

  • Поиск хвостов распределения (P99/P999 latency).
  • Диагностика взаимоблокировок в Go runtime.
  • Анализ влияния GC в Java на latency.
  • Поиск утечек файловых дескрипторов.
  • Трассировка падения соединений (RST, timeouts).

Обновления 2026

  • Интеграция с OpenTelemetry eBPF auto-instrumentation.
  • Поддержка USDT в Go 1.22+ без перекомпиляции.
  • BPF CO-RE стабилен для production на ядрах 5.15+.
  • Рекомендация: использовать sampling 1:100 для P999 анализа.

Заключение

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