Две новые технологии, BTF и CO-RE, прокладывают для BPF путь в отрасль с миллиардным оборотом. Уже сейчас существует множество BPF (eBPF) стартапов, создающих сетевые продукты, продукты для обеспечения безопасности и производительности (и многое другое вне нашего поля зрения), но требующих от клиентов установки зависимостей LLVM, Clang и заголовков библиотек ядра (kernel-headers), которые могут занимать в памяти более 100 мегабайт, что негативно сказывается на скорости распространения технологии. BTF и CO-RE устраняют эти зависимости во время выполнения, делая BPF не только более практичным для встроенных сред Linux, но и для повсеместного внедрения.
Эти технологии представляют из себя:
BTF: BPF Type Format, который предоставляет структурную информацию в целях устранения необходимости в заголовках библиотек ядра и Clang.
CO-RE: BPF Compile-Once Run-Everywhere, который делает скомпилированный байт-код BPF перемещаемым, избавляя от необходимости перекомпиляции с помощью LLVM.
Clang и LLVM по-прежнему требуются для компиляции, но в результате получается облегченный ELF-бинарник, который включает предварительно скомпилированный BPF байт-код и может выполняться везде. В проекте BCC есть такой набор, называемый libbpf tools. Для примера я перенес свой инструмент opensnoop(8):
# ./opensnoop
PID COMM FD ERR PATH
27974 opensnoop 28 0 /etc/localtime
1482 redis-server 7 0 /proc/1482/stat
1657 atlas-system-ag 3 0 /proc/stat
[…]
Это opensnoop(8) – ELF-бинарник, который не использует libLLVM или libclang:
# file opensnoop
opensnoop: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=b4b5320c39e5ad2313e8a371baf5e8241bb4e4ed, with debuginfo, not stripped
# ldd opensnoop
linux-vdso.so.1 (0x00007ffddf3f1000)
libelf.so.1 => /usr/lib/x8664-linux-gnu/libelf.so.1 (0x00007f9fb7836000)
libz.so.1 => /lib/x8664-linux-gnu/libz.so.1 (0x00007f9fb7619000)
libc.so.6 => /lib/x8664-linux-gnu/libc.so.6 (0x00007f9fb7228000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9fb7c76000)
# ls -lh opensnoop opensnoop.stripped
-rwxr-xr-x 1 root root 645K Feb 28 23:18 opensnoop
-rwxr-xr-x 1 root root 151K Feb 28 23:33 opensnoop.stripped
… и stripped занимает всего 151 Кбайт.
А теперь представьте BPF-продукт: вместо того, чтобы требовать от клиентов установки различных тяжелых (и хрупких) зависимостей, BPF-агент теперь может быть одним крошечным бинарником, который работает с любым ядром, имеющим BTF.
Дело не только в том, чтобы сохранить BPF байт-код в ELF и затем отправить его в любое другое ядро. Многие BPF-программы используют структуры ядра (kernel structs), которые могут изменяться от одной версии ядра к другой. Ваш BPF байт-код может по-прежнему выполняться на разных ядрах, но он может считывать неправильные смещения структуры и выводить бессмыслицу! opensnoop(8) не просматривает структуры ядра, поскольку он использует стабильные точки трассировки и их аргументы, но многие другие инструменты это делают.
Это проблема перемещения, и BTF и CO-RE решают эту проблему для BPF-бинарников. BTF предоставляет информацию о типе, чтобы смещения структуры и другие детали могли быть запрошены по мере необходимости, а CO-RE записывает, какие части BPF-программы необходимо переписать и как. Разработчик CO-RE Андрей Накрыко написал длинные статьи, в которых это объясняется более подробно: «Переносимость BPF» и «информация о типах CO-RE BTF».
Эти новые BPF-бинарники возможны только в том случае, если установлен этот параметр конфигурации ядра. Он добавляет около 1,5 Мбайт к образу ядра (это крошечный размер по сравнению с DWARF debuginfo, который может составлять сотни Мбайт). В Ubuntu 20.10 этот параметр конфигурации уже установлен по умолчанию, и все остальные дистрибутивы должны следовать ему. Примечание для разработчиков дистрибутива: он требует pahole >= 1.16.
Для работы со средствами оценки производительности BPF (BPF performance tools) вы должны начать с запуска инструментария BCC и bpftrace, а затем написания bpftrace-кода. Инструментарий BCC в конечном итоге следует переключить с Python на libbpf C – на работе это не отразится. Средства оценки производительности кода в BCC Python теперь считаются устаревшими, по этому мы переходим к libbpf C с BTF и CO-RE (хотя у нас все еще остается некоторая работа с библиотеками, например, поддержка USDT, поэтому Python-версии будут нам необходимы еще некоторое время). Обратите внимание, что существуют другие варианты использования BCC, которые могут продолжать использовать Python-интерфейс; сомейнтейнер BPF Алексей Старовойтов и я кратко обсудили это на iovisor-dev.
Моя книга BPF Performance Tools посвящена запуску инструментария BCC и написанию bpftrace-кода, и эта часть не меняется. Однако примеры программирования на Python в Приложении C теперь считаются устаревшими. Приносим извинения за неудобства. К счастью, это всего лишь 15 страниц из 880-страничной книги.
А что насчет bpftrace? Он поддерживает BTF, и в будущем мы планируем также уменьшить объем его установки (в настоящее время он может достигать 29 Мбайт, и мы убеждены, что этот показатель может быть намного меньше). Учитывая средний размер программы libbpf в 229 Кбайт (на основе текущих инструментов libbpf, stripped) и средний размер программы bpftrace в 1 Кбайт (инструменты из моей книги), большая коллекция инструментов bpftrace плюс бинарник bpftrace может потребовать меньший объем установки, чем эквивалент в libbpf. Кроме того, версии bpftrace можно изменять на лету. libbpf лучше подходит для более сложных и серьезных инструментов, которым нужны настраиваемые аргументы и библиотеки.
Как видно из скриншотов, будущее инструментов оценки производительности BPF таково:
# ls /usr/share/bcc/tools /usr/sbin/*.bt
argdist drsnoop mdflush pythongc tclobjnew
bashreadline execsnoop memleak pythonstat tclstat
[…]
/usr/sbin/bashreadline.bt /usr/sbin/mdflush.bt /usr/sbin/tcpaccept.bt
/usr/sbin/biolatency.bt /usr/sbin/naptime.bt /usr/sbin/tcpconnect.bt
[…]
… и таково:
# bpftrace -e 'BEGIN { printf("Hello, World!n"); }'
Attaching 1 probe…
Hello, World!
^C
… а не таково:
#!/usr/bin/python
from bcc import BPF
from bcc.utils import printb
prog = """
int hello(void *ctx) {
bpftrace_printk("Hello, World!n");
return 0;
}
"""
[…]
Спасибо Yonghong Song (Facebook) за руководство в разработке BTF, Andrii Nakryiko (Facebook) за руководство разработке CO-RE и всем, кто участвует в этом проекте.
Перевод статьи подготовлен в преддверии старта курса “Нагрузочное тестирование”. В связи с этим приглашаем всех желающих посетить бесплатный демо-урок по теме: “Проведение нагрузочного тестирования в средстве Performance center”.
VK объявляет о приобретении 40% компании Intickets.ru (Интикетс). Это облачный сервис для контроля и управления продажей билетов на мероприятия. Сумма…
OpenAI готовится запустить собственную поисковую систему на базе ChatGPT. Информацию об этом публикуют западные издания. Ожидается, что новый поисковик может…
Центр управления связью общего пользования (ЦМУ ССОП) Роскомнадзора рекомендовал компаниям из реестра провайдеров ограничить доступ поисковых ботов к информации на российских сайтах.…
Apple возобновила переговоры с OpenAI о возможности внедрения ИИ-технологий в iOS 18, на основе данной операционной системы будут работать новые…
Конкурсный управляющий российской «дочки» Google подготовил 23 иска к участникам рекламного рынка. Общая сумма исков составляет 16 млрд рублей –…
Google завершил обновление основного алгоритма March 2024 Core Update. Раскатка обновлений была завершена 19 апреля, но сообщил об этом поисковик…