Трассировка и профайлинг в Linux с помощью bcc/eBPF
18 октября 2017
Недавно у меня наконец-то дошли руки поиграться с eBPF. Если вдруг вы все пропустили, eBPF — это очередная реализация идеи «а давайте сделаем DTrace для Linux». Другой реализацией этой идеи является SystemTap. Только SystemTap трудно устанавливается, пользоваться им не очень удобно, и его страшно запускать на проде. В отличие от него, eBPF прямо-таки похож на нормальный инструмент. Давайте же поскорее с ним познакомимся!
Немного матчасти
Итак, что такое eBPF, и что такое bcc?
Аббревиатура eBPF расшифровывается как Enhanced Berkeley Packet Filter. Название возникло по историческим причинам, поскольку проект зародился, как попытка портировать BPF (эта штука, умеющая, например, фильтровать пакеты для libpcap / tcpdump прямо в ядре) из FreeBSD под Linux. Сейчас eBPF, несмотря на название, умеет намного больше, чем фильтровать пакеты (потому он и Enhanced) и представляет собой механизм ядра, предоставляющий возможности трассировки и профайлинга как самого ядра, так и пользовательских приложений. Иногда eBPF называют просто BPF’ом, что создает некоторую путаницу.
Тулкит для создания программ, использующих возможности eBPF, называется bcc (иногда также пишут прописными буквами, BCC). Название расшифровывается, как BPF Compiler Collection. При написании кода с использованием bcc в качестве языка программирования используется смесь Python и C. Также в bcc входит большой набор готовых утилит для профайлинга программ и мониторинга системы. Бытует мнение, что эти готовые программки даже полезнее возможности писать свои собственные.
Установка bcc/eBPF
Для использования bcc/eBPF вам понадобится ядро Linux версии 4.1 или старше. Если быть точнее, лучше использовать версию не младше 4.9, иначе часть клевых возможностей eBPF будет вам недоступна. Согласно файлу INSTALL.md из репозитория bcc, ядро должно быть собрано со следующими флагами:
CONFIG_BPF_SYSCALL=y
CONFIG_NET_CLS_BPF=m
CONFIG_NET_ACT_BPF=m
CONFIG_BPF_JIT=y
CONFIG_HAVE_BPF_JIT=y
CONFIG_BPF_EVENTS=y
Проверить их наличие можно командой:
Лично я тестировал bcc/eBPF на двух системах — Arch Linux с ядром 4.13.3 и Ubuntu 16.04 с ядром 4.10.0. В обеих системах ядро по умолчанию имеет нужные нам флаги.
Установка в Ubuntu 16.04 происходит так. Создаем /etc/apt/sources.list.d/iovisor.list:
'xenial xenial-nightly main" > /etc/apt/sources.list.d/iovisor.list'
Затем говорим:
sudo apt-get install bcc bcc-tools python-bcc
В Arch Linux установить bcc/eBPF можно так:
Про установку пакетов из AUR в этой операционной системе, а также про утилиту yaourt, ранее рассказывалось в заметке Управление пакетами в Arch Linux с помощью ABS и pacman.
Некоторые утилиты из bcc-tools
Скрипты из пакета bcc-tools лежат в каталоге /usr/share/bcc/tools/. Рассмотрим некоторые из них.
Для отображения запускаемых программ и их аргументов есть утилита execsnoop. Ее вывод выглядит как-то так:
sshd 7871 813 0 /usr/sbin/sshd -D -R
sh 7873 7871 0
uname 7878 7875 0 /bin/uname -m
cut 7885 7883 0 /usr/bin/cut -d -f4
lsb_release 7884 7883 0 /usr/bin/lsb_release -sd
...
Если хочется узнать, какие процессы какие файлы открывают, воспользуйтесь opensnoop:
3450 i3status 4 0 /etc/mtab
3450 i3status 4 0 /proc/loadavg
754 psql 3 0 /usr/lib/locale/locale-archive
754 psql 3 0 /usr/share/locale/locale.alias
...
Посмотреть топ процессов по создаваемому ими дисковому I/O позволяет утилита biotop:
3388 dmcrypt_write W 7 0 loop0 281 3524.0 0.66
3360 loop0 W 8 0 sda 76 3524.0 0.19
378 jbd2/sda2-8 W 8 0 sda 113 676.0 0.05
3360 loop0 R 8 0 sda 10 40.0 0.14
...
С помощью tcplife можно в реальном времени посмотреть, кто сожрал весь сетевой трафик:
3506 Chrome 10.128.0.6 33110 87.250.247.182 443 1 18 69347.77
3506 Chrome 10.128.0.6 37576 213.180.204.161 443 1 10 68529.41
3506 Chrome 10.128.0.6 37568 213.180.204.161 443 1 10 68529.48
3506 Chrome 10.128.0.6 42526 95.101.241.61 443 0 3 22147.14
3506 Chrome 10.128.0.6 42522 95.101.241.61 443 0 3 22147.23
3506 Chrome 10.128.0.6 56444 178.154.131.216 443 2 11 82244.22
3506 Chrome 10.128.0.6 56460 178.154.131.216 443 2 8 82157.24
3506 Chrome 10.128.0.6 56442 178.154.131.216 443 3 329 82290.86
...
Аналогичная утилита, но показывающая не лог реального времени, а топ процессов, называется tcptop:
18023 openvpn 192.168.27.173:59342 46.101.213.42:443 14 17
3534 Chrome 10.128.0.6:38314 104.244.42.1:443 5 10
3534 Chrome 10.128.0.6:35538 192.229.233.50:443 5 0
3534 Chrome 10.128.0.6:38336 104.244.42.1:443 5 5
...
Еще из особо интересных утилит я бы лично отметил cpudist, runqlat, filetop, biolatency, gethostlatency, а также совершенно выносящие мозг trace и argdist.
Всего на момент написания этих строк в bcc-tools входило около 100 утилит. Само собой разумеется, рассмотреть их все в рамках одного поста не представляется возможным. К счастью, описание каждой из утилит и поддерживаемых ею флагов можно прочитать, запустив утилиту с флагом -h
. Кроме того, в подкаталоге /doc/ вы найдете примеры использования каждой из утилит.
Строим флеймграфы!
Какая же заметка про DTrace или его аналог может обойтись без флеймграфов? В случае с eBPF флеймграф для процесса с заданным pid строится как-то так:
git clone https://github.com/brendangregg/FlameGraph
./FlameGraph/flamegraph.pl --colors hot < out.profile > out.svg
Примерный вид результата:
Здесь я профилировал PostgreSQL, выполняющий VACUUM FULL
.
Иногда нужно замерить время, которое процесс проводит «off-cpu», к примеру, в sleep или ожидая ввода-вывода. В этом случае вам могут помочь утилиты offcputime и offwaketime. Они имеют такие же флаги, что и утилита profile.
Заключение
Написание собственных утилит с помощью bcc, увы, выходит за рамки данной заметки. Соответствующий туториал вы найдете в репозитории bcc. Кроме того, учиться можно по коду утилит из пакета bcc-tools.
Ссылки по теме:
- Страничка, посвященная eBPF, на сайте Брендана Грегга;
- Статьи об eBPF на сайте ferrisellis.com — первая и вторая;
- Уже упомянутый репозиторий bcc на GitHub;
- Трассировщик ply использует eBPF и позволяет писать пробы на языке, напоминающем язык SystemTap;
- Netflix Vector — система мониторинга с веб-интерфейсом, использующая, помимо прочего, и возможности eBPF;
Мои личные впечатления от bcc/eBPF исключительно положительные. Просто установил и пользуешься, ни о чем особо думать не нужно, и при этом не страшно запускать в продакшене. Правда, у меня возникли кое-какие проблемы с утилитой ext4slower. Кроме того, оказалось, что некоторые утилиты (например, dbstat и dbslower) требуют установки dtrace4linux для сборки профилируемых приложений с поддержкой USDT, что несколько неудобно. Но учитывая относительную молодость технологии, некоторые шероховатости были вполне ожидаемы. Я довольно уверен, что названные проблемы со временем поправят.
Дополнение: Основы трассировки с помощью bpftrace
Метки: Linux, Оптимизация, Отладка.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.