В этой статье мы разберём, как запустить лёгкий eBPF DaemonSet, который собирает информацию о TCP-задержках между сервисами, количестве повторных передач и профилях системных вызовов внутри подов Kubernetes. Никаких изменений в приложениях, никаких Envoy sidecar-ов и никакого взрывного роста бюджета.
Проблема observability с sidecar-ами
Многие команды сразу выбирают Envoy или Istio, не оценив затраты. Sidecar-контейнер сервисной сетки добавляет 50–200 мс холодного старта, ~50 МБ памяти на под и нагрузку на CPU, которая растёт при горизонтальном масштабировании. Для стартапа с 40 микросервисами на среднем Kubernetes-кластере это уже существенная статья расходов.
eBPF полностью меняет подход.
Что такое eBPF и как он работает
eBPF (Extended Berkeley Packet Filter) — это программы, которые выполняются в ядре Linux в изолированной JIT-компилируемой виртуальной машине. Они подключаются к tracepoint, kprobes и uprobes, получая прямой доступ к сетевым событиям, решениям планировщика и системным вызовам — без какой-либо инструментации в пользовательском пространстве.
Для трассировки межсервисных задержек мы подключаемся к функциям ядра tcp_sendmsg и tcp_recvmsg и связываем временные метки через BPF-карты — разделяемые структуры памяти, доступные как из ядра, так и из пользовательского пространства.
Архитектура BPF-карт
BPF-карты типизированы, имеют ограниченный размер и управляются ядром. Для многосервисного Kubernetes-окружения хэш-карта с ключом (pid, container_id) позволяет связать задержку с конкретным подом без пересечения данных.
| Тип карты | Назначение | Сложность поиска |
|---|---|---|
| BPF_MAP_TYPE_HASH | Связывание PID и временной метки | O(1) в среднем |
| BPF_MAP_TYPE_PERF_EVENT_ARRAY | Потоковая передача событий в userspace | O(1) на CPU |
| BPF_MAP_TYPE_RINGBUF | Экспорт трасс с высокой пропускной способностью | Lock-free, меньше издержек |
| BPF_MAP_TYPE_LRU_HASH | Отслеживание соединений в масштабе | Автоудаление устаревших записей |
Для обнаружения TCP-ретрансмиссий подключаемся к tracepoint tcp_retransmit_skb и агрегируем счётчики по (src_ip, dst_ip, dport) в LRU-хэше. Так мы получаем сигнал на уровне сети без участия приложения.
CO-RE: переносимость между версиями ядра
Исторически главным барьером для внедрения eBPF была фрагментация версий ядра. CO-RE (Compile Once, Run Everywhere) с BTF (BPF Type Format) и libbpf решает эту проблему. eBPF-объектный файл содержит информацию о типах, а загрузчик подменяет смещения полей во время загрузки в соответствии с BTF работающего ядра.
Практический workflow: скомпилировать один раз в CI, упаковать .o файл в образ контейнера и загружать на ядрах от 5.4 до 6.x без перекомпиляции. Это делает eBPF пригодным для гетерогенных облачных сред, где версии ядер различаются между пулами узлов.
Интеграция с Grafana и Tempo
При ограниченном бюджете мы используем следующий пайплайн:
- eBPF-демон (Go + библиотека cilium/ebpf) читает события из ring buffer.
- OpenTelemetry Collector получает спаны по OTLP, батчирует и сжимает их.
- Grafana Tempo сохраняет трейсы в объектном хранилище (S3/GCS) — примерно $0.02/ГБ в месяц против $0.10–$0.30 в управляемых APM.
- Grafana отображает карты сервисов на основе данных трейсов — без Jaeger или Zipkin.
По сравнению с полной сеткой Istio этот стек работает как один DaemonSet-под на узел, потребляя ~30 МБ RAM и <0.5% CPU на ядро. Вы получаете 90% ценности observability при ~15% инфраструктурных затрат.
Сравнение подходов к observability
| Подход | Изменения кода | Потребление памяти | Видимость ядра | Сложность настройки |
|---|---|---|---|---|
| Envoy sidecar (Istio) | Нет | ~50 МБ/под | Только L7 | Высокая |
| Ручной SDK (OTel) | Да | Минимально | Только приложение | Средняя |
| eBPF DaemonSet | Нет | ~30 МБ/узел | L3–L7 + syscalls | Средняя |
| Без инструментации | Нет | Нет | Нет | Н/Д |
Подводные камни
Ключи BPF-карт. Используйте (netns_ino, pid) как ключ, а не просто PID. В общем ядре Kubernetes PID могут пересекаться между контейнерами. Пространство имён по inode сетевого namespace предотвращает утечку данных между подами.
Маршрутизируйте через OTel Collector. Не отправляйте eBPF-события напрямую в Tempo. Collector даёт батчинг, повторные попытки и возможность сменить бэкенд без изменения BPF-кода.
BTF должен быть включён. Проверьте командой ls /sys/kernel/btf/vmlinux. Если файла нет, CO-RE не сработает.
Начинайте с cilium/ebpf на Go. У этой библиотеки лучшая поддержка CO-RE, активное сопровождение и чистый API для работы с картами и ring buffer.
Заключение
eBPF даёт observability на уровне ядра — TCP-задержки, ретрансмиссии, профили syscall — при доле памяти и CPU, потребляемых сервисной сеткой. Сочетание CO-RE, BPF ring buffer и лёгкого пайплайна OTel → Tempo → Grafana готово к production и работает на стартап-инфраструктуре.
Istio стоит использовать только тогда, когда действительно нужно управление трафиком. Для чистой observability eBPF — лучший выбор по умолчанию.
Комментарии (0)
Войдите, чтобы комментировать.
Пока нет комментариев. Будьте первым.